Back up and restore
Back up ReputeCast with pg_dump, the secret key and the files folder: a restore needs all three, and the database alone is not enough.
What a backup contains
Section titled “What a backup contains”| Part | What it holds | Where it is |
|---|---|---|
| PostgreSQL database | Everything else: workspaces, contacts, campaigns, uploaded images, the job queue, the audit log, and every stored credential in encrypted form. | The database in database.url. |
| Secret key | The AES-256-GCM key that encrypts provider credentials, OIDC client secrets, HostRepute tokens and authenticator (TOTP) seeds in the database. | REPUTECAST_SECRETS__KEY when you set it; otherwise the key file secrets.key_file: /var/lib/reputecast/secret.key in Docker, data/secret.key for the binary (relative to the directory ReputeCast starts in). |
| Files folder | Digital products’ files and lead magnets, which are too large for the database. | files.dir; by default a files folder next to the key file (/var/lib/reputecast/files in Docker). It appears once someone uploads a file. |
Keep your configuration too: the .env file or shell variables you start Docker Compose with, or your YAML config file
and environment file for the binary. The configuration reference lists every setting.
Before you begin
Section titled “Before you begin”- Shell access to the server, and the Docker Compose project directory (the one with
docker-compose.yml) or the binary’s environment file. - For the binary:
pg_dump,pg_restoreandpsqlof the same PostgreSQL major version as your server, or newer. - Enough disk space outside the data volume for the dumps.
Back up
Section titled “Back up”The shipped compose file names the project reputecast, so its volumes are reputecast_pgdata and
reputecast_appdata. The app volume holds the key file and the files folder.
-
Dump the database from inside the
postgrescontainer, so client and server versions always match.-Tturns off the terminal, which would otherwise corrupt the binary dump:Terminal window docker compose exec -T postgres pg_dump -U reputecast -d reputecast -Fc > reputecast-$(date +%F).dumppg_dumptakes a consistent snapshot while ReputeCast keeps running. -
Archive the app volume (secret key and files folder) with a short-lived container. Any image with
tarworks:Terminal docker run --rm -v reputecast_appdata:/data -v "$PWD":/backup alpine:3.22 \tar czf /backup/appdata-$(date +%F).tar.gz -C /data .tarkeeps the owner (user 65532, the image’s non-root user) and the0600mode ofsecret.key. -
If you set
REPUTECAST_SECRETS__KEYyourself instead of using the key file, store that value with your configuration backup. -
Copy the dump and the archive off the server.
-
Dump the database. Use the connection details from
REPUTECAST_DATABASE__URL:Terminal window pg_dump "postgres://reputecast:secret@localhost:5432/reputecast" -Fc -f reputecast-$(date +%F).dump -
Copy the key file and the files folder. With the defaults both live in the
datafolder of the directory ReputeCast runs in; if you setsecrets.key_fileorfiles.dir, copy those paths instead:Terminal window tar czf reputecast-data-$(date +%F).tar.gz -C /path/to/reputecast data -
If you set
REPUTECAST_SECRETS__KEYinstead of using a key file, back up the environment file that holds it. -
Copy the dump and the archive off the server.
Restore
Section titled “Restore”Restore the database before ReputeCast starts. The Docker image runs with --auto-install: started on an empty
database, it creates a new first Owner, which you don’t want on top of a restore.
-
Stop the app and keep PostgreSQL running. On a new server, start only PostgreSQL:
Terminal docker compose stop appdocker compose up -d --wait postgres -
Replace the database with an empty one:
Terminal docker compose exec -T postgres dropdb -U reputecast --force --if-exists reputecastdocker compose exec -T postgres psql -U reputecast -d postgres -c 'CREATE DATABASE reputecast' -
On a new PostgreSQL server, create the role that SQL segments run as.
pg_dumpcopies one database, not the server’s roles, and without this role the restore stops withrole "reputecast_segments" does not exist:Terminal docker compose exec -T postgres psql -U reputecast -d postgres \-c 'CREATE ROLE reputecast_segments NOLOGIN NOINHERIT' \-c 'GRANT reputecast_segments TO reputecast' -
Restore the dump:
Terminal window docker compose exec -T postgres pg_restore -U reputecast -d reputecast --exit-on-error < reputecast-2026-10-22.dump -
Put the secret key and files back into the app volume.
docker compose create appcreates the container and its volume without starting it:Terminal docker compose create appdocker run --rm -v reputecast_appdata:/data -v "$PWD":/backup alpine:3.22 \tar xzf /backup/appdata-2026-10-22.tar.gz -C /data -
Start ReputeCast:
Terminal window docker compose up -dIf the image is newer than the backup, it applies the pending migrations at start.
-
Stop ReputeCast, for example
sudo systemctl stop reputecast. -
Recreate the database, as a user that may create databases:
Terminal dropdb --force --if-exists reputecastpsql -d postgres -c 'CREATE DATABASE reputecast OWNER reputecast' -
On a new PostgreSQL server, create the SQL segments role first and grant it to the app’s user (
reputecasthere):segments-role.sql CREATE ROLE reputecast_segments NOLOGIN NOINHERIT;GRANT reputecast_segments TO reputecast; -
Restore the dump as the app’s user:
Terminal window pg_restore -d "postgres://reputecast:secret@localhost:5432/reputecast" --exit-on-error reputecast-2026-10-22.dump -
Put the key file and the files folder back where
secrets.key_fileandfiles.dirpoint, readable only by the user ReputeCast runs as:Terminal window tar xzf reputecast-data-2026-10-22.tar.gz -C /path/to/reputecast -
If the binary is newer than the backup, run
reputecast migrate up, then start ReputeCast again.
Check that it worked
Section titled “Check that it worked”curl -s http://localhost:8080/readyzanswersready. See health checks, metrics and logs.- The app logs don’t contain
generated a new secret key. If they do, ReputeCast didn’t find the restored key: stop it, put the key back and start it again. - Sign in with your password and authenticator app. A working authenticator sign-in proves the key matches the database.
- Open Sending providers in a workspace: connected sending providers keep their status instead of asking for credentials.
Test a restore before you need one: restore the latest backup into a second Compose project on another port (for
example docker compose -p reputecast-restore-test with REPUTECAST_PORT=8090) and sign in there.
Troubleshooting
Section titled “Troubleshooting”role "reputecast_segments" does not existduringpg_restore: the server is new. Create the role (step 3 of the restore), recreate the empty database and restore again.- Authenticator sign-in fails with
secrets: cannot decrypt value: the database was restored without its key, or with the wrong one. Put the original key back. If it is lost, people sign in with a recovery code or passkey, an instance admin removes their authenticator withreputecast user reset-2fa, and each workspace enters its provider credentials again. - A new Owner with a temporary password appears in the logs: the app started before the database was restored. Stop it, recreate the database and restore again.
pg_restore: error: unsupported versionor similar: yourpg_restoreis older than thepg_dumpthat wrote the file. Run the restore inside thepostgrescontainer, or install a newer client.
Related
Section titled “Related”- Upgrade ReputeCast: take a backup before every upgrade.
- Security and hardening: how the secret key protects credentials, and how to rotate it.
- PostgreSQL: versions, pool size and the SQL segments role.
- Recover access from the command line.