Backup & restore
What gets backed up
scripts/backup.sh produces a zstd-compressed tarball with:
db.dump—pg_dump -Fc -Z 6of the whole databaseetc-meridian/— the config tree at/etc/meridianuploads/— the file repo (/var/lib/meridian/uploads)branding/— uploaded logos and AUP assetsMANIFEST— metadata: timestamp, host, DB name, includes-keys flag, component listsecrets/— only if--include-keyswas passed
The --include-keys decision
With keys: full DR bundle. Can be restored onto any fresh host. But the bundle now contains the crown jewels — store it with the same care as the source.
Policy recommendation: take routine backups without keys for operational rollback, and take one with-keys backup per significant-change event (master-key rotation, major upgrade, integration cutover). Keep the with-keys bundles offline in secured storage.
Manual backup
# Routine (no keys):
sudo /opt/meridian/scripts/backup.sh
# DR-grade (with keys) — keep this offline:
sudo /opt/meridian/scripts/backup.sh --include-keys
# Custom output location:
sudo /opt/meridian/scripts/backup.sh --output /mnt/offsite/
Automatic backups
Three jobs run without intervention:
db-full-backup— daily 02:00, routine (no keys)db-wal-ship— every 15 minutes, for point-in-time recoverybackup-rotation— daily 02:00, keeps 7 daily + 4 weekly + 3 monthly snapshots
WAL archive lives at /var/lib/meridian/backups/wal/ (gzipped per-segment). Adjust retention in Admin → Scheduled Jobs.
Restore
Verify the bundle first (no changes made)
sudo /opt/meridian/scripts/restore.sh --dry-run /path/to/bundle.tar.zst
Full restore
sudo /opt/meridian/scripts/restore.sh /path/to/bundle.tar.zst
The script:
- Extracts + verifies the
MANIFEST. - Shows what it's about to replace.
- Requires you to type
RESTOREexactly to confirm. - Stops
meridian-app,meridian-celery,meridian-beat. - Drops + recreates the DB,
pg_restores with--no-owner --role meridian. - rsyncs
etc-meridian/,uploads/,branding/, and (if present)secrets/back into place. - Starts services and verifies all three stay up.
Restoring onto a fresh host
You need a --include-keys bundle for this. Workflow:
- Stand up a new Debian 13 (or 12) host.
- Run
install.shwith the same portal domain as the source host (so the TLS cert SAN matches). - Copy the bundle onto the host.
sudo /opt/meridian/scripts/restore.sh /path/to/bundle.tar.zst- Log in. Users, audit history, integrations, and branding are all back.
Point-in-time recovery (PITR)
The db-wal-ship job archives WAL segments every 15 minutes. To recover to a specific point:
- Identify the target recovery time.
- Extract the most-recent full backup from before that time.
- Restore the backup normally.
- Replay WAL from
/var/lib/meridian/backups/wal/up to the target time usingrestore_commandinrecovery.conf.
This is a PostgreSQL-level operation; see the PG docs for specifics. Meridian does not ship a PITR wizard in 1.0.0.
Verifying backup integrity
A bundle that won't restore is worse than useless. Verify monthly:
# Dry-run a random recent bundle:
sudo /opt/meridian/scripts/restore.sh --dry-run \
/var/lib/meridian/backups/full/meridian-backup-*.tar.zst
For extra confidence, spin up a throwaway test host periodically and perform a full restore onto it.