Docs
Install

Kubernetes

Install 3AM in a Kubernetes cluster with the Helm chart.

The chart runs 3AM as a single-replica StatefulSet (the audit log has one writer) with a persistent volume, and an optional model Deployment that only 3AM can reach. It is hardened by default:

  • non-root (uid 65532), read-only root filesystem, all capabilities dropped, seccomp RuntimeDefault;
  • no service-account token mounted, and no injected service-link variables;
  • a NetworkPolicy that limits who can reach the console.

Tested on Kubernetes 1.34. Expected to work on 1.27+, including EKS, AKS, GKE and Rancher.

1. Make the images available

If your cluster can pull from the registry 3AM gave you access to, set image.repository to it in step 3, and add an imagePullSecrets entry if it needs credentials.

2. Create the namespace and secrets

kubectl create namespace bank-ops
# the licence, if you already have it (otherwise install it later in the console)
kubectl -n bank-ops create secret generic 3am-licence --from-file=licence.json
# your sealed packs, from the bundle
kubectl -n bank-ops create secret generic 3am-packs --from-file=3am-0.1.0/config/packs/

3. Install the chart

helm install 3am 3am-0.1.0/helm/3am-0.1.0.tgz -n bank-ops \
  --set image.repository=registry.bank.internal/3am/3am-core \
  --set licence.existingSecret=3am-licence \
  --set packs.existingSecret=3am-packs

Kubernetes names can't start with a digit, so resources are named threeam… (for a release called 3am).

4. Open the console and sign in

kubectl -n bank-ops port-forward svc/threeam 8700:8700
kubectl -n bank-ops get secret threeam-admin -o jsonpath='{.data.token}' | base64 -d; echo

Open http://localhost:8700 and sign in with the token. The chart generates it once and keeps it across upgrades. For a permanent address, enable the ingress (below).

5. Check the install

kubectl -n bank-ops get pods
kubectl -n bank-ops exec statefulset/threeam -- /opt/3am/3am-core preflight

Values

ValueDefaultPurpose
image.repository, image.tag, image.digestlocalhost/3am-core, 0.1.0, emptyWhere to pull 3AM from. Set digest to pin
imagePullSecrets[]Registry credentials
persistence.size, persistence.storageClass20Gi, cluster defaultThe data volume (audit log, incidents, index)
licence.existingSecret, licence.keyempty, licence.jsonA Secret with the licence. Empty: install it in the console
packs.existingSecretemptyA Secret with your sealed packs (*.3pk)
config.existingConfigMapemptyA ConfigMap with connectors.json and policy.json, if you manage config as code
secretMounts[]Secrets mounted at /etc/3am/secrets/<name>, referenced from connectors.json as {"file": "…"}
adminToken.existingSecretemptyYour own admin token (key token). Otherwise generated once and kept
ingestToken.existingSecretemptyYour own ingest token. Otherwise generated once and kept
model.enabled, model.profiletrue, cpuThe on-prem model for incident notes. gpu requests nvidia.com/gpu: 1
model.imagedocker.io/ollama/ollama:0.35.0The model runtime image
model.pullOnStarttruePulls the model on start. Air-gapped: set false and preload the model volume
service.type, service.portClusterIP, 8700The console service
ingress.enabled, ingress.className, ingress.host, ingress.tlsSecretoffA permanent address with TLS
networkPolicy.enabled, networkPolicy.allowFromNamespacestrue, []Who may reach the console (e.g. [ingress-nginx])
resources, nodeSelector, tolerationsrequests 250m / 512Mi, limit 2GiScheduling
pollSeconds15How often 3AM reads alerts

Example with an ingress and the GPU model:

helm upgrade --install 3am 3am-0.1.0/helm/3am-0.1.0.tgz -n bank-ops \
  --set ingress.enabled=true,ingress.className=nginx,ingress.host=3am.bank.internal,ingress.tlsSecret=3am-tls \
  --set networkPolicy.allowFromNamespaces='{ingress-nginx}' \
  --set model.profile=gpu

The install fingerprint on Kubernetes

The licence is tied to the cluster through the UID of its kube-system namespace. The console's setup screen shows it, or read it directly:

kubectl get namespace kube-system -o jsonpath='{.metadata.uid}'; echo

OpenShift

The chart runs 3AM as uid 65532. OpenShift's default restricted-v2 policy assigns a random uid instead, so allow the release's service account to run as a fixed non-root user:

oc adm policy add-scc-to-user nonroot-v2 -z default -n bank-ops

OpenShift is expected to work with this step but is not yet part of 3AM's certification runs.

Upgrades and removal

helm upgrade 3am 3am-0.2.0/helm/3am-0.2.0.tgz -n bank-ops --reuse-values
helm uninstall 3am -n bank-ops          # the data volume and the generated tokens are kept

On this page