Skip to content

Backup and restore

Three things, and losing any one of them makes the others useless:

Component Why Losing it means
The database Every document record, version, permission, workflow, audit entry, and the wrapped encryption keys. Includes the job and workflow-engine schemas. Everything.
The storage root The encrypted document contents, previews and signing renditions. Documents are listed but cannot be retrieved.
The Data Protection key ring Protects authentication cookies, stored secrets, and the keys that unwrap every document’s data key. Every encrypted document becomes unreadable, and every session is invalidated.

The database records which stored file backs each version, so the database and storage root must be captured together. The backup tool does this for you.

A DPAPI-protected key ring is machine-scoped and cannot be restored onto a different machine. If your recovery plan involves new hardware, set DataProtection:CertificateThumbprint before the first backup is taken, and escrow that certificate separately from the backups themselves.

docsentry-backup (in tools/Docsentry.Backup) is a cross-platform command-line tool. One run produces a backup set containing:

  • a SQL Server backup of the database, taken with COPY_ONLY and checked with RESTORE VERIFYONLY
  • the storage tree
  • the Data Protection key ring
  • a signed manifest listing every part with its hash
  • a secret inventory recording which secrets the deployment depends on, never their values

Every part is written inside an encrypted envelope, and the manifest is signed, so a tampered or truncated set is detected rather than restored.

COPY_ONLY is unconditional: without it, the tool would insert itself into whatever differential or log backup chain the database team already runs and break their restore sequence. It also means the tool takes full backups and does not manage a log chain. If you need point-in-time recovery, keep a separate log-backup regimen alongside it.

Run the tool as a dedicated least-privilege operator. Database/operational/Grant-BackupOperator.sql and Grant-RestoreOperator.sql create the grants each verb needs. Give both the SQL Server service account and the account running the tool access to the staging directory: they are different identities, and the tool’s preflight proves the round trip works rather than guessing.

Command reference: Backup CLI.

docsentry-backup verify checks a set at one of three levels, each including the ones before it:

Level Checks
Manifest The manifest opens and its signature is valid. Fast.
Structure Every part the manifest lists is present at the destination.
Content Every part decrypts and matches the hash recorded in the manifest. Thorough and slow.

Schedule Structure after every backup, and run Content periodically.

docsentry-backup restore restores a set onto a target SQL Server and storage root. It is built to be safe to run and safe to re-run:

  1. You name the target. --confirm-target <database> must match the target database, so a restore cannot overwrite the wrong database by accident.
  2. Preflight checks the target, the staging round trip, and permissions before anything is changed. --dry-run stops after this step.
  3. Files first. The storage tree and key ring are placed before the database is restored, so a restored database never points at content that is not there yet.
  4. The database is restored with its data and log files relocated automatically, using names derived from the target database so they cannot collide with an existing database on the same instance.
  5. Orphaned database users are repaired, so the application principal maps to its server login again.
  6. Scheduled job state is cleared, so the restored instance does not replay jobs that belong to the source.
  7. The schema ledger is checked, confirming the restored database is at the version the application expects.

Re-running a restore that was interrupted skips files already in place.

After restoring, start the application. At startup it verifies it can unwrap the storage key material with the restored key ring, and refuses to start if it cannot - so a wrong or missing key ring is reported immediately rather than as a stream of unreadable documents.

  • Database backups alone. They contain no file content and no key ring.
  • Storage backups alone. Content is encrypted and named by a keyed address; without the database and key ring there is no way to open it.
  • The recycle bin. It is a user convenience with a retention period, not a backup.
  • Deduplication. It saves space; it is not redundancy.

Run docsentry-backup selftest after installing the tool on a new host and after any change to key provisioning. Use list to confirm sets are arriving at their destination, and alert on a non-zero exit code from every scheduled run.

Then, periodically, restore a set into a scratch database and storage root, start the application against it, and sign in. A backup nobody has restored is a hope, not a recovery plan.