Backups
What to back up
Section titled “What to back up”Three things, and together they are the whole install: .env, config/ and the pgdata volume.
| What | Where | Why |
|---|---|---|
| The database | the pgdata volume (the database) |
Habit ticks, work shifts, School ticks, Board layouts and the archives. Some of it exists nowhere else. |
config/ |
the install folder | Your settings. Small, easy to rebuild, but no reason to. |
.env |
the install folder | Your secrets. Back it up somewhere as private as the original, or not at all. |
What’s not worth backing up: Money and Listening store nothing in Atlas, and the weather archive can’t be refetched for past hours, but losing it costs only history.
Your Habits and Work rows, your School done-ticks and your Board layouts are the irreplaceable part: you are their only upstream.
Dump the database
Section titled “Dump the database”Keep dumps in a folder outside the repo, somewhere only you can read. They hold secrets (see below). Make it once:
mkdir -p ~/atlas-backups && chmod 700 ~/atlas-backupsThen, from the repo folder:
docker compose exec -T atlas-db pg_dump -U atlas -Fc atlas > ~/atlas-backups/atlas-$(date +%F).dumpUse your POSTGRES_USER and POSTGRES_DB if you changed them from atlas. The dump is consistent while Atlas is running; there’s no need to stop it.
A nightly cron line on the host does it unattended. Add it with crontab -e:
15 3 * * * cd /path/to/atlas && docker compose exec -T atlas-db pg_dump -U atlas -Fc atlas > ~/atlas-backups/atlas-$(date +\%F).dumpTwo cron traps:
- The
\%matters: cron treats a bare%as a newline. - Cron runs with a minimal
PATH(often just/usr/bin:/bin), which may not includedocker. Runcommand -v dockerand, if it’s somewhere else (Docker Desktop on macOS puts it in/usr/local/bin), add aPATH=...line above the job in your crontab that includes that folder.
Check your backup exists
Section titled “Check your backup exists”A cron job that fails does so silently on most hosts. After its first night, and now and then after that, check from the repo folder:
ls -lh ~/atlas-backups/docker compose exec -T atlas-db pg_restore --list < ~/atlas-backups/atlas-$(date +%F).dump | headToday’s file should be there and not tiny. An empty or few-byte file means pg_dump failed: the shell creates the file before the command runs. pg_restore --list should print a table of contents, not an error. If the file is missing or tiny, run the command part of the cron line (everything after 15 3 * * *) by hand and read what it says.
Restore
Section titled “Restore”Into a running stack, replacing what’s there:
docker compose stop atlas-api atlas-crondocker compose exec -T atlas-db pg_restore -U atlas -d atlas --clean --if-exists < ~/atlas-backups/atlas-2026-10-01.dumpdocker compose start atlas-api atlas-cronThis is for a dump made by the version you’re running. For a dump from an older version, follow Rolling back instead.
On a new machine: run the installer (or clone, for a source build), copy over config/ and .env, docker compose up -d atlas-db, restore as above, then docker compose up -d (docker compose up -d --build for a source build). For an installed Atlas, the restored .env pins the version the dump was made with.
Treat the dump as sensitive
Section titled “Treat the dump as sensitive”The dump contains your Google Health sign-in tokens (oauth_tokens) as well as your sleep and activity history. Store it like you store .env. If one leaks, press Disconnect on the Status screen, which revokes the token at Google, and connect again.
Removing everything
Section titled “Removing everything”docker compose down -v stops Atlas and deletes its database volume. Only do it on purpose, with a dump in hand.