Sync the self-hosting stack

This commit is contained in:
2026-08-27 14:42:54 +02:00
parent fa19933a32
commit aa1dfb5b02
3 changed files with 114 additions and 11 deletions
+81
View File
@@ -9,6 +9,87 @@ 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-08-27 — The console container listens on 8080 and runs unprivileged `web 0.120.0`
**Check your port mapping before you pull.** The web container used to listen on **80** and now
listens on **8080**, because binding a port below 1024 needs root and the container no longer runs
as root. The compose file in this repository is already updated — `${JARVIS_PORT:-8080}:8080` — so
if you use it unchanged there is nothing to do. If you wrote your own mapping, or your reverse proxy
targets the container port directly rather than the published one, change `:80` to `:8080`.
Nothing else about how you reach it changes: same URL, same paths, same TLS terminator in front.
**The container's upstream is configurable.** `JARVIS_API_UPSTREAM` and `JARVIS_DNS_RESOLVER` now
say where the API is and who resolves that name; they default to what compose has always used, so an
unchanged stack behaves identically. They exist for anybody running these images somewhere the name
`api` and Docker's own DNS do not mean anything.
**A terminal no longer opens a second shell when your connection drops.** Reconnecting used to
silently start a fresh login on the machine — a new session, a new audit entry, a new recording —
underneath a window still showing the old scrollback. It now tells you the connection was lost and
offers to open a new session, which is a decision rather than something that happened to you.
**A part of the console that fails to load after an upgrade now says so.** The interface ships as
content-hashed files that are replaced on every upgrade, so a tab left open from before can reach
for something the server no longer has — which used to be a blank panel and a line in the browser
console. It now raises the same notice an update raises, with words, and offers the reload that
fixes it.
## 2026-08-27 — An upgrade refuses to drop a column instead of doing it `api 0.93.0`
**The one to read.** Until now, every boot ran the schema sync with `--accept-data-loss`, so an
upgrade that needed to remove a column simply removed it. That was survivable while one container
was the whole deployment and is the wrong default for anything else — and it meant a destructive
schema change happened with nobody having decided anything.
It now **refuses**, prints which columns or tables it would have dropped, and stops. Nothing is
altered and the api does not start. If those drops are what you want, set
`SCHEMA_ACCEPT_DATA_LOSS=true` in `.env` for that one upgrade and put it back afterwards. Take a
dump first either way: there is still no migration history, so pulling an older image does not put
the schema back.
The schema phase is also its own entrypoint now (`migrate.sh`) rather than part of the api's boot.
On compose nothing changes — the api still runs it, because one container is the whole deployment —
and it takes a database lock while it works, so `--scale api=2` waits rather than races.
**Two health endpoints, for anything watching this instance.** `/api/health/live` says only that the
process is running, and `/api/health/ready` answers 503 when Postgres **or Redis** is unreachable.
`/api/health` is unchanged, including its 200-while-degraded behaviour, so whatever you already
point at it keeps working.
**Two tabs no longer sign you out of everything.** Both tabs share one session cookie, so both
refreshing at the same moment looked exactly like a stolen cookie being replayed, and the protection
against that revoked every session you had. Concurrent refreshes are now told apart from a replay by
how long ago the token was rotated. A genuine replay still revokes the family, which is what it is
for.
**An enrolment token's use limit is now actually a limit.** Two machines running the same install
command in the same second could both enrol on a token that permitted one — an Ansible play across a
fleet does exactly that. The check and the increment are one operation now.
**A terminal transcript survives the process being killed.** Output used to live only in memory until
the session ended, so an out-of-memory kill or a host losing power took the whole recording of a root
shell with it. It is written down every few seconds now, and a session that ended that way hands back
what was captured, clearly marked as stopping early. A session with no transcript at all also says
which of the three reasons applies rather than guessing — recording was off, retention has passed, or
it was lost — because telling an auditor a recording was never made when it was made and lost is the
answer that stops them looking.
**A restart no longer writes an ending into a session that is still open.** Starting up used to close
every terminal session row it found, on the reasoning that a row with no ending belongs to a process
that died. With one container that was true. It is now scoped to the process's own sessions.
**The api container runs as a non-root user.** Nothing you do changes; it matters if you run these
images under a policy that refuses root containers.
**Optional: `VAULT_KEY_CREATED_AT`.** Only needed where the vault key file is rewritten by your
platform rather than sitting still in a volume — on compose it is inferred correctly from the file
and you can ignore this. See `.env.example` for what it decides.
**And the reason for most of the above: more than one api replica is now possible.** It is not yet
supported, and this compose file still runs one. Nobody has served real traffic on more than one, so
if you are considering it, read the note in the README first.
## 2026-08-25 — A run gets 200 tool rounds instead of 50 `api 0.92.0`
**If the assistant has been stopping mid-investigation with "the results above were not analysed",