Backups and restore
PostgreSQL and RustFS are separate authoritative stores and form one recovery set. Back up both under the same timestamp before upgrades or other risky changes. Redis is a reconstructible cache and is not part of the authoritative pair.
Replace <ts> with one timestamped directory name before running any command. Do not execute the angle-bracket placeholder literally.
PostgreSQL backup
Run from ~/dev/lobe:
sudo -n docker exec lobe-postgres pg_dump -U postgres --format=custom -f /tmp/lobechat.dump lobechat && sudo -n docker cp lobe-postgres:/tmp/lobechat.dump backups/<ts>/lobechat.dump && sudo -n docker exec lobe-postgres rm /tmp/lobechat.dumpThis produces a custom-format logical dump outside the Docker volume. Verify that PostgreSQL can read its catalog:
pg_restore --list backups/<ts>/lobechat.dumpA file that merely exists is not sufficient; pg_restore --list must complete successfully.
RustFS backup
The backup client uses the exact pinned minio/mc digest from Compose, joins the private runtime network, reads credentials from .env without printing them, and mirrors bucket lobe to the paired backup directory:
sudo -n docker run --rm --network lobe_lobe-network --env-file .env -v "$PWD/backups/<ts>/rustfs:/backup" --entrypoint /bin/sh minio/mc:latest@sha256:a7fe349ef4bd8521fb8497f55c6042871b2ae640607cf99d9bede5e9bdf11727 -c 'mc alias set rustfs http://rustfs:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY" && mc mirror rustfs/lobe /backup/lobe'Verify the mirrored tree:
ls -R backups/<ts>/rustfs/lobeThe listing must show the expected object tree. Do not enable shell tracing around the --env-file command.
Recovery set register
For each <ts>, retain together:
backups/<ts>/lobechat.dumpbackups/<ts>/rustfs/lobe/- application image identity expected by the data:
lobehub/lobehub:2.2.15@sha256:9186fbb2a1cd593eada518560695e1f14f0fa570ed987ba1bf1b3008456422cafor the currently documented release
A Docker volume, volume snapshot name, or running container is not a backup receipt.
Restore prerequisites
Before restore:
- select the application digest matched to the backup
- bring the stack to a state where PostgreSQL and RustFS are healthy
- make the selected PostgreSQL dump available inside
lobe-postgres - make the selected RustFS mirror available to the pinned
minio/mccontainer - ensure application writes cannot race the restore
- understand that
--clean --if-existsreplaces database objects in the selected database
Do not delete volumes as a rollback mechanism.
PostgreSQL restore
Copy the selected dump into the PostgreSQL container, restore it into lobechat, then remove the temporary copy:
sudo -n docker cp backups/<ts>/lobechat.dump lobe-postgres:/tmp/lobechat.dump
sudo -n docker exec lobe-postgres pg_restore -U postgres -d lobechat --clean --if-exists /tmp/lobechat.dump
sudo -n docker exec lobe-postgres rm /tmp/lobechat.dumpThe required restore operation is pg_restore -U postgres -d lobechat --clean --if-exists /tmp/lobechat.dump inside lobe-postgres.
RustFS restore
Reverse the mirror direction with the same pinned client and private network:
sudo -n docker run --rm --network lobe_lobe-network --env-file .env -v "$PWD/backups/<ts>/rustfs:/backup" --entrypoint /bin/sh minio/mc:latest@sha256:a7fe349ef4bd8521fb8497f55c6042871b2ae640607cf99d9bede5e9bdf11727 -c 'mc alias set rustfs http://rustfs:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY" && mc mirror /backup/lobe rustfs/lobe'After both restores, reconcile the matched application digest and repeat verification. The bucket policy still makes restored object URLs anonymously readable; writes remain signed.
Upgrade rollback boundary
- application rollback:
- restore the previous pinned image reference and run
sudo -n docker compose up -d
- restore the previous pinned image reference and run
- database rollback after an incompatible migration:
- restore the matched pre-upgrade PostgreSQL dump
- restore the matching RustFS mirror when object state changed
- forbidden shortcut:
- deleting
lobe_postgres_dataorlobe_rustfs_data
- deleting