Backup and restore
A complete backup has five parts: the PostgreSQL databases, Redis, the uploads
volume, the SeaweedFS volume, and your .env file. If you use HTTPS, also keep
the Caddy volume. Before you rely on your backups, test a restore on a spare
installation.
Back up before using setup
Section titled “Back up before using setup”The current setup wizard does not create or download backups. Before an upgrade, use the manual steps below and keep a secure copy of your private environment file with the data. Test a restore on a spare installation.
If you retained an archive from an earlier development build, do not assume it contains the complete SeaweedFS volume. Check its contents before relying on it as a complete backup.
Manual backup
Section titled “Manual backup”The volume archive commands below use the default named volumes. If you set
POSTGRES_DATA, REDIS_DATA, UPLOADS_DATA or SEAWEEDFS_DATA to a host folder,
record that path with your backup. Keep using the database export commands for
PostgreSQL. For Redis, uploads and SeaweedFS, back up the selected folders while
their services are stopped instead of archiving the default Docker volumes.
Restore those folder backups to the paths selected in .env before starting
the services. A backup of an unused default volume does not contain your data.
Run these commands in your lunarpaper folder, beside compose.yaml and .env.
For HTTPS, replace docker compose in each command with
docker compose --project-name lunarpaper --env-file .env -f release/compose.yaml -f release/compose.https.yaml.
They work in both bash and
PowerShell. Lunar Paper is unavailable for a few minutes while the backup runs.
If you installed with docker run, read
docker run installations first.
Create a folder for the backup. On Linux and macOS, also run
chmod 700 backups so only you can read it.
mkdir backupsStop Lunar Paper, but leave the database, Redis and file storage running:
docker compose stop lunarpaperExport both databases to a file and copy it into the backups folder:
docker compose exec -T postgres sh -c 'pg_dumpall --username=$POSTGRES_USER --clean --if-exists > /tmp/postgres.sql'docker compose cp postgres:/tmp/postgres.sql backups/postgres.sqldocker compose exec -T postgres rm /tmp/postgres.sqlSave the Redis data, stop Redis and SeaweedFS, and then archive their volumes and the uploads volume:
docker compose exec -T redis sh -c 'REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli SAVE'docker compose stop redis seaweedfsdocker run --rm -v lunarpaper_redis-data:/source:ro -v "${PWD}/backups:/backup" alpine tar czf /backup/redis.tgz -C /source .docker run --rm -v lunarpaper_uploads-data:/source:ro -v "${PWD}/backups:/backup" alpine tar czf /backup/uploads.tgz -C /source .docker run --rm -v lunarpaper_seaweedfs-data:/source:ro -v "${PWD}/backups:/backup" alpine tar czf /backup/seaweedfs.tgz -C /source .Start everything again:
docker compose up -d --waitFinally, keep a copy of the Compose files and selected platform/PostgreSQL image
versions, copy .env into the backups folder, and move the folder to
encrypted storage away from the server. .env holds the keys that decrypt your
data, so the backup is useless without it.
Restore
Section titled “Restore”Restore into a new installation. If you want to restore over an existing installation, stop it and move its volumes aside first. Never restore into volumes that already hold data.
The restore has four stages:
- Restore
compose.yamland.envintolunarpaperand select the exact platform and PostgreSQL versions used by the backup. For HTTPS, restore the configuration files intoreleaseand.envinto the parentlunarpaperfolder. Keep the original project name and use the commands for your installation method. - Unpack the archives into new volumes.
- Start PostgreSQL and Redis, and restore the database dump.
- Start everything, complete the database upgrade if one is needed, and check that everything works.
The commands for each stage follow. First, unpack the archives:
docker volume create lunarpaper_redis-datadocker volume create lunarpaper_uploads-datadocker volume create lunarpaper_seaweedfs-datadocker run --rm -v lunarpaper_redis-data:/target -v "${PWD}/backups:/backup:ro" alpine tar xzf /backup/redis.tgz -C /targetdocker run --rm -v lunarpaper_uploads-data:/target -v "${PWD}/backups:/backup:ro" alpine tar xzf /backup/uploads.tgz -C /targetdocker run --rm -v lunarpaper_seaweedfs-data:/target -v "${PWD}/backups:/backup:ro" alpine tar xzf /backup/seaweedfs.tgz -C /targetThen restore the database:
docker compose up -d --wait postgres redisdocker compose cp backups/postgres.sql postgres:/tmp/postgres.sqldocker compose exec -T postgres sh -c 'psql --username=$POSTGRES_USER --dbname postgres -f /tmp/postgres.sql'docker compose exec -T postgres rm /tmp/postgres.sqlThen start everything:
docker compose up -d --waitYou can ignore warnings that the volumes “already exist”. To check the
restore, sign in, open a file you know was uploaded, and check that
/api/health/ready returns HTTP 200.
docker run installations
Section titled “docker run installations”A docker run installation uses the same volume names, so the archive and unpack commands work without changes. Replace the Docker Compose commands with these:
| Instead of | Use |
|---|---|
docker compose stop lunarpaper |
docker stop lunarpaper |
docker compose exec -T postgres … |
docker exec lunarpaper-postgres … |
docker compose cp postgres:/tmp/postgres.sql … |
docker cp lunarpaper-postgres:/tmp/postgres.sql … |
docker compose exec -T redis … |
docker exec lunarpaper-redis … |
docker compose stop redis seaweedfs |
docker stop lunarpaper-redis lunarpaper-seaweedfs |
docker compose up -d --wait |
docker start lunarpaper-redis lunarpaper-seaweedfs lunarpaper |
Your saved block of settings takes the place of .env, so keep it with the
backup. To restore, paste the block, create the network, and unpack the
volumes. Then start the database, restore the dump, and start Redis, file
storage and Lunar Paper, following install steps 4 to 7. Never generate new
secrets for a restore.
