Skip to content

Backup & restore

Admin → Site settings carries a platform export / import panel: a full-fidelity backup of your install as one versioned JSON document, with sections you pick per operation.

Choose any combination of sections:

site_settings · users · roles · competitions · automations · audit_log · pages

Custom pages travel in the backup too (the pages section, v1.5.0), matched by slug on an additive restore.

Since v1.6.0, custom brand themes ride inside the site_settings section (there is no separate themes checkbox), so moving or restoring an install keeps its themes; imported themes are re-validated and their local authorship is dropped. Per-competition custom registration fields carry their definitions with the competitions section — but the collected answers do not (they are personal data, available only through the organiser’s per-competition CSV export, never a backup).

The export is complete for what it covers — including password hashes and flag hashes — because a backup that can’t actually restore your install isn’t one. The exception is install-specific credentials encrypted at rest (ADR-0020): SSO identity providers and their secrets have never been part of the export; since v1.3.0 the SMTP password stays out too (the rest of the SMTP config — host, port, username, sender — still travels), and since v1.4.0 so does the AI provider configuration with its API key. Re-enter those on the new install after a restore.

Deliberately excluded: active login sessions, in-app notifications, collaborative-note snapshots, personal dashboard layouts, division memberships, AI assistant conversations and transcripts (v1.4.0), generated post-event report files (v1.5.0) — transient or per-subject state that doesn’t belong in a portable backup; the report files in particular are transient artefacts cleaned up by retention or deletion, so they’re never bundled — and the encrypted-at-rest credentials above (SSO providers with their secrets; since v1.3.0 also the SMTP password, and since v1.4.0 the AI provider key), which are install-specific and re-entered on new infrastructure. The challenge-instance provisioner settings are excluded on the same footing — infrastructure-specific operator config, re-entered per install.

Import is additive — it creates, never modifies or deletes:

  • Top-level entities are skipped if they already exist, matched by natural key: users by username/email, roles and competitions by name, custom pages by slug.
  • A competition is atomic — if its name exists, its whole subtree is skipped; otherwise everything under it imports together.
  • Fresh IDs are minted and every reference is rewritten through ID maps; invite codes are regenerated.

The result screen reports created/skipped counts per table, so you can see exactly what happened.

  • Moving installs — export on the old box, import on the new.
  • Pre-upgrade snapshots — cheap insurance before a version bump.
  • Seeding a staging copy — import competitions without live user data by selecting sections.

For challenge-only portability use the ctfcli zip flow; for disaster recovery, also keep ordinary PostgreSQL backups (pg_dump) and MinIO volume snapshots — the platform export is an application-level tool, not a substitute for infrastructure backups.