DATA_DIR:
What a complete backup needs
Back up a consistentsuchi.db snapshot together with blobs/,
.decrypt-key, and any operator configuration stored in the
directory. The database without blobs/ has metadata but no document bytes.
The database without .decrypt-key cannot open sealed mailbox, OAuth,
PDF-password, LLM, or authenticator TOTP credentials. Recovery-code storage is
one-way digested and cannot recreate the codes shown during setup.
rendered/ is generated state and can be rebuilt. A cleanly stopped database
does not need its WAL or shared-memory files. An atomic snapshot of a live
archive must include the database and its WAL together; never copy them at
different times.
The generated filing index contains only
the current system/tree map and descriptions, as do taxonomy exports; neither
preserves documents, automations, permissions or review/version/link history. They cannot replace a complete backup.
Keep the generated index namespace reserved for Suchi; see the filing guide for
refresh, recovery and legacy-category diagnostics.
A complete backup is whole-instance: systems share SQLite, CAS and credential
keys. It preserves membership, ACLs, document/version/link relationships and the
global document-ID high-water state. Host/backup operators can access every system
and remain trusted; a filing prefix is not backup isolation or per-system encryption.
Native takeout manifest v2 selects one system and is deliberately partial; source
addresses do not request preservation of IDs when documents are ingested again.
The mbsync deployment keeps credentials and Maildir state outside DATA_DIR;
back up its deployment directory separately when that path is used.
Built-in database snapshots
EveryBACKUP_INTERVAL (default 24h), Suchi creates a consistent SQLite
snapshot and records it in:
manifest.json records each snapshot ID, byte count, creation time and SHA-256;
retention updates that manifest before deleting old files. The digest detects
accidental corruption but is not a signature: protect the manifest and snapshots
together.
Suchi retains the newest BACKUP_KEEP snapshots, defaulting to seven.
BACKUP_INTERVAL=0 disables the loop. These snapshots include only the
database. A complete backup also needs document files, the credential key, and
configuration. Offline GC consults the live database, not these older snapshots,
so it can reclaim bytes that an older snapshot still references. Keep a complete
backup for disaster recovery.
Backup methods
Stop and copy
Stopping Suchi before copying the directory is the simplest consistent method. Stop CLI imports and other archive writers too; do not run GC during the copy:suchi export, suchi gc and suchi doctor, take an
operating-system lock on DATA_DIR/.suchi.lock; a second process fails with
archive_in_use instead of opening the database. The lock is released when
the process exits, including after a crash, so the leftover .suchi.lock file
is harmless: leave it in place and include it in backups like any other file.
Shared network filesystems are not supported storage, even with the lock.
Atomic filesystem snapshot
Filesystem snapshots such as ZFS, btrfs, or LVM are suitable when they capture the whole data directory atomically, including the database WAL, blobs, and keys. Copy from that stable snapshot, not from the changing live directory. Encrypted backup tools such as restic or Borg can archive the snapshot off-host. A database snapshot followed by a live blob-tree copy is not an atomic archive backup. A separate GC process could remove bytes still needed by that snapshot. Do not copy only a livesuchi.db, copy WAL files separately, or omit blobs.
Restore
- Stop the target process.
- Move the existing
DATA_DIRaside rather than deleting it immediately. - Restore the database, blobs, credential key, and configuration into an empty directory.
- Set ownership and restrictive key permissions.
- Start the exact target Suchi version. It accepts only the source database states in the release compatibility table.
- Check
/readyz, open known documents, run a search, and test one sealed integration such as a mailbox connection.
DATA_DIR, fsyncs it, removes stale
suchi.db-wal and suchi.db-shm, then atomically renames it to suchi.db.
Every archive writer must still be stopped. A database-only restore does not
restore blobs, the credential key, or configuration.
If rendered/ was omitted or the data directory moved, queue link rebuilding
with suchi refile --skip-automations; add --system S01 for each additional
system. The running server processes those jobs. Startup itself refreshes
filing indexes and pending moves, not every document link.
The restore drill in the manually dispatched checks workflow verifies a
built-in database snapshot, then stops and copies a synthetic archive into a
fresh directory. After restart it checks database integrity, key preservation,
original document download, and search. Run it locally with make build and
bash hack/smoke-restore.sh. It does not validate an operator’s off-host backup
or external credentials; restore those into a scratch instance periodically.
Upgrade and rollback
Before an upgrade, confirm that the current database state appears in the target release’s compatibility table. Take a complete backup using one of the methods above, stop every archive writer, and keep the deployment pinned to an explicit version. Pull or install the target version, recreate or restart the single Suchi instance, then verify/readyz and run suchi doctor.
Database migrations are one-way. To roll back after a migration, stop Suchi,
restore the complete pre-upgrade data directory, install the previous binary or
image, and verify readiness again. Do not run an older binary against a database
opened by a newer release.
The first stable-v1 startup from a supported pre-stable database creates an
exclusive mode-0600 database snapshot beside suchi.db before changing it.
That snapshot is a last-resort database copy, not a complete backup: it does not
contain blobs, the credential key or configuration. Retain the complete backup,
the previous binary or image, and the adoption snapshot until a restore drill
succeeds.
If startup rejects the database, leave the original data directory stopped and
inspect the error against the compatibility table. Do not change
PRAGMA user_version, edit lineage rows, skip versions, or run repair SQL to
force admission.
Retention and garbage collection
Choose retention based on recovery needs and applicable law. Deleting a document does not remove bytes from existing snapshots or external backups. Trash and its automatic 30-day retention permanently remove document rows and rendered files, but leave original and derived CAS bytes in place.suchi gc
reports unreferenced blobs; suchi gc --apply removes them only during offline
maintenance. Stop the server and all other archive writers before applying GC,
and take a complete recoverable backup first. See CLI.
Moving to another host uses the same procedure: create a consistent backup,
restore it under the destination DATA_DIR, update ownership and PUBLIC_URL,
then point the reverse proxy or DNS to the new instance.