Backups and recovery exports
baum uses two complementary forms of protection:
- Backups contain the PostgreSQL database, object storage, local Git repositories, and non-secret configuration.
- Recovery exports contain the installation configuration, credentials, and secrets that backups deliberately exclude. They are encrypted to an age recipient that you control.
You need both to recover from the loss of the appliance. Keep them off the baum server and in separate, access-controlled storage.
Configure off-host backups
Section titled “Configure off-host backups”The appliance takes a backup daily and before an update. It keeps the seven
most recent completed runs locally under /var/lib/baum/backups/ by
default. Local backups do not protect you if the VM or its disk is lost, so
configure an S3-compatible destination:
sudo baumctl backup destination set \ --endpoint s3.example.com \ --region eu-west-2 \ --bucket baum-backups \ --prefix production \ --access-key-id ACCESS_KEY_ID \ --retention 30The command prompts for the secret access key without displaying it. The
endpoint must be a host and optional port, without a URL path. TLS is enabled
by default; use --secure=false only for a trusted endpoint that does not
support TLS. The destination must not be the appliance’s primary object
storage.
--retention controls the number of completed remote runs retained and
defaults to 30. baum verifies the destination by writing, reading, and
removing a probe before saving the configuration.
Check the saved destination, then take an initial backup:
sudo baumctl backup destination statussudo baumctl backupsudo baumctl doctorA successful run prints its local directory. In remote storage, each run is
stored below the configured prefix using a UTC timestamp. baum uploads
backup.json last; its presence marks the remote run as complete.
Create a recovery key
Section titled “Create a recovery key”Install age on a trusted operator workstation and generate an X25519
identity there, not on the baum server:
age-keygen -o baum-recovery-key.txtage-keygen -y baum-recovery-key.txtThe second command prints the public recipient, which begins with age1. The
identity file contains the private key. Store it in a password manager, secrets
vault, or another protected recovery system, and make sure authorized
operators can retrieve it if the usual administrator is unavailable. Never
copy the private identity to the baum server merely to create an
export.
Export the recovery bundle
Section titled “Export the recovery bundle”Copy only the public age1... recipient to the appliance and run:
sudo baumctl recovery export \ --recipient age1EXAMPLE_REPLACE_WITH_YOUR_RECIPIENT \ --output /tmp/baum-recovery.ageMove the resulting encrypted bundle off the appliance, verify that the stored copy is readable, and remove the server-side copy. The bundle includes the installed release definition, baum configuration, GitHub App details, and appliance secrets. It does not include the database, objects, or Git repository data; those remain in the backups.
Create a new recovery export after changing baum secrets, configuration, GitHub App credentials, storage credentials, or the installed release. Retain at least the export that corresponds to the release used by your recoverable backups.
Restore a backup
Section titled “Restore a backup”Restoring stops the application and replaces its database and stored data. For a local completed backup, run:
sudo baumctl restore \ /var/lib/baum/backups/20260812T120000Z \ --yesTo download a completed run from the configured destination and restore it, use its timestamp:
sudo baumctl restore --from-destination 20260812T120000Z --yesThe installed baum release must match the release recorded in the
backup. If it does not, baumctl tells you which version to install or
roll back to first. After the restore, run sudo baumctl status and
sudo baumctl doctor.
Recover a lost appliance
Section titled “Recover a lost appliance”On a replacement supported Ubuntu VM, install the server prerequisites as described in Self-host baum. Transfer the encrypted bundle and, only for the duration of recovery, the age identity to the replacement host. Import the installation state:
sudo baumctl recovery import \ --identity /path/to/baum-recovery-key.txt \ --input /path/to/baum-recovery.ageThe import verifies the bundle, its checksums, and its signed release manifest before installing the recovered configuration and secrets. Then reconcile the appliance and restore the matching off-host backup:
sudo baumctl applysudo baumctl restore --from-destination 20260812T120000Z --yessudo baumctl doctorSecurely remove the copied private identity from the replacement host when recovery is complete. Practice this procedure periodically on an isolated host; an untested backup and an unavailable private key are not a recovery plan.