From ef1b961d2d60d47a40fb1e24c2fabca5c1b2a3a7 Mon Sep 17 00:00:00 2001 From: Luxit Date: Sun, 27 Sep 2026 23:05:31 +0200 Subject: [PATCH] Sync the self-hosting stack --- CHANGELOG.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7471086..d212cdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,85 @@ one of them changed. An entry says which artefact and which version, so `web 0.1 Every version published to a channel appears here. Nothing is written from memory afterwards: a build cannot be published without its entry. +## 2026-09-27 — The install's last step no longer strands a first deployment `api 0.116.1` `web 0.141.2` + +**The symptom.** On a first installation the wizard could stop on its last step, the vault key +backup: the key was not shown, and the step still asked for its last eight characters. It happened +on the published Kubernetes stack. It had two independent causes. + +**A deployment finished the install for you.** The data repair that runs with every schema sync +marked an instance installed as soon as it had a platform administrator. That was meant for +instances installed before the wizard existed, but the wizard's own second step creates that +administrator. On Kubernetes the sync is the `jarvis-migrate` hook, which runs on every Argo CD sync, +image updates included; on compose it runs at each api start. So a deploy between the second step +and the last one marked a half-installed instance installed, and an installed instance no longer +shows its vault key. + +**The last step hid the key on Kubernetes.** It left out the "Show my vault key" button whenever the +key came from the environment, and said you already had it in your `.env`. On Kubernetes the key +always comes from the environment, from the `jarvis-generated` Secret the minting Job writes, and +nobody has seen it. The only command offered was a `docker compose` one. This cause alone was enough +to strand an operator, even when no deploy ran during the install. + +What changed: + +- The repair now marks only an instance whose administrator the install did not create, meaning + one with no `install.claim` entry in its audit trail, and only once that administrator is more + than fifteen minutes old. A sync in the middle of an install leaves it alone. Instances from before + the wizard are still recognised, and an instance already marked installed stays marked. An install + that finished and later lost its mark (an `install.complete` entry, or an unattended install) gets + it back, as it did before. +- The wizard writes the administrator and its `install.claim` entry together, so a sync can no + longer land between the two. If that entry cannot be written, the claim fails and nothing is + created; submit it again. +- The last step always offers the one-time reveal, which is audited, wherever the key comes from. +- The command for reading the key yourself matches the deployment, and prints the key on a line of + its own, so your prompt no longer sits against its last characters. On Kubernetes it is `kubectl` + on `jarvis-generated`, with your namespace filled in when the api can read it, plus the same on + `jarvis-secrets` if you set `VAULT_MASTER_KEY` there; it runs as is in PowerShell too. With the + published compose file it is `docker compose exec`. A refused reveal names the same command, the + checks step names the Secret on Kubernetes, and the claim step shows both published commands. +- The `.env` sentence is now only a hint beside the button, shown when the api itself receives + `VAULT_MASTER_KEY` in its environment outside Kubernetes. The published compose file never does + that: its `init` service copies a key you set in `.env` into the `jarvis_secrets` volume, so the + step shows the `docker compose exec` command instead. +- If the instance is already installed when the last step runs, the step says so, gives that + command, and lets you continue into Jarvis. You can type the key's last eight characters there to + check the copy you kept; that is optional. +- Reloading `/install` as the administrator of an instance that was marked installed before its + last step shows that same screen, instead of going straight into Jarvis. It stops once you have + checked your copy there, or if the key had already been shown to you. +- Finishing on an instance that turns out to be already installed still checks the eight + characters; it used to accept any eight. The api reports that the instance was already installed, + and the step continues into Jarvis as usual. On Kubernetes, a wrong answer points at + `jarvis-secrets` in case that is where your key is. +- The key is never revealed on an installed instance, even by an api pod that has not yet heard + that another one finished the install. + +**Stuck on that screen now?** You do not have to wait for this release. On the version you run +today, read the key with the command below and type its last eight characters on the last step. +That finishes the install, or is accepted if a deploy already marked the instance installed. Keep +the key somewhere that is neither the cluster nor next to your database dumps. + +```sh +kubectl -n jarvis get secret jarvis-generated -o go-template="{{.data.VAULT_MASTER_KEY | base64decode | println}}" +``` + +`jarvis` is the namespace in the published manifests; use yours if you changed it. Use +`jarvis-secrets` instead of `jarvis-generated` if you set `VAULT_MASTER_KEY` there yourself. On +compose it is `docker compose exec api sh -c "cat /var/lib/jarvis/secrets/vault-master-key; echo"`. + +After the upgrade, reload the install page, signed in as the administrator (signed out, you are +brought back to it after signing in): + +- If a deploy had already marked your instance installed, the page says so and shows the command + for your deployment. Back the key up, check it there if you like, and continue into Jarvis. +- Otherwise your instance is not installed yet, and the install resumes at its address step. Your + settings are saved; click through to the last step, which now shows the key. + +**Self-hosters:** api and web; publish the api first, since the web reads what it now reports about +where the key is. No schema change, no new environment variable, and nothing to run by hand. + ## 2026-09-27 — No notice under every picture in the viewer `web 0.141.1` **A picture opened in the viewer no longer carries a notice saying it is the copy that was sent.**