v0.1.0 Latest

Backup and restore

pg_dump the database, archive the uploads volume, keep .env. A Trove KB backup never contains a secret.

Everything Trove KB owns lives in two places: the Postgres database and the uploads volume. Secrets are not among them. Passwords and TOTP seeds stay in your vault, so a Trove KB backup never contains one.

WhatWhereNeeded to restore
Databasepgdata volume, Postgres 16Yes
Attachmentsuploads volume, or your S3 bucketYes, unless STORAGE_DRIVER=s3
.envYour secret storeYes: AUTH_SECRET signs sessions, POSTGRES_PASSWORD opens the database
secrets/bw_master_password.txtYour secret storeOnly in bw_serve mode

Back up

# Database, compressed custom format.
docker compose exec -T db pg_dump -U trove -Fc trove > trove-kb-$(date +%F).dump

# Attachments, when STORAGE_DRIVER=local.
docker run --rm -v trove-kb_uploads:/data -v "$PWD:/backup" alpine \
  tar czf /backup/trove-kb-uploads-$(date +%F).tar.gz -C /data .

Store .env alongside them. A nightly cron on the host is enough for most installs:

15 2 * * * cd /srv/trove-kb && docker compose exec -T db pg_dump -U trove -Fc trove > /backups/trove-kb-$(date +\%F).dump

Attachments can live on the NAS instead of a local volume: docker compose -f docker-compose.yml -f docker-compose.nfs.yml up -d with NFS_SERVER and NFS_UPLOADS_PATH set. Uploaded files are write-once, read-many, which is what a share is good at; the database stays on local disk because it is hot data.

Restore

docker compose down
docker volume rm trove-kb_pgdata trove-kb_uploads     # only when starting clean
docker compose up -d db
docker compose exec -T db pg_restore -U trove -d trove --clean --if-exists < trove-kb-2026-03-01.dump
docker run --rm -v trove-kb_uploads:/data -v "$PWD:/backup" alpine \
  tar xzf /backup/trove-kb-uploads-2026-03-01.tar.gz -C /data
docker compose up -d

Migrations run automatically on start, so a dump from an older version is brought up to date by the container it is restored into.

Verify a backup

Restore into a throwaway stack rather than trusting the file:

APP_PORT=3099 docker compose -p trove-kb-verify up -d db
docker compose -p trove-kb-verify exec -T db pg_restore -U trove -d trove --clean --if-exists < trove-kb-2026-03-01.dump
APP_PORT=3099 docker compose -p trove-kb-verify up -d
# Sign in, open a company, then tear it down.
docker compose -p trove-kb-verify down -v

Exports are not backups

The per-company export (JSON and Markdown, from the company page or GET /api/v1/companies/:id/export) is for reading and handover. It leaves out revisions, the audit trail, API keys, and webhook configuration. Use pg_dump for anything you intend to restore from.