Skip to main content

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]:
rootkey_public_host must be the same hostname you set on the platform Ingress in the values file, and must match the host in PUBLIC_FILE_BASE_URL. The installer compares all three and refuses to deploy if they disagree — because a mismatch produces a working application where every file returns 404, with nothing naming the cause.
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:
The gate type-checks only the keys the application parses — control-plane.deployment_id must be a UUID, and every *Url key must be an absolute URL. A CHANGE_ME left on BUCKET_NAME or an HMAC secret passes the gate and fails later, far from its cause. Fill in everything.
5

Create your values file

Copy the example and edit your copy:
Three things must be set:
  1. Every image repository and tag — the registry ROOTKey gave you and the released commit SHA of each service. The gate rejects the shipped placeholders.
  2. The platform hostname, on the platform-frontend Ingress.
  3. PUBLIC_FILE_BASE_URL, under global.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 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:
A Secret in the wrong namespace is invisible to the Ingress, and the failure looks like a certificate problem rather than a placement one.
7

Run the installation

For an air-gapped host, add --airgap true to load images from the bundle instead of pulling them.
The --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.
For a first install, running it in phases is much easier to diagnose than one long run. Use --tags to stop after each stage: --tags preflight, then --tags k3s, then --tags secrets, and so on. For an upgrade, run the whole thing — two of the stages are idempotent seeds that must not be forgotten.
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 jobbucket 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 already deployed, --atomic is 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