Skip to content

Backups

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.

Keep dumps in a folder outside the repo, somewhere only you can read. They hold secrets (see below). Make it once:

Terminal window
mkdir -p ~/atlas-backups && chmod 700 ~/atlas-backups

Then, from the repo folder:

Terminal window
docker compose exec -T atlas-db pg_dump -U atlas -Fc atlas > ~/atlas-backups/atlas-$(date +%F).dump

Use 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:

Terminal window
15 3 * * * cd /path/to/atlas && docker compose exec -T atlas-db pg_dump -U atlas -Fc atlas > ~/atlas-backups/atlas-$(date +\%F).dump

Two 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 include docker. Run command -v docker and, if it’s somewhere else (Docker Desktop on macOS puts it in /usr/local/bin), add a PATH=... line above the job in your crontab that includes that folder.

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:

Terminal window
ls -lh ~/atlas-backups/
docker compose exec -T atlas-db pg_restore --list < ~/atlas-backups/atlas-$(date +%F).dump | head

Today’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.

Into a running stack, replacing what’s there:

Terminal window
docker compose stop atlas-api atlas-cron
docker compose exec -T atlas-db pg_restore -U atlas -d atlas --clean --if-exists < ~/atlas-backups/atlas-2026-10-01.dump
docker compose start atlas-api atlas-cron

This 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.

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.

docker compose down -v stops Atlas and deletes its database volume. Only do it on purpose, with a dump in hand.