Backups and upgrades
What to back up
Section titled “What to back up”Two things, kept apart from each other:
| What | Why |
|---|---|
| The PostgreSQL database | Every event, incident, source, destination and setting. |
The infrainbox-data volume |
The master encryption key. Without it, the encrypted secrets in a database dump — destination credentials, push keys — can’t be read back. |
Back up
Section titled “Back up”From deploy/compose/, with the stack running:
./backup.sh -o /srv/backups/infrainbox-$(date +%F)This writes two files into that directory: infrainbox.dump (a pg_dump -Fc of the database) and infrainbox-data.tar.gz (the volume holding the master key). It runs against whatever compose project and .env the stack was started with, so a Caddy override or a custom project name still applies.
Restore
Section titled “Restore”Onto a stopped or destroyed stack:
./restore.sh -o /srv/backups/infrainbox-2026-09-14In order, this starts PostgreSQL, applies the running version’s migrations, restores the infrainbox-data volume from the tarball, restores the database with pg_restore --clean --if-exists, then starts the stack again. Two flags for partial restores:
--db-only— restore the database only; use this when the volume is already intact or already restored.--no-start— stop after restoring, without starting the stack.
Restore onto the same version you backed up from. Migrations only ever move forward, so restoring an old dump onto a newer binary applies migrations it never saw before restoring.
Check it works
Section titled “Check it works”restore.shfinishes without error anddocker compose psshows both services healthy.- Signing in shows the incidents and sources you had before.
- A destination’s “Send test” button still works — proof its stored credential decrypted correctly under the restored master key.
Test this restore procedure at least once before you need it for real.
Upgrades
Section titled “Upgrades”docker compose pull # or set a new tag directlydocker compose up -dMigrations run automatically at start, and the server refuses to start against a database schema newer than it knows how to handle — so a downgrade is caught immediately rather than corrupting data. Never pin to :latest: an unpinned tag turns an ordinary restart into an unplanned upgrade. Back up before an upgrade that touches the database schema, the same as before any other change to a production instance.
Rotating the master key
Section titled “Rotating the master key”If you need to rotate the master key (routine hygiene, or suspected exposure):
- Set the new key as
INFRAINBOX_MASTER_KEY(or_FILE) and the current one asINFRAINBOX_MASTER_KEY_PREVIOUS, then restart every server process. It now opens existing secrets under either key and seals new ones under the new one. - Run the rotation itself, which re-wraps every stored secret in small, resumable batches:
Terminal window docker compose exec infrainbox /infrainbox admin keys rotate - Back up the new key (
infrainbox admin master-key export, kept apart from database dumps as usual), then removeINFRAINBOX_MASTER_KEY_PREVIOUSand restart. The server refuses to start without the previous key while any secret still needs it, so this is safe to attempt and re-run.
infrainbox admin master-key export is the only place the key is ever shown — never in the dashboard, never in a log.