Skip to content

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

CategoryPolicyCurrent examples
Hard-pinned — data-plane services where a minor version bump can corrupt or re-indexmajor + minor, bump deliberatelytraefik: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 imagesmajor-alpinepostgres: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)

bash
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=grafana

Safe upgrade procedure (profile)

bash
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-learning

Full-stack upgrade

Don't. Update one profile at a time so you can correlate any regression. If you must:

bash
make backup-now
make update              # pulls + recreates all profiles
make mem-check           # OOM risk after new images land

Breaking-change checklist

When a major version of a hard-pinned service is available:

  1. Read upstream release notes. Especially database compatibility and format migrations.
  2. Take a fresh offen backup (make backup-now) — verify the tarball in data/backups/.
  3. Stop the profile (make stop-profile p=<profile>), bump the pin in docker-compose.yml, restart.
  4. If something corrupts, restore from the backup tarball (stop profile, extract over data/<service>/, restart).
  5. 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-worker runs it. Watch worker logs.
  • If upgrade fails, rollback via the backup before the Authentik Postgres volume has re-migrated.

MIT License