Restoring a backup
Lantern’s worker dumps the whole database every night at 03:00 household time, and when an admin taps Settings > Backups > Back up now, into backups/ in the data directory (./data/backups with docker-compose.yml, the data volume on Arcane). The migrate role also dumps it before every update (pre-migrate-*.dump). Dumps are kept for 14 days (APP_BACKUP_RETENTION_DAYS); the newest is always kept. Each is a pg_dump custom-format file holding the whole database: the household, logins, calendars, events, lists, recipes, and settings. Photo files are not in it: recipe photos, the photo library’s copies from Immich, and members’ and routines’ pictures live in photos/ in the data directory (./data/photos), so back up the whole data directory, not only the dumps, and restore photos/ with the database (step 3b).
A restore replaces the database with the dump. Everything after the dump is lost, and everyone is signed out if their session is newer than it.
1. Choose the dump
Section titled “1. Choose the dump”ls -l ./data/backups/lantern-2026-10-17T07-00-00Z.dump was made at that UTC time; pre-migrate-20261017T070000Z.dump just before an update. To undo an update, use the pre-migrate dump from just before it, with the image version that was running before (see docs/runbooks/rollback.md).
2. Stop Lantern, keep the database running
Section titled “2. Stop Lantern, keep the database running”docker compose stop web worker3. Replace the database with the dump
Section titled “3. Replace the database with the dump”The tools are in the Lantern image and the database container. With docker-compose.yml and the default names (POSTGRES_DB=lantern, POSTGRES_USER=lantern; use yours from .env):
# Copy the dump into the database container.docker compose cp ./data/backups/lantern-2026-10-17T07-00-00Z.dump postgres:/tmp/restore.dump
# Empty the database, then restore into it.docker compose exec postgres dropdb --username=lantern --force lanterndocker compose exec postgres createdb --username=lantern --owner=lantern lanterndocker compose exec postgres pg_restore --username=lantern --dbname=lantern --no-owner --no-privileges --exit-on-error /tmp/restore.dumpdocker compose exec postgres rm /tmp/restore.dump--exit-on-error stops at the first problem instead of leaving a half-restored database; if it stops, read the message, fix it, and run the three database commands again.
3b. Restore the photos
Section titled “3b. Restore the photos”The database’s photo rows name files in photos/. Put back the photos/ folder from the same backup of the data directory, so the files match the rows:
rm -rf ./data/photos && cp -a /path/to/backup/data/photos ./data/photosA photo whose files are missing shows as a placeholder and is left out of Export everything; nothing else breaks. Files with no row are never served, and can be deleted.
4. Start Lantern
Section titled “4. Start Lantern”docker compose up -dThe migrate role runs first: it backs up the restored database and applies any migrations the dump predates, so a dump from an older version restores into a newer one. Check /healthz and sign in.
Checking a dump without touching the live database
Section titled “Checking a dump without touching the live database”Restore it into a scratch database instead (step 3 with lantern_check in place of lantern, skipping dropdb), look around with psql, then dropdb lantern_check. CI does this on every pull request: apps/worker/src/jobs/backup.int.test.ts runs the backup job, restores its dump into a fresh database, and compares the rows.