From 4560702550c1c4227e883521b920d58d650d1046 Mon Sep 17 00:00:00 2001 From: Joakim Persson Date: Wed, 22 Apr 2026 10:29:03 +0200 Subject: [PATCH] Document the upgrade-ritual for reconciling VM compose files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New releases may add named volumes or bind-mount lines to docker-compose.yml. The image can't update compose files on the VM — they're user-owned — so a plain 'docker compose pull && up -d' picks up the new image but silently misses new mount points. Example from v1.14.19c → v1.14.20: bash history persistence needs the devbox-shell-history named volume at /home/developer/.cache/bash. The v1.14.20 image is configured to write history there either way, but without the volume mount on the VM, writes land in the container's writable layer and vanish on every --force-recreate. Add a 'Upgrading an existing VM to a new release' subsection to deploy/README.md describing the backup → diff → merge → recreate ritual, so future upgrades don't quietly drop features the same way. --- deploy/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/deploy/README.md b/deploy/README.md index 9f3cc58..74ca340 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -198,6 +198,34 @@ After editing `docker-compose.yml` on the VM to uncomment the bind mounts you ne The script reads `docker-compose.yml` on the remote VM, detects which bind mounts are active, and syncs only those directories from your local machine. It also creates the remote directories if they don't exist. +### Upgrading an existing VM to a new release + +Each tagged release may add new named volumes or bind-mount lines to `docker-compose.yml`. Pulling a new image via `docker compose pull` grabs the new container behaviour, but compose files on the VM are user-owned and never touched by the image — you have to reconcile them yourself when upgrading across versions. + +**Symptom of a missed reconcile:** a new feature quietly doesn't work even though the image is correct. Example from v1.14.19c → v1.14.20: bash history persistence requires the `devbox-shell-history` named volume mounted at `/home/developer/.cache/bash`. The v1.14.20 image writes history to that path either way, but without the volume mount on the VM, writes land in the container's writable layer and vanish on every `--force-recreate`. + +**Upgrade ritual:** + +```bash +# On the VM, before recreating the container: +cd ~/opencode-devbox +cp docker-compose.yml docker-compose.yml.bak-$(date +%Y%m%d-%H%M%S) + +# Compare against the repo version to see what's new: +# (from your local checkout) +scp devbox-affection:~/opencode-devbox/docker-compose.yml /tmp/vm-compose.yml +diff -u /tmp/vm-compose.yml ~/src/src_local/opencode-devbox/docker-compose.yml +``` + +For each new `volumes:` entry or mount line in the repo version that isn't in your VM's file, add it manually — preserving any local customizations you've made (image variant, read/write flags on bind mounts, etc.). Then: + +```bash +docker compose config >/dev/null # verify YAML still parses +docker compose up -d --force-recreate +``` + +If you maintain the VM's compose file with no local changes, `scp` the repo version over wholesale. If you have customizations (the common case), do the diff-and-merge by hand. + ### Shell defaults inside the container The image ships baked `.bash_aliases` and `.inputrc` in `/etc/skel-devbox/` — quality-of-life defaults (prefix history search on Up/Down arrows, persistent history across container recreates via the `devbox-shell-history` named volume, `[devbox]` prompt marker, sensible aliases). On first container start the entrypoint copies them to `/home/developer/` **only if the target file does not already exist**.