Database Backup and Restore
MisterShell creates full PostgreSQL custom-format archives and stores them on the SFTP target configured in Settings → System → Config → Backup. The scheduled task and manual operator command use the same service and archive validation.
Database archives cover PostgreSQL data only. They do not cover recordings,
the event store, mounted TLS files, or DB_ENCRYPTION_KEY. Back up those items
separately. Keep the same DB_ENCRYPTION_KEY; without it, encrypted secrets in
a restored database cannot be decrypted.
Scheduled backups
The built-in Database Backup task remains visible under Settings → System → Scheduled Tasks. You can enable it, set its interval, use Run Now, and inspect its execution logs like any other scheduled task. Scheduled execution is coordinated by the current Core leader.
Each run creates a file named like:
full_backup_20260823_101112123456_core-0.dump
The archive is uploaded only after PostgreSQL has produced a non-empty custom archive and MisterShell has read and validated it completely.
Manual backup and listing
Run these inside any Core container:
docker exec -it <core-container> msh show backups
docker exec <core-container> msh backup database --yes
To confirm mutating commands interactively, first open the console with
docker exec -it <core-container> msh, then enter backup database. Manual
backup and listing are allowed on any Core; unique filenames prevent Cores from
overwriting one another.
Restore eligibility
In-product restore is supported only for a deployment configured as a single
Core. It works with either embedded or external PostgreSQL; the difference is
only the configured DATABASE_URL. Its database role must be allowed to force
drop, create, own, and restore the target database.
| Topology | Backup/list | msh restore | Recovery owner |
|---|---|---|---|
| Single Core + embedded DB | Scheduled/manual SFTP | File or SFTP | MisterShell operator |
| Single Core + external DB | Scheduled/manual SFTP | File or SFTP; DB role needs drop/create/restore | MisterShell/DB operator |
| Multiple Cores | Leader-scheduled; manual from any Core | Refused | Platform admins shut all Cores and restore externally |
The Core image ships PostgreSQL 17 client tools. An archive created by a newer client is never applied to an older server: MisterShell reads the dump version and checks the configured server before confirmation or quiescing. Use PostgreSQL 17 or a later compatible server for an external database if you want to use in-product backup and restore.
For every multi-Core deployment, msh restore refuses to run. Platform
administrators must stop all Cores, restore the shared database with native
PostgreSQL tooling, verify it, and then start the Cores again. Merely shutting
down all but one Core does not make the deployment eligible.
Restore a local archive
Place a readable custom-format archive inside the Core container, then run:
docker exec <core-container> \
msh restore database file /data/restore/archive.dump --yes
To confirm interactively, open msh first and enter the restore command without
--yes. Before confirmation, MisterShell checks
the PGDMP header, reads the archive table of contents, requires the
alembic_version, app_settings, and cluster_state relations used by the
restore checks, and renders the entire archive to /dev/null. The local source
file is never deleted.
Restore an SFTP archive
List the available basenames, then restore one:
docker exec -it <core-container> msh show backups
docker exec <core-container> \
msh restore database sftp full_backup_20260823_101112123456_core-0.dump --yes
MisterShell first downloads the file to a private 0600 file under
/data/restore-staging, then runs the exact same validation and restore engine
as local-file mode. This preliminary fetch requires the current database and its
backup settings to remain readable. An aborted or invalid preflight removes the
staging file.
When a new SFTP restore starts, MisterShell removes abandoned staging downloads older than seven days. Recent files are retained so a failed restore can be retried from its reported local path.
What happens during restore
After validation and explicit confirmation, MisterShell verifies that the
command is running through docker exec in the expected Core container. It
suspends the Core application, force-drops and recreates the configured database
from template0, restores with fail-fast PostgreSQL options, then verifies
UTF-8 encoding, the Alembic revision, and required application relations.
On success, the command expires the restored leadership lease, prints and
audits the result, clears the cluster liveness marker so startup performs cold
initialization, then stops the Core. A container restart policy such as
unless-stopped starts it again; otherwise, start the container yourself.
If a destructive step fails, the Core deliberately remains suspended so it
cannot serve a partial database. Do not restart it. For an SFTP restore, the
error includes the preserved local staging path. Open a new docker exec
session, correct the database/archive problem, and retry with:
restore database file <preserved-path>
SFTP trust and archive security
MisterShell uses the configured SFTP username and password but does not verify or pin the SFTP server host key. Platform administrators are responsible for a trusted endpoint, DNS, routing, and network path. PostgreSQL restore executes content supplied by the archive, so restore only archives whose source you trust. MisterShell validates readability and product identity; it does not establish archive authenticity.