Upgrade Runbook
Most images in docker-compose.yml use :latest. That's convenient but makes rollbacks harder. This doc states the pinning policy and the safe-bump workflow.
Pinning policy
| Category | Policy | Current examples |
|---|---|---|
| Hard-pinned — data-plane services where a minor version bump can corrupt or re-index | major + minor, bump deliberately | traefik:v3.4, grafana/loki:3.4.3, grafana/promtail:3.4.3, ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 |
| Minor-pinned — stable base images | major-alpine | postgres:16-alpine, redis:7-alpine, docker.io/valkey/valkey:8-alpine, nginx:alpine |
| Rolling — security-sensitive services or ones with a trusted release channel | :latest (updated by Dependabot alerts) | cloudflare/cloudflared:latest, ghcr.io/goauthentik/server:latest, grafana/grafana-oss:latest, prom/prometheus:latest, prom/node-exporter:latest, lscr.io/linuxserver/plex:latest, lscr.io/linuxserver/qbittorrent:latest, lscr.io/linuxserver/obsidian:latest, tailscale/tailscale:latest, crowdsecurity/crowdsec:latest, fbonalair/traefik-crowdsec-bouncer:latest, nextcloud:stable-apache, ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}, ghcr.io/gethomepage/homepage:latest, offen/docker-volume-backup:v2 |
Rule of thumb: anything with a persistent on-disk format (Postgres, Loki, Prometheus TSDB, Immich embeddings) gets a hard pin. Anything essentially stateless gets :latest.
Dependabot
.github/dependabot.yml watches Docker images in code/Dockerfile and npm deps in code/apps/package.json, both weekly. It does not watch docker-compose.yml — that would require a different ecosystem (see known_issues.md for automated compose bumping).
Safe upgrade procedure (single service)
cd ~/Desktop/hemanth/h5h/code
# 1. Run a backup first. This is the undo button.
make backup-now
# 2. Pull + recreate just that service.
make update-service s=grafana
# 3. Watch health.
docker compose -f docker/docker-compose.yml logs -f grafana
make health
# 4. If broken, pin to the previous tag in docker-compose.yml and redeploy:
# edit image line, then:
make update-service s=grafanaSafe upgrade procedure (profile)
make backup-now
make update-profile p=photos # pulls immich + ML + postgres + redis, recreates together
docker compose -f docker/docker-compose.yml logs -f immich-server immich-machine-learningFull-stack upgrade
Don't. Update one profile at a time so you can correlate any regression. If you must:
make backup-now
make update # pulls + recreates all profiles
make mem-check # OOM risk after new images landBreaking-change checklist
When a major version of a hard-pinned service is available:
- Read upstream release notes. Especially database compatibility and format migrations.
- Take a fresh offen backup (
make backup-now) — verify the tarball indata/backups/. - Stop the profile (
make stop-profile p=<profile>), bump the pin indocker-compose.yml, restart. - If something corrupts, restore from the backup tarball (stop profile, extract over
data/<service>/, restart). - Update service_catalog.md if the image tag changed — the generator picks it up automatically via
make gen-docs.
When Authentik itself is upgrading
Authentik is a hard dependency for everything behind forward-auth. During its upgrade, users will see 401s.
- Keep the upgrade window short; don't bundle it with other profile updates.
- If the post-upgrade schema needs a migration,
authentik-workerruns it. Watch worker logs. - If upgrade fails, rollback via the backup before the Authentik Postgres volume has re-migrated.