What to back up
On a self-hosted site, backups are entirely yours. The software does not make scheduled backups, has no restore button and does not copy your files anywhere. The licence says so too: "You are responsible for backing up your data and securing your installation." This page lists what to copy. The pages that follow show how. It is for whoever runs the server.
The checklist
A site is rebuilt from four things. Copy all four.
| What | Why you need it |
|---|---|
| The database | Everything entered in the admin panel: concerts, members, announcements, donors, orders, pages, the admin list, and all Site Settings (name, colours, wording, switches). Site Settings live in the database, not in a file. |
| The uploaded files | The public store (gallery photos, posters, logos) and the private store (member documents, rehearsal tracks). Kept in separate places, and they are not in the database. |
| Your settings | The environment file (or the secrets) holding SITE_URL, LICENSE_KEY, the admin password, email and database credentials. Without them you can restore the data but not run the site. |
| Your own edits | wrangler.toml on Cloudflare (it holds your database and bucket ids), and site.config.json if you edited it. |
You do not need to back up:
- Downloaded releases (
DATA_DIR/releases). They come from the release server again. - Sessions and emailed login links. With the default settings they are in the database (unless you keep sessions in Redis or Cloudflare KV), are short-lived, and only stay valid if you restore the same database. Nobody loses anything if they are lost; they log in again.
- The built site (
dist/) andnode_modules/. They are in the download.
Keep a copy of the settings somewhere other than the server, such as a password manager. A backup of your data is no use if the server was the only place the credentials were written down. On Cloudflare, a secret set with wrangler secret put cannot be read back from Cloudflare.
Where each part lives
| Set-up | Database | Public files | Private files | Settings |
|---|---|---|---|---|
| Single server, Node, SQLite and local files (defaults) | ./data/choir.sqlite, plus choir.sqlite-wal and choir.sqlite-shm while the site runs | ./data/storage/public/ | ./data/storage/private/ | Your environment file |
Docker, SQLite stack (docker-compose.sqlite.yml) | /app/data/choir.sqlite in the volume data | /app/data/storage/public/ in the same volume | /app/data/storage/private/ in the same volume | .env next to the compose file |
Docker, PostgreSQL and MinIO stack (docker-compose.yml) | The db-data volume (PostgreSQL 16) | The bucket choir-public in MinIO (volume minio-data) | The bucket choir-private in MinIO | .env |
| PostgreSQL or MySQL on a server of your own | In that database server | Local files or an S3 bucket, as configured | Same | Your environment file |
| Cloudflare Workers | The D1 database named in wrangler.toml | The R2 bucket bound as PUBLIC_BUCKET | The R2 bucket bound as PRIVATE_BUCKET | wrangler.toml, and secrets, which you must keep yourself |
With the defaults, the three database files and the storage folder are all inside DATA_DIR. If you changed SQLITE_PATH, STORAGE_LOCAL_DIR or DATA_DIR, copy where those now point. npm run config:check prints the database and storage locations.
The PostgreSQL Docker stack has no named volume for /app/data. That is fine for your data (it is in PostgreSQL and MinIO), but see Update a Docker site.
The automatic copy before an update
When you press Update now on a SQLite site, the installer first makes a copy of the database in DATA_DIR/backups/, named like before-1.6.12-20261011T130500.sqlite, and keeps the last three. It exists so that a failed update can be undone.
It is not a backup:
- It lives on the same disk as the database it copies, so it does not survive losing the server.
- It is made only when you update, and only for SQLite.
- It does not include your uploaded files.
- Only the newest three are kept.
PostgreSQL and MySQL databases are not copied by an update at all.
How often, and where to
- The database: at least daily. Choirs enter data in bursts (before a concert, after a sale), so daily is the minimum worth having. Take a copy just before any update.
- Uploaded files: daily is simple. Files are never changed once uploaded (each upload gets a new unguessable name), so copying only new files is safe and quick.
- Settings: whenever they change.
- Keep copies off the server. A copy on the same disk does not help when the disk fails, the server is hacked, or the account is closed. Use another machine, a cloud bucket, or an external disk that is not left plugged in. Keep several generations, not just the latest, so you can go back past a mistake.
- Test a restore. A backup you have never restored is a hope, not a backup. Once, before you need it, restore into a spare folder or server and check that you can log in and see your photos. Restore a backup, or move to a new server shows how.
What the admin panel downloads is not a backup
The admin panel has spreadsheet downloads for lists such as members, donors, gifts and orders. They are worth keeping, but they hold only those lists. They do not include Site Settings, pages, the gallery, member files, announcements or the admin list, and nothing can load them back automatically.
How to do it
- Single server or Docker with SQLite: Back up a single-server site (SQLite and local files)
- PostgreSQL, MySQL, S3 storage, MinIO or Cloudflare: Back up PostgreSQL, MySQL, S3 storage and Cloudflare
- Putting a backup back: Restore a backup, or move to a new server