Files
coder/q5vault/operations/install-upgrade.md

5.2 KiB

title, description, source, reviewed
title description source reviewed
⬆️ Install, upgrade, backup Bring-up, status, logs, the pinned-image upgrade procedure, and the postgres backup and restore commands for the Coder stack in /home/loca/dev/coder. verified deployment on the loca operator host, 2026-08-19 2026-08-19

⬆️ Install, upgrade, backup

🔑 Ground rules

  • every docker command needs sudo -n; user loca is not in the docker group, which is intentional because docker group membership grants root-level privileges on the host
  • always run compose from the project root so the project name, .env and volume scoping resolve: cd /home/loca/dev/coder
  • .env holds CODER_PG_PASSWORD at mode 600 and is git-ignored; never echo it, copy it into a template, or paste it into a ticket
  • the deployed version is pinned twice on purpose: the image tag in docker-compose.yml and the plain-text pin in config/runtime-version.txt (currently v2.35.3). Both change together or neither changes

🚀 Bring-up

cd /home/loca/dev/coder
sudo -n docker compose up -d
sudo -n docker compose ps
curl -sf http://127.0.0.1:52226/healthz
  • database starts first and coder waits on its healthcheck (pg_isready -U coder -d coder), so a cold start can take a few seconds before /healthz answers
  • expected steady state: container coder running, container coder-database running and healthy, one published socket 127.0.0.1:52226
  • full proof sequence: operations/verification

📋 Status, logs, stop

cd /home/loca/dev/coder
sudo -n docker compose ps                  # both containers, database health
sudo -n docker compose logs -f coder       # server log stream
sudo -n docker compose logs --tail 200 database
sudo -n docker compose restart coder       # server only, database untouched
sudo -n docker compose stop                # keep containers, stop processes
sudo -n docker compose down                # remove containers, keep named volumes
  • down never removes coder_pgdata or coder_home; only an explicit down -v would, and that destroys every user, template and workspace record
  • restarting coder alone is safe and is the normal way to pick up an environment change in docker-compose.yml

⬆️ Upgrade the pinned image

Upstream states plainly that Coder does not support rollbacks, so the database snapshot is step one, not an optional extra.

cd /home/loca/dev/coder

# 1. snapshot the database first
sudo -n docker compose exec -T database pg_dump -U coder coder | gzip > /home/loca/dev/coder/backup-$(date +%F).sql.gz

# 2. edit the tag in docker-compose.yml, for example ghcr.io/coder/coder:v2.36.0
#    and write the same value into config/runtime-version.txt

# 3. pull and recreate only the server
sudo -n docker compose pull coder
sudo -n docker compose up -d coder

# 4. verify the running build matches the new pin
curl -sf http://127.0.0.1:52226/api/v2/buildinfo
curl -sf http://127.0.0.1:52226/healthz
curl -sSI https://code.loca.zone/
  • upstream's docker-compose upgrade path is exactly pull then up -d for the coder service; the database service is left alone unless the postgres major version itself is being changed
  • buildinfo is the authority on what is actually running: it reports the semantic version plus commit, the advertised dashboard_url, and whether telemetry is enabled
  • if buildinfo still shows the old version, the tag edit did not land or pull fetched a cached digest; re-check docker-compose.yml before restarting anything else
  • a postgres major-version bump is a separate operation: dump with the old image, down, change the image, bring up a fresh volume, restore the dump

💾 Backup and restore

# backup
cd /home/loca/dev/coder && sudo -n docker compose exec -T database pg_dump -U coder coder | gzip > /home/loca/dev/coder/backup-$(date +%F).sql.gz

# restore
gunzip -c /home/loca/dev/coder/backup-2026-08-19.sql.gz | sudo -n docker compose exec -T database psql -U coder -d coder
  • -T is required; without it compose allocates a TTY and the dump stream is corrupted by terminal translation
  • the dump carries everything Coder persists: users, templates, template versions, workspace records and Terraform state
  • restore into a running database that is otherwise idle; stop the coder service first with sudo -n docker compose stop coder so no writes race the restore, then start it again
  • keep at least the snapshot taken immediately before the last upgrade; store it outside the repo tree if it must be retained long-term

🔁 If an upgrade goes wrong

  • there is no supported downgrade path, so recovery is: sudo -n docker compose stop coder, restore the pre-upgrade dump, set the old tag back in docker-compose.yml and config/runtime-version.txt, then sudo -n docker compose up -d coder
  • verify with buildinfo that the old version is live before letting any workspace agent reconnect
  • if only the proxy is broken, nothing about the image needs touching: sudo -n nginx -t and the debug order in operations/index cover that case

📚 Sources