3.8 KiB
Harbor state recovery
Storage owners
Harbor uses the existing data directory. harbor.sqlite is the only working owner of settings, profiles, subscriptions, device inventory and accumulated device counters. Settings and devices are versioned JSON documents inside SQLite (currently state schema 10 and inventory schema 3); the journal is a separate indexed table with the existing 30-day/10,000-event limit.
traffic.sqlite is separate, replaceable working history: 90 days, completed minute buckets for the latest 7 days and hourly buckets before that. Removing history does not reset settings or exported counters. Prometheus is optional and independently retains only the metrics it scrapes; it cannot restore this database.
Secrets, hardware identity, generated configuration and sing-box's own cache remain files.
Atomic writes and migration
SQLite uses WAL, FULL synchronous commits and a five-second busy timeout. A document mutation runs its read and write in one transaction. Journal append/deduplication/pruning is transactional. Profile/server switching still prepares candidate configuration and runtime before publishing the canonical state.
Before the first successful SQLite startup, Harbor imports state.json, devices.json, activity-journal.json and, when required by a pre-profile schema, subscription-cache.json in one transaction. Existing normalizers preserve revision, stable IDs, ordered rules and decimal-string counters. A null optional subscription cache is valid.
The import marker commits with all imported records. An unsupported version, invalid input or conflicting cache owner aborts the entire import. Harbor does not erase settings, rename damaged originals, start stale configuration or silently return to first-run. Correct the reported original and retry only after making a backup.
After a successful import, the original JSON files remain unchanged under their original names as transition-time backups. They are never read or written as current state again. Changing them does not change Harbor. A corrupt or unsupported SQLite database does not fall back to those stale JSON files.
Backup and recovery
Stop both control and collector processes before offline recovery. On a Gateway this means the control and dataplane components; stop the Mac backend for Mac recovery.
- Preserve the whole data directory, including any
-waland-shmfiles, before changing anything. - Restore a matching backup of
harbor.sqliteand any necessary secret/config files. Do not mix a database with another backup's WAL. - Start the same compatible release and inspect
GET /api/statebefore applying a profile.
For online backups use SQLite's backup API; copying only a live .sqlite file can omit committed WAL data. Offline copies after a clean stop are simpler.
To discard only working traffic history, stop the collector and move its traffic.sqlite plus any associated traffic.sqlite-wal and traffic.sqlite-shm aside together. Leave harbor.sqlite untouched. A new collector database starts a new coverage period; there is no automatic Prometheus backfill. Do not unlink an open database.
Deletion/retention makes pages reusable; it does not necessarily shrink the physical file immediately. Traffic retention and compaction run in the worker, outside connection processing.
Downgrade
A pre-SQLite binary ignores harbor.sqlite. Merely starting it would revive old JSON settings and lose all changes since the cutover. Automatic downgrade is unsupported.
Either restore a complete pre-upgrade backup deliberately, accepting the loss of subsequent changes, or first export current state into the exact schema required by the older binary. No automatic export/downgrade tool is provided. Preserve the SQLite backup in either case; do not overwrite current state with stale JSON as a recovery shortcut.