Update and migrate: Image rollback
Goal and result
Section titled “Goal and result”Return to the exact previous image and restore matching data whenever a schema or migration ran.
Applies to
Section titled “Applies to”Use the recorded previous digest with its matching PostgreSQL dump and /data archive. A channel switch is allowed only after release-note review and a matched backup.
DiscVault v26 stable
Section titled “DiscVault v26 stable”- DiscVault v26 stable ·
ghcr.io/helmerznl/discvault:latest - restore the matching data before starting the previous image
- PostgreSQL +
/data
DiscVault v26 beta
Section titled “DiscVault v26 beta”- DiscVault v26 beta ·
ghcr.io/helmerznl/discvault:beta - restore the matching data before starting the previous image
- PostgreSQL +
/data
Prerequisites
Section titled “Prerequisites”- matching backup set
- recorded immutable
PREVIOUS_IMAGE
Procedure
Section titled “Procedure”- Stop:
next-api+next-worker+next-mcp - Restore: matching
/dataarchive - Restore: matching PostgreSQL dump ·
pg_restore --exit-on-error - Start:
PREVIOUS_IMAGE→ API health → worker + MCP
Commands and settings
Section titled “Commands and settings”Both channels
Section titled “Both channels”set -euo pipefailBACKUP_ID=20260714T180000Zcd /opt/discvault. "/srv/backups/discvault-$BACKUP_ID.env"test -n "$PREVIOUS_IMAGE"export DISCVAULT_IMAGE="$PREVIOUS_IMAGE"docker pull "$DISCVAULT_IMAGE"ENV_FILE=/opt/discvault/.envENV_TMP="$(mktemp "$ENV_FILE.restore.XXXXXX")"trap 'rm -f "$ENV_TMP"' EXITawk -v image="$DISCVAULT_IMAGE" ' /^DISCVAULT_IMAGE=/ { print "DISCVAULT_IMAGE=" image; found=1; next } { print } END { if (!found) exit 42 }' "$ENV_FILE" > "$ENV_TMP"chmod 0600 "$ENV_TMP"docker compose --env-file .env -p discvault -f compose.yaml stop next-worker next-mcp next-apimv /srv/discvault "/srv/discvault.failed-$(date -u +%Y%m%dT%H%M%SZ)"tar --acls --xattrs -C /srv -xzf \ "/srv/backups/discvault-data-$BACKUP_ID.tgz"docker compose --env-file .env -p discvault -f compose.yaml up -d postgresdocker compose --env-file .env -p discvault -f compose.yaml exec -T postgres \ sh -c 'dropdb --if-exists --force -U "$POSTGRES_USER" "$POSTGRES_DB"'docker compose --env-file .env -p discvault -f compose.yaml exec -T postgres \ sh -c 'createdb -U "$POSTGRES_USER" "$POSTGRES_DB"'docker compose --env-file .env -p discvault -f compose.yaml exec -T postgres \ sh -c 'pg_restore --exit-on-error --no-owner -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \ < "/srv/backups/discvault-$BACKUP_ID.dump"docker compose --env-file .env -p discvault -f compose.yaml up -d --force-recreate next-apicurl --fail http://localhost:6080/api/next/healthdocker compose --env-file .env -p discvault -f compose.yaml \ up -d --force-recreate next-worker next-mcpdocker compose --env-file .env -p discvault -f compose.yaml psmv "$ENV_TMP" "$ENV_FILE"trap - EXITExpected result
Section titled “Expected result”The recorded previous image is running and the restored library passes health and data checks.
PREVIOUS_IMAGE·@sha256:- restore the matching data before starting the previous image
- library counts and sampled media match the selected backup
Safety and rollback
Section titled “Safety and rollback”Next step
Section titled “Next step”Update and migrate: DiscVault 26 migration
Source and status
Section titled “Source and status”helmerzNL/DiscVault@6d27c689ac21- Verified:
2026-07-14 - DiscVault Docs:
0.1.0
