Back up and restore Lumio.
Self-hosting means the backup is on you. This guide shows exactly what needs backing up, how to automate it and how a restore works when it counts.
What needs backing up
Three things — only together do they make a complete backup:
- The PostgreSQL database — galleries, users, settings, metadata
- The object data — the actual images/videos (MinIO volume or external S3 bucket)
- The
.env— holds the keys; without it you can no longer reach the object data
Rule of thumb: database daily, object data depending on change rate, and always a copy off-site.
Back up the database
A pg_dump while running, from the project directory:
cd /opt/lumio
docker compose exec -T postgres pg_dump -U lumio lumio > db_$(date +%F).sql
# compress it right away to save space
docker compose exec -T postgres pg_dump -U lumio lumio | gzip > db_$(date +%F).sql.gz Back up the object data
With the bundled MinIO the files live in a Docker volume (usually
lumio_minio_data — check with docker volume ls). Back it up with a small helper container:
docker run --rm \
-v lumio_minio_data:/data:ro \
-v "$PWD":/backup \
alpine tar czf /backup/minio_$(date +%F).tar.gz -C /data .
And don't forget the .env — just copy it (it's sensitive, keep it safe):
cp /opt/lumio/.env env_$(date +%F).backup Automate & copy off-site
Put the steps into a small script and run it via cron. The crucial
ingredient is the copy to a second location — a different disk, a
different building or an object-storage bucket. With
rclone that last part is a one-liner:
# Example: push backups off-site after the backup runs
rclone copy /opt/lumio/backups remote:lumio-backups
# Cron: daily at 3:15 (crontab -e)
15 3 * * * /opt/lumio/backup.sh >> /var/log/lumio-backup.log 2>&1 Prune old backups regularly (e.g. keep 14 days) so storage doesn't fill up.
Restore (when it counts)
On a fresh machine: install Lumio as usual but use the backed-up .env (same keys = the object data match again). Then put the data back:
cd /opt/lumio
cp /path/to/backup/.env .env # use the backed-up .env
# object data back into the volume (stack may still be down)
docker volume create lumio_minio_data
docker run --rm \
-v lumio_minio_data:/data \
-v /path/to/backup:/backup \
alpine sh -c "tar xzf /backup/minio_YYYY-MM-DD.tar.gz -C /data"
# start the stack (creates the empty DB)
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# load the database
gunzip < /path/to/backup/db_YYYY-MM-DD.sql.gz | \
docker compose exec -T postgres psql -U lumio lumio Then log in and open a gallery — images and metadata should be fully there.
Common questions about backup & restore
How often should I back up? +
The database daily (it's small and the dump is quick), the object data depending on how much changes — daily under active use, otherwise weekly. What matters is less the frequency than the rule: automated via cron and with a copy off-site. A backup that only sits on the same machine is not a backup.
Why do I have to back up the .env too? +
Because that's where the secrets live — among them S3_ACCESS_KEY and S3_SECRET_KEY. Without those keys you can no longer get at your backed-up MinIO object data, and without JWT_SECRET/SESSION_SECRET sessions behave oddly after a restore. So the .env is a mandatory part of the backup (and belongs in a secure place, it's sensitive).
Does Lumio need to be stopped for a backup? +
No. pg_dump produces a consistent snapshot while the database runs. The object data are immutable files (new uploads are added, existing ones don't change) — copying them live is fine. Only for a clean volume snapshot under very high write load can a brief stop make sense.
Is backing up only the database enough? +
No. The database holds galleries, users, settings — but not the images. Those live as object data (in the MinIO volume or the external S3 bucket). You need both parts, otherwise after a restore you get empty galleries or images with no association.
What about external S3 (Hetzner, B2)? +
Then the object data don't live locally but in the bucket. Back them up with the provider's own tools: versioning plus a lifecycle rule, or a regular mc mirror into a second bucket at a different provider. The database and the .env you back up normally as described below.
Ready for your own gallery?
Source code on GitHub, questions and discussions there too. If anything in the guide trips you up, reach out — we're happy to improve the docs.