- Dev Center
- Documentation
- Deployment
- Deploying diagnos-api
Deployment
Deploying diagnos-api
Deploy diagnos-api with Docker or Kubernetes: environment, mTLS material, OpenBao auto-unseal and locking keys in RAM.
English · Português (Brasil)
The API is a thin shell over the SDK. It needs three things: the service account token, a certificate pair to serve HTTPS, and the CA that signs the client certificates — mutual TLS is the only authentication it accepts, so a request without a valid client certificate never reaches application code. With OpenBao configured, a pod restart resumes the SDK session without a human approving again.
Environment#
| Variable | Required | Meaning |
|---|---|---|
DIAGNOS_API_TOKEN |
yes | Service account token (apikey-…). |
DIAGNOS_API_MTLS_CA_FILE |
yes | PEM bundle of the CA(s) allowed to sign client certificates. |
DIAGNOS_API_TLS_CERT_FILE / DIAGNOS_API_TLS_KEY_FILE |
yes | Server certificate and key (PEM). |
DIAGNOS_API_HOST / DIAGNOS_API_PORT |
no | Default 0.0.0.0 / 8443. |
DIAGNOS_API_ALLOWED_CLIENT_CN |
no | Comma-separated CNs; when set, only these client certificates pass. |
OPENBAO_*, DIAGNOS_VAULT_URL, DIAGNOS_MEMORY_LOCK, … |
no | Every SDK variable applies too — see Configuration. OPENBAO_TOKEN_FILE is how Compose (deploy/compose) and file-mounted Kubernetes Secrets hand over the OpenBao token without an environment value. |
Without OpenBao, the first start prints the approval link and code to the container log; a workspace admin approves once per process lifetime. Generating the certificates and calling the API: the REST API guide.
Kubernetes#
kubectl apply -k deploy/k8s # edit the Secret first
deploy/k8s ships a Deployment (1 replica — the SDK session is per process; scale with OpenBao and one service
account per replica if you need more), a ClusterIP Service on 8443, a Secret template and a ConfigMap. Client
certificates are the callers' responsibility; the CA bundle is mounted read-only.
Docker Compose#
deploy/compose is the fastest way to see the whole stack — OpenBao and diagnos-api — running together with
nothing pre-existing:
cd deploy/compose
cp .env.example .env # fill in DIAGNOS_API_TOKEN, then `diagnos status` for the two ids
# certs/ needs clients-ca.pem/server.pem/server-key.pem — see this file's own openssl recipe below
docker compose up
A one-shot openbao-bootstrap service initialises OpenBao (or resumes, on later runs), enables the KV v2 mount,
writes the scoped diagnos-sdk policy, and mints the token the API reads — diagnos-api only starts once that
finishes successfully. deploy/compose/README.md has the full walkthrough.
Warning
Staging only, read before using this. The default OPENBAO_SEAL=shamir keeps OpenBao's unseal keys sitting on
a local Docker volume so the bootstrap service can re-unseal on every restart without a human — a deliberate
convenience for a disposable environment, and a real widening of who can read every saved session if this
configuration ever runs anywhere that matters. deploy/compose/.env.example documents the aws/gcp/azure/
transit alternatives, sharing the exact same seal.hcl files as the Kubernetes overlays below.
OpenBao on Kubernetes#
deploy/k8s/openbao is a kustomize base for OpenBao itself (namespace openbao, a one-replica raft StatefulSet,
the ClusterIP Service the OPENBAO_ADDR above already assumes) — a separate concern from deploy/k8s (the API), so
a platform team can own it independently:
kubectl apply -k deploy/k8s/openbao # unseals manually (Shamir)
# or, with real auto-unseal:
kubectl apply -k deploy/k8s/autounseal/aws # aws | gcp | azure | transit | static | shamir
deploy/k8s/autounseal/<provider> overlays the base with the seal each KMS needs — every one verified field-by-field
against openbao.org's own docs, not remembered from HashiCorp Vault (the two have diverged):
| Provider | What it needs |
|---|---|
aws |
IRSA (eks.amazonaws.com/role-arn) + kms:Encrypt/Decrypt/DescribeKey on one key |
gcp |
Workload Identity (iam.gke.io/gcp-service-account) + roles/cloudkms.cryptoKeyEncrypterDecrypter |
azure |
Workload identity federation (azure.workload.identity/client-id) + Key Vault get/wrapKey/unwrapKey |
transit |
A token, scoped to encrypt/decrypt on one key, from another already-unsealed OpenBao/Vault |
static |
A 32-byte key you generate and hold — read that overlay's security warning first |
shamir |
Nothing — the fallback; manual bao operator unseal after every restart |
After the first kubectl apply, bootstrap OpenBao itself (kv-v2 mount, the diagnos-sdk policy, the token) by
running the same script the Compose bootstrap uses, inside the already-running pod:
deploy/k8s/openbao/bootstrap-configmap.yaml has the exact command and where the resulting token goes.
Memory locking#
The SDK calls mlock() on session keys and group DEKs so the kernel never pages them to swap —
docs/PROTOCOL.md's "never sends a key to the vault" guarantee would not mean much if the
key could still end up on a disk block. Three things have to line up for that call to succeed in a container:
CAP_IPC_LOCK—deploy/k8s/deployment.yaml'scapabilities.add: [IPC_LOCK]anddeploy/compose'scap_add: [IPC_LOCK]both grant it; the image itself carriescap_ipc_lockas a file capability so a non-root process can use it.RLIMIT_MEMLOCK— the default 64 KiB is not enough;deploy/compose'sulimits.memlock: { soft: -1, hard: -1 }removes the limit entirely (Kubernetes has no per-container ulimit field, which is exactly why the capability above matters more there).DIAGNOS_MEMORY_LOCK=require(commented out indeploy/k8s/configmap.yaml) — makes the process refuse to start ifmlockfails instead of silently continuing with swappable keys; uncomment it once the first two are confirmed working on your nodes.
Separately, DIAGNOS_HARDEN_PROCESS (default "1") disables core dumps and ptrace attach for the process — set
"0" only on a deployment you are actively debugging, and revert right after.
In this section
- diagnos-api · Docker Compose One docker compose up for OpenBao and diagnos-api: what the bootstrap does, how the token is handed over, and the staging-only caveats.
- OpenBao auto-unseal · AWS KMS Auto-unseal OpenBao for diagnos with AWS KMS: the key, minimal IAM permissions and an IRSA trust policy scoped to one ServiceAccount.
- OpenBao auto-unseal · GCP Cloud KMS Auto-unseal OpenBao for diagnos with Google Cloud KMS through Workload Identity and a single encrypter/decrypter role.
- OpenBao auto-unseal · Azure Key Vault Auto-unseal OpenBao for diagnos with Azure Key Vault through workload identity federation and get/wrapKey/unwrapKey only.
- OpenBao auto-unseal · Transit (another OpenBao/Vault) Auto-unseal OpenBao for diagnos with the Transit engine of another OpenBao or Vault, using a token scoped to one key.
- OpenBao auto-unseal · Static key Auto-unseal OpenBao for diagnos with a static 32-byte key you hold, and why that is the weakest of the seal options.
- OpenBao auto-unseal · Shamir (manual, the fallback) The Shamir fallback for OpenBao under diagnos: no KMS needed, a manual bao operator unseal after every restart.