From 78a3202305d4ae1c5106152522d6e9bdc84c3cd3 Mon Sep 17 00:00:00 2001 From: Antoine CAVELIER Date: Fri, 21 Aug 2026 11:48:47 +0200 Subject: [PATCH] Sync the self-hosting stack (8342e2e) --- .env.example | 21 ++++++++++++++++++--- README.md | 38 +++++++++++++++++++++++++++++--------- docker-compose.agent.yml | 2 +- docker-compose.yml | 13 +++++++++++-- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index a26cd7c..3398f3d 100644 --- a/.env.example +++ b/.env.example @@ -75,16 +75,31 @@ OPENAI_API_KEY= #OPENAI_THINKING_LEVEL=medium # --------------------------------------------------------------------------- -# Pinning (optional, recommended in production) +# Channels and pinning (optional, recommended in production) # --------------------------------------------------------------------------- -# Both services track `latest` unless you set these, so `docker compose pull && up -d` upgrades you. +# Every image tracks the `stable` channel unless you set these, so `docker compose pull && up -d` +# upgrades you to whatever has most recently been promoted. `stable` moves only after a build has +# run on the publisher's own instance; `dev` moves on every build and nothing has tried it yet. +# `latest` is a second name for `stable`, kept so nothing that already used it has to change. +# +# Which channel you are on is yours to state, because nothing in the image knows it — a channel is +# decided after a build and moves afterwards. Set it and the app shows it beside the version +# numbers; leave it empty if you pin below, because then you follow no channel. +#JARVIS_CHANNEL=stable + # Pinning makes an upgrade a decision instead of a side effect of pulling. The app reports its real -# version either way — `latest` is a second name on the same image, not a build that forgot its number. +# version either way — a channel tag is a second name on the same image, not a build that forgot +# its number. #JARVIS_IMAGE_API=git.luxit.be/luxit/jarvis-api:0.59.1 #JARVIS_IMAGE_WEB=git.luxit.be/luxit/jarvis-web:0.74.2 # Only read when the agent overlay is enabled, just below. Its version is the AGENT's, and moves # independently of the two above — a Jarvis release usually does not change the agent at all. +# +# PIN THIS ONE FIRST if you pin only one. The two above change what your own server runs; this one +# changes what runs on every machine you administer, and it applies itself without asking. An +# enrolled agent also refuses any version that is not strictly newer, so moving this back stops a +# rollout rather than reversing it on machines that already took the update. #JARVIS_IMAGE_AGENT=git.luxit.be/luxit/jarvis-agent-dist:0.20.0 # --------------------------------------------------------------------------- diff --git a/README.md b/README.md index 46a31be..3209587 100644 --- a/README.md +++ b/README.md @@ -44,17 +44,37 @@ Both are the kind that produce confusing symptoms rather than clean errors. docker compose pull && docker compose up -d ``` -That is the whole upgrade: both services track `latest`. Schema changes apply themselves when the api -starts, and the api and the web are versioned independently — their numbers are not meant to match, -because usually only one side changed. +That is the whole upgrade: every service tracks the **`stable`** channel by default. Schema changes +apply themselves when the api starts, and the api and the web are versioned independently — their +numbers are not meant to match, because usually only one side changed. -**`latest` does not mean the app forgets which build it is.** The tag is a second name on the same image -as the version tag, and the version is stamped into the image when it is built — so the footer in the -app and `/version.json` keep reporting the real number, whichever name you pulled it under. That is -what lets you tell somebody which build you are on when something goes wrong. +### Channels -Once you are in production, consider pinning: set `JARVIS_IMAGE_API` and `JARVIS_IMAGE_WEB` in `.env` -to explicit tags. It makes an upgrade a decision rather than a side effect of pulling. +| Channel | What it means | +| -------- | ---------------------------------------------------------------------------------- | +| `stable` | Promoted after running on the publisher's own instance. **The default, and what you want.** | +| `dev` | Every build, as soon as it is published. Nothing has tried it yet. | +| `latest` | A second name for `stable`, kept so nothing that already used it has to change. | + +A channel is a **pointer** and a version number is a **fact**. `0.78.2` means one specific set of +bytes for ever; `stable` means whichever set we currently stand behind, and it moves. A build only +reaches `stable` by being promoted — and promotion copies the manifest of an image that has already +been published and already run. It never rebuilds, so the bytes you receive are the same bytes that +were tested, not a fresh build of the same source. + +**Channels do not mean the app forgets which build it is.** The version is stamped into the image +when it is built, so the footer in the app, `/version.json` and the agent manifest keep reporting the +real number whichever name you pulled it under. That is what lets you tell somebody which build you +are on when something goes wrong. + +Once you are in production, consider pinning: set `JARVIS_IMAGE_API`, `JARVIS_IMAGE_WEB` and +`JARVIS_IMAGE_AGENT` in `.env` to explicit version tags. It makes an upgrade a decision rather than a +side effect of pulling. + +**Pin the agent one first if you pin only one.** The api and the web change what your own server +runs; the agent changes what runs on every machine you administer, and it applies itself without +asking. An enrolled agent also refuses any version that is not strictly newer, so moving that pin +back stops a rollout rather than reversing it on machines that already took the update. Take a database dump before an upgrade that moves the api's minor version: diff --git a/docker-compose.agent.yml b/docker-compose.agent.yml index 1dcefc4..3f7c7c8 100644 --- a/docker-compose.agent.yml +++ b/docker-compose.agent.yml @@ -19,7 +19,7 @@ services: # Runs once per `up`, copies its payload into the shared volume, exits. Not a server. agent-releases: - image: ${JARVIS_IMAGE_AGENT:-git.luxit.be/luxit/jarvis-agent-dist:latest} + image: ${JARVIS_IMAGE_AGENT:-git.luxit.be/luxit/jarvis-agent-dist:stable} # Explicit, because the default would be wrong the moment somebody copies this block: a # restarting one-shot is an infinite loop, and Compose's own default policy is already "no". restart: "no" diff --git a/docker-compose.yml b/docker-compose.yml index 80a4a82..e2f90bb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -51,7 +51,7 @@ services: retries: 10 api: - image: ${JARVIS_IMAGE_API:-git.luxit.be/luxit/jarvis-api:latest} + image: ${JARVIS_IMAGE_API:-git.luxit.be/luxit/jarvis-api:stable} restart: unless-stopped # The assistant runs long operations, and a deploy is the most common thing that interrupts one. # Given room to stop, the API aborts each loop, writes the partial answer with a note saying why @@ -103,6 +103,15 @@ services: # Required to create new organizations, users or agents. Without it an instance keeps running # everything it already has, creates nothing new, and contacts nobody. See the README. JARVIS_LICENSE_KEY: ${JARVIS_LICENSE_KEY:-} + # Which distribution channel this instance follows, shown to signed-in operators beside the + # version numbers. Set `JARVIS_CHANNEL=stable` (or `dev`) in .env if you track a channel; + # LEAVE IT EMPTY IF YOU PIN EXACT VERSIONS, because then you follow no channel — you follow a + # decision — and the footer shows nothing rather than a label that stopped being true. + # + # It is not baked into the image, and cannot be: a channel is decided after a build and moves + # afterwards, so the same image is `dev` one week and `stable` the next. Only you know which + # one you are on. + APP_CHANNEL: ${JARVIS_CHANNEL:-} AGENT_HEARTBEAT_INTERVAL_SEC: ${AGENT_HEARTBEAT_INTERVAL_SEC:-30} RUN_SHUTDOWN_GRACE_SEC: ${RUN_SHUTDOWN_GRACE_SEC:-25} @@ -124,7 +133,7 @@ services: start_period: 40s web: - image: ${JARVIS_IMAGE_WEB:-git.luxit.be/luxit/jarvis-web:latest} + image: ${JARVIS_IMAGE_WEB:-git.luxit.be/luxit/jarvis-web:stable} restart: unless-stopped depends_on: - api