Disaster Recovery
What to Back Up
| File | Location | Critical |
|---|---|---|
yuzu-server.cfg | /etc/yuzu/ | Yes — contains user credentials |
*.db (all SQLite databases) | /var/lib/yuzu/ | Yes — all operational data |
| TLS certificates | /etc/yuzu/certs/ | Yes — mTLS identity |
Enrollment tokens and the pending-agent approval queue are in PostgreSQL (HA WS-6 6.2,
auth.enrollment_tokens/auth.pending_agents) — back them up via the samepg_dump/pg_restoreprocedure as the rest of theauthschema, not as local files.enrollment-tokens.cfg/pending-agents.cfgare no longer written by the 0.15.0 server; a copy found at any boot where the database holds no import record for it (a fresh database never does) is imported exactly once as live credentials, without any check of where it came from (the marker+fingerprint mechanics that refuse a later file with different content are indocs/adr/2002-high-availability-architecture.md§8).0.15.0 supports initial deployment into a fresh database only: restore a backup taken from a 0.15.0 deployment, not one written by an earlier build, and start with no leftover
enrollment-tokens.cfgorpending-agents.cfgin--data-diror the directory holdingyuzu-server.cfg(the server imports them without checking where they came from).
Shipped InstructionDefinitions live inside the
yuzu-serverbinary (embedded at build time byserver/core/scripts/embed_content.py) and are reseeded on every boot into the PostgreSQLinstruction_storeschema (ADR-0058) — notinstructions.db, which this store no longer reads or writes. Operator edits to definitions persist in Postgres; back them up via thepg_dump/pg_restoreprocedure covered elsewhere in this document for the server’s Postgres substrate.
Backup Strategy
Automated Daily Backup
# Add to crontab
0 2 * * * /usr/local/bin/yuzu-backup.sh --data-dir /var/lib/yuzu --config-dir /etc/yuzu --output /backup/yuzu
Pre-Upgrade Backup
Back up a 0.15.0 deployment before changing it (0.15.0 itself has no supported upgrade from an earlier build):
yuzu-backup.sh --output /backup/yuzu-pre-upgrade-$(date +%Y%m%d)
Using the Backup Script
# Default paths
./scripts/yuzu-backup.sh
# Custom paths
./scripts/yuzu-backup.sh --data-dir /var/lib/yuzu --config-dir /etc/yuzu --output /backup/yuzu
The script:
- Flushes SQLite WAL files (
PRAGMA wal_checkpoint(TRUNCATE)) - Copies all
.dband.cfgfiles - Generates a SHA256 manifest for integrity verification
Restore Procedure
Use only a backup taken from this 0.15.0 deployment; restore the Postgres dump and the keys directory together (see Key management in Server Administration).
# 1. Stop the server
systemctl stop yuzu-server
# 2. Restore from backup
./scripts/yuzu-restore.sh /backup/yuzu-backup-20260321-020000
# 3. Verify manifest
# (restore script does this automatically)
# 4. Start the server
systemctl start yuzu-server
# 5. Verify
curl http://localhost:8080/livez
Restoring a backup taken before the OIDC-secret redaction fix? Rotate the OIDC client secret. Earlier versions recorded it in the clear in the server log,
GET /api/configand theconfig.updateaudit detail. The current server no longer discloses it - including for audit rows written before the fix, which are redacted when read - but a restored backup still contains the plaintext bytes on disk, and anything that read it while it was exposed still holds a working credential. See Security hardening -> OIDC.
Recovery Time
| Scenario | Data at Risk | Recovery Time |
|---|---|---|
| Config file loss | Credentials, tokens | Minutes (restore from backup) |
| Database corruption | Responses, audit, policies | Minutes (restore + migration) |
| Full server loss | Everything | 15-30 minutes (new server + restore) |
| Agent data loss | Agent state, Echo history | Agent re-enrolls, Echo rebuilds |
Failover Architecture
For high availability:
- Active-passive: Two servers with shared storage (NFS/CIFS). Standby takes over on failure.
- Gateway multi-site: Deploy gateways in each site. If one server goes down, re-point gateways.
- Database replication: Use Litestream or sqlite3 backup API for continuous replication to object storage.
Data Loss Mitigation
- WAL mode: SQLite WAL provides crash recovery — incomplete transactions are rolled back on restart
- Retention policies: Response and audit data have configurable retention (90/365 days default)
- Agent resilience: Agents buffer commands locally and retry on reconnection