Chronicler
Self-hosting

Backups and restore

Scheduled backups, an offsite copy, and how to get your data back.

You are the only one holding this data. Set up backups on day one.

What gets backed up

Admin → Backups backs up the database: accounts, collections, conversations, document metadata and the search index. Backups are standard PostgreSQL dumps named chronicler-YYYYMMDD-HHMMSS.dump, stored inside the backend_uploads volume.

The original uploaded files live in the same volume but are not inside the dump. A complete disaster-recovery plan is: these database backups, plus a copy of the backend_uploads volume, plus your .env.

Scheduled backups

Admin → Backups → Automatic backups:

SettingOptionsNotes
FrequencyOff, Daily, WeeklyDaily is right for most people.
Keep1–365Older backups are deleted automatically once you're over the count.
Offsite folderA path inside the containerOptional, and the most valuable part. See below.

Save the schedule and the panel shows the last run, the next one, and the error from the last failure if there was one. Changes take effect without a restart.

The offsite copy

A backup in the same Docker volume as the data doesn't survive the failure you're actually worried about. To keep a copy elsewhere, mount a host folder — a NAS share, an external disk — into the backend container.

Add the mount to your compose file

Under the backend service:

docker-compose.yml
    volumes:
      - backend_uploads:/app/uploads
      - /mnt/nas/chronicler-backups:/mnt/backups

On Windows, the left side is a host path like D:\backups.

Recreate the container

Terminal
docker compose up -d

Set the folder in the console

Enter /mnt/backups — the path inside the container — as the offsite folder and save. Chronicler write-tests the folder as you save and refuses a path it can't write to, so a typo fails immediately rather than silently for months.

The compose file that the desktop app's guided setup writes doesn't include this mount. You have to add it by hand, and re-add it after a guided update replaces the file. Keeping your own copy of the compose file avoids that.

Manual backups

Back up now in the console creates one immediately — do this before an update or any risky change.

Download saves a dump to the machine you're using the app on. That is the simplest offsite copy there is: download one occasionally and put it somewhere safe.

From the command line:

Terminal
docker exec chronicler-postgres pg_dump -U chronicler -Fc chronicler_app > chronicler-backup.dump

Restoring

Restoring replaces the entire database. Everything created since that backup is gone — accounts, conversations, documents. It cannot be undone.

Take a backup of the current state first

Even a broken database is better than no fallback. Back up now.

Tell people to stop

There's no maintenance mode. Anyone using the app during a restore will see errors, and their work may be lost.

Restore

Admin → Backups, find the archive, choose Restore, and confirm. The action is recorded in the audit log with who did it.

Check, then re-index

Sign in, open some documents, run a search. If results look wrong, run Admin → Model → Reindex all — the index in an old dump can lag the documents.

From the command line:

Terminal
docker exec -i chronicler-postgres pg_restore -U chronicler -d chronicler_app \
  --clean --if-exists --no-owner < chronicler-backup.dump

Moving to another machine

Back up and copy

Take a fresh backup and download it. Copy your docker-compose.yml and .env too — without that .env the old database volume is unreadable.

Install on the new machine

Follow Manual install, but use the existing.env rather than generating a new password.

Restore, then move the licence

Restore the dump, then release the licence on the old install and activate on the new one (Licensing).

Copy the uploaded files

The dump has no file contents. Copy the backend_uploads volume across:

Terminal
# on the old machine
docker run --rm -v chronicler_backend_uploads:/data -v "$PWD":/out alpine \
  tar czf /out/uploads.tgz -C /data .

# on the new one
docker run --rm -v chronicler_backend_uploads:/data -v "$PWD":/in alpine \
  tar xzf /in/uploads.tgz -C /data

Test it

An untested backup isn't a backup. Once, on a spare machine, restore one and sign in. Ten minutes now, or an unpleasant discovery later.