Skip to content

Backups

A backup is a copy of your content that you can bring back when something goes wrong: a broken server, a failed update, or an editor who deleted the wrong thing. Your docker project comes with two scripts for it, scripts/backup.sh and scripts/restore.sh. This page shows how to use them, how to run them automatically and how to check that a backup really works.

WhatWhere it livesIn the backup
Everything you create in the admin: spaces, content types, entries, versions, users, roles, menus, workflowsThe database (postgres, or with SQLite the database volume)Yes, database.dump (SQLite: database.db)
Uploaded images and filesThe uploads volumeYes, uploads.tar.gz
Resized images the public API has cachedA cache volumeNo, they are created again when needed
Your project files and .envThe project folderNo, keep them yourself (see below)

Run the script in your project folder on the server. The stack has to be running:

Terminal window
./scripts/backup.sh

It writes a new folder named after the date and time, for example backups/2026-09-11_03-00-00/, and prints backup written to backups/... when it is done. The folder holds two files:

  • database.dump: a complete copy of the database, made with the Postgres tool pg_dump. With SQLite the file is database.db instead, a copy made with manablox backup while api runs.
  • uploads.tar.gz: a compressed archive of the uploads volume.

The script keeps the 14 newest backup folders and deletes older ones, so the disk does not fill up. The CMS keeps running while it works.

The scripts only come with a docker project. In a local project with SQLite, copy the database with manablox backup while the CMS runs, and keep data/uploads too:

Terminal window
pnpm exec manablox backup backups/2026-01-31.db

It never overwrites an existing file, so use a new name each time. The database shows how to restore such a copy.

Cron is the Linux service that runs commands on a schedule. Open your list of scheduled commands:

Terminal window
crontab -e

Add this line at the end. It runs the backup every night at 3:00 (server time) and appends what the script prints to a log file. Replace /srv/my-cms with your project folder:

Terminal window
0 3 * * * cd /srv/my-cms && ./scripts/backup.sh >> backups/backup.log 2>&1

Save and close the editor. The five fields at the start mean minute, hour, day of month, month and day of week, so 0 3 * * * is “at 3:00, every day”.

The user whose crontab this is must be allowed to run Docker (it is root, or a member of the docker group). The next morning, check that it worked:

Terminal window
ls backups/
tail backups/backup.log

You should see a new folder and a line backup written to ... in the log.

A backup on the same server does not help if the server itself is lost. Copy the backups to somewhere else regularly: your own computer, a second server, or a storage service your hosting company offers.

For example, from your own computer, this copies all backup folders from the server into a local folder cms-backups (only new files are transferred on later runs):

Terminal window
rsync -av root@203.0.113.10:/srv/my-cms/backups/ ./cms-backups/

Many hosting companies also offer snapshots of the whole server. They are a good extra, but not a replacement: a snapshot lives with the same company and restores only the whole server, while the files from backup.sh can be restored on any machine.

If your project stores uploads in an S3 bucket (STORAGE_DRIVER=s3), the files are not on the server, and uploads.tar.gz stays almost empty. The database dump is still essential. For the files, use what your storage provider offers, for example versioning on the bucket, so a deleted or overwritten file can be brought back. See Uploads and images.

The restore script brings the database and the uploads back to the state of one backup:

Terminal window
./scripts/restore.sh backups/2026-09-11_03-00-00

It stops api and public, replaces the whole database with the one from the backup, replaces the uploads with the ones in the archive, and starts the CMS again. It prints restored from ... when it is done. With SQLite it replaces the database file and deletes the stale manablox.db-wal and manablox.db-shm files beside it, which belong to the old database.

To restore onto a new server, set it up as described in Put it on a server with your saved project folder and .env, start the stack once, copy the backup folder into backups/, and run the restore script there.

A backup you have never restored is a hope, not a backup. Try it once, and again every few months, on a machine that is not your live server. Your own computer with Docker is enough:

  1. Copy your project folder (with .env) and one backup folder from the server to your computer.
  2. In the copied .env, switch to the plain-http trial domains: ADMIN_DOMAIN=http://cms.localhost, PUBLIC_DOMAIN=http://content.localhost, PUBLIC_URL=http://cms.localhost and PUBLIC_API_URL=http://content.localhost (see Domains and HTTPS).
  3. Build and start the stack:
Terminal window
docker compose build
docker compose up -d
  1. Put the backup folder into backups/ inside the project and restore it:
Terminal window
./scripts/restore.sh backups/2026-09-11_03-00-00
  1. Open http://cms.localhost, sign in with your normal account and check that your spaces, entries and images are there.
  2. When you are done, remove the test stack and its data with docker compose down -v.