jngkadocs
Operations / Backups

Backups

Everything Jangka stores lives in Postgres: documents, section history, comments, users, settings, the job queue and generated export files. Besides the database, you only need MASTER_KEY.

Back upWhere it isWithout it
The databaseThe pgdata volume, or your own Postgres serverEverything is lost
MASTER_KEY.env next to the compose fileStored LLM API keys and SSO client secrets can't be decrypted

Keep the two apart. A copy of the database together with the key gives access to your provider keys.

Back up the database

With the bundled Postgres, pg_dump runs inside the postgres container and writes a compressed dump on the host:

terminalsh
docker compose exec -T postgres pg_dump -U jangka -Fc jangka > jangka-$(date +%F).dump

The app can keep running during the dump. To take one every night at 02:00, add a cron entry on the host (% has to be escaped in crontab):

crontab -e
0 2 * * * cd /opt/jangka && docker compose exec -T postgres pg_dump -U jangka -Fc jangka > backups/jangka-$(date +\%F).dump

Copy the dumps off the server and delete old ones on whatever schedule your retention policy sets.

With your own Postgres, use your provider's backups or snapshots, or run pg_dump against DATABASE_URL with a client of version 18 or later.

Generated DOCX and PDF files are in the database too, but they expire after 24 hours and are removed every hour. A restored instance simply exports them again on request.

Back up MASTER_KEY

Copy the MASTER_KEY line from .env into a password manager or secret store once. It never changes, so one copy is enough.

Restore

Restore into the same Jangka version that made the dump, or a newer one. A newer version migrates the restored database on start. An older one can't read a schema it doesn't know.

terminalsh
docker compose stop app
docker compose exec -T postgres pg_restore -U jangka -d jangka --clean --if-exists < jangka-2026-11-03.dump
docker compose start app

--clean --if-exists drops existing objects before recreating them, so the database ends up exactly as it was in the dump. Set MASTER_KEY in .env to the key that was in use when the dump was taken.

If you run a separate worker, stop and start it together with app.