Skip to main content
An on-premise installation is configured in three files, each holding a different kind of value. Knowing which file owns what is most of the work.
All three are per-deployment and all three stay out of the repository. A values file committed to the repo becomes the file the next installation is accidentally run against.

The Vault

Copy ansible/group_vars/all/vault.example.yml to vault.yml, fill it in, and encrypt it. Every top-level key becomes one Kubernetes Secret in the release namespace.

root-services

database

Five connection strings, one per database. In Scenario C the installer creates all five on the host it provisions; in Scenario B you point them at your own endpoint. Scenario C also needs vault_postgres_passwords, a separate top-level block naming one password per role:
The installer applies exactly these with ALTER ROLE; it never generates its own. Re-running an install therefore re-asserts what your vault says rather than rotating anything behind your back, which is also what makes rotating a password a matter of editing the vault and re-running.

aws-bucket

Object storage. In an on-premise installation this is MinIO running in your cluster, not AWS — the key names are historical.
BUCKET_NAME is one of the keys the value gate does not type-check. A CHANGE_ME left here passes the gate, and the installation then fails at the MinIO Ingress precondition — which is loud and early, but only because that check was added for exactly this.

control-plane

The rest

Social sign-in is optional and per-provider. A deployment that configures none simply does not offer social sign-in — the providers are registered only when configured, rather than half-registered with empty credentials.
container-config.port must stay 3333. It looks like a free choice and it is not.Twenty-one of the twenty-two workloads take their listening port from this one value, via BACKEND_PORT, and the chart pins containerPort: 3333 against it. Change it and every one of them listens where its own Service does not point.What makes it expensive is how it fails. Most of those workloads have no liveness or readiness probe, so they come up, report Running, and serve nothing. Only one workload is instrumented, and it is the only reason the misconfiguration is visible at all — it fails its probe, restarts, and keeps restarting. We hit this with a value of 3000: twenty workloads looked healthy, one restarted 231 times, and the install timed out waiting for a deployment that could never become ready.The shipped vault.example.yml already has the right value. Copy it rather than retyping it.

Who owns the blockchain endpoint

The blockchain values can be yours or ROOTKey’s, and it is a deliberate choice rather than a default: Either way the wallet that signs stays inside your deployment: the RPC endpoint is where transactions are sent, not who signs them. Decide this during scoping, because it changes both the egress allowlist and who is responsible for the node’s availability.

Three top-level keys, outside rootkey_secret_data

Everything above lives under rootkey_secret_data and becomes a Kubernetes Secret. These do not — they sit at the top level of the same file and are read by the installer itself. Miss them and the install fails while pulling the first image.
These are the registry credentials from your delivery record. They become the rootkey-registry pull secret that every workload references.
vault_image_pull_registry ships with the right value and is the one of the three that looks filled in and is not checked as carefully as the other two. Leave it alone — a changed hostname produces a pull secret registered for a registry nobody pulls from, and the resulting ImagePullBackOff names the image rather than the secret.
And, in Scenario C only, where the installer creates the PostgreSQL databases itself:
One per line, never reused across deployments — openssl rand -base64 24. In this mode the installer builds each connection string from the node address plus these, which is why the database block above may keep its placeholders.

Licensing

The licence is issued by the Control Plane at rootkey_control_plane_url, and is fetched and renewed over that link.
Offline licensing — in development. Licence delivery for deployments with no Control Plane link is being built, with its own issuing and verification path.In the meantime there is nothing to configure for it in the vault.If your deployment is air-gapped, raise licensing with ROOTKey during scoping. It is a conversation to have before the install rather than after, and we will tell you where the offline path stands for your timeline.

The Helm Values File

Copy helm/values-onprem.example.yaml. Everything below is per-deployment.

Images

Every one of the 22 workloads needs a real repository and tag. The tag is the released commit SHA of that service, which ROOTKey publishes with each release.
The value gate rejects <commit-sha>, registry.example.com and CHANGE_ME in any image field.

The file base URL

This is where a browser fetches a stored file from. It reaches every workload that declares the variable.
Getting this wrong is the single most common way an installation “succeeds” and is unusable. Every pod is Ready, Helm reports success, users register, files upload and anchor — and then no avatar, logo, file link or compliance report opens, with nothing in any log, because the URL is only ever dereferenced by the user’s browser and never reaches the cluster.
Three rules:
  1. The host must be the same as the platform frontend Ingress host, and the same as rootkey_public_host.
  2. The path must be /files.
  3. Do not include the bucket name. The MinIO Ingress prepends it from the vault.

Ingress

The TLS Secret must already exist in the namespace. There is no ACME issuer.

Resources

The CPU and memory limits shipped in the chart are sized for the multi-tenant cloud, where a tight per-pod limit stops one customer starving another. An on-premise box is the opposite: it is dedicated to one client, and the same limit becomes a brake with no beneficiary.
This is measured, not estimated. On an eight-core box at 16% utilisation, a service limited to 200m accumulated 84 throttling events and 4.69 seconds of throttled time during a 3-second test, with 6.7 cores idle beside it. The visible symptom is file creation timing out after five seconds on a machine that looks unloaded.
Raise the limits in your values file. The example file ships with values already raised for a dedicated host and explains each one.

The Inventory

ansible/inventory/hosts.ini — the target, plus variables that belong to the deployment rather than to Helm.
rootkey_deployment_tenancy has no default, on purpose, and the deploy stage asserts it. An install without it stops with a message naming the variable, rather than guessing.There is no safe default because both values are wrong for somebody and neither failure announces itself. A direct client left on multi-tenant never gets the licence’s plan materialised, so registration falls through to a local path and the deployment appears to work until somebody looks at what plan the users are on.If you are unsure which you are, it is in your contract — ask before installing rather than picking one.
Values set here win over ansible/group_vars/all/main.yml, which ships with rootkey_public_host empty. That file is shared and versioned; the inventory is yours.

Deployment-Wide Variables

Set in ansible/group_vars/all/main.yml, or overridden per deployment with -e KEY=VALUE.
→ Next: Verification