Before You Start
Work through Requirements first. The installer validates most of it and refuses to run rather than failing halfway, but a missing certificate or an unopened firewall rule still costs you the slot. Everything below runs from your control machine — your laptop, a jump host, or a CI runner. It is not the target.The Value Gate
Before Ansible is invoked at all, the installer refuses to run a deploy while any of the following is true:There is no flag to skip the gate. It exists because each of these produces a failure that is either silent or destroys its own evidence.
Setup
1
Unpack the release bundle
ROOTKey delivers a release as a single archive. Unpack it somewhere you can write to on the control machine:The bundle carries the Helm charts, the Ansible roles, the installer, and — for an air-gapped install — every container image plus the k3s and Helm binaries.Verify it before trusting anything inside it.
sha256sum -c alone proves the archive
is internally consistent, not that it came from ROOTKey — only the signature does that:install.sh does not do this for you. Verification is a deliberate step you take before
unpacking, and nothing later in the install will fail if you skip it.See Trust and Verification for where the key comes from and what
to do when a check fails.2
Run the preflight, before touching anything
The preflight is read-only. It changes nothing on the target and is deliberately not blocked by the value gate, so you can run it before anything is filled in.It reports PASS, WARN or FAIL for CPU, RAM, disk, operating system, and the required ports. Resolve every FAIL before continuing. Treat a WARN on vCPUs as a FAIL if you can: four cores install, but throttle badly enough to time out file anchoring.
3
Fill in the inventory
Copy the example and edit your copy. The real file is git-ignored, so it never travels back into the repository.For Scenario C, one host with SSH details. For Scenario B,
ansible_connection=local and the kubeconfig passed on the command line.Then set the platform hostname in the same file, under [rootkey:vars]:4
Fill in the vault
Copy the example vault and fill in every value. See Configuration Reference for what each key is and where it comes from.Store the vault password in a file the installer can read, and keep that file out of version control:
5
Create your values file
Copy the example and edit your copy:Three things must be set:
- Every image
repositoryandtag— the registry ROOTKey gave you and the released commit SHA of each service. The gate rejects the shipped placeholders. - The platform hostname, on the
platform-frontendIngress. PUBLIC_FILE_BASE_URL, underglobal.envOverrides:
Do not append the bucket name to that URL. The MinIO Ingress prepends it from the vault, so the bucket name lives in exactly one place. Two copies drift, and the failure when they do is a 404 on every file.
6
Load the TLS certificate into the cluster
The installer consumes a Secret; it does not create one. Load your certificate for the platform hostname:The Secret name must match A Secret in the wrong namespace is invisible to the Ingress, and the failure looks like a certificate problem rather than a placement one.
ingress.tls[].secretName in your values file and rootkey_tls_secret_name in the inventory. rootkey-tls is the default both expect.The ordering, precisely. The namespace is created by the secrets stage (stage 3), and the certificate is not consumed until the Ingress is created in the deploy stage (stage 7). So you have two correct options:7
Run the installation
- Scenario C
- Scenario B
--airgap true to load images from the bundle instead of pulling them.--values flag is not optional in practice: without it the installer falls back to the shipped example, which is full of placeholders, and the gate refuses.The run executes ten stages in order — preflight, Kubernetes runtime, secrets, database, chart staging, in-cluster stateful services, the Data Plane itself, the plan seed, the contract seed, and host hardening.8
Watch for the lines that matter
Three messages tell you whether the parts that fail silently actually worked.
contract-seed — on a fresh install you want contratos semeados. On a re-install you want skip: já há contratos, which means the guard held. If you see skip: o fixture não veio no bundle, the platform will install cleanly and return 500 on the first file upload, with no cause in the gateway log.The bucket job — bucket ready: <name> (anonymous download enabled). If it says anonymous read NOT granted, stored files will return AccessDenied to every browser.The MinIO precondition — it runs before any Helm command in the stateful stage. If it fails, it names which of the three values is missing and nothing has been installed yet.What Runs, In Order
Re-running the Installation
Every stage is idempotent, and an upgrade is the same command as an install.- Helm uses
upgrade --install. On a release that is alreadydeployed,--atomicis on, so a failure rolls back rather than leaving the platform half-changed. On a first install it is deliberately off: a rollback there would delete the pods, logs and events that explain what went wrong. - PostgreSQL is rotation-safe. It reads the passwords from your vault and applies them; it never generates its own, so a re-run cannot orphan your credentials.
- The seeds check before they write. The contract seed skips with a message when contracts already exist rather than duplicating them.
→ Next: Configuration Reference · Verification

