Backup & Restore
Database schema upgrades are forward-only — there is no downgrade path. A backup taken with altavms backup is your only way to roll back, which makes it part of the upgrade routine, not an optional extra.
Taking a backup
Section titled “Taking a backup”sudo altavms backup --output /root/There’s no downtime: the database is snapshotted with SQLite’s VACUUM INTO, which takes a consistent point-in-time copy while the service keeps writing, and the copy is already checkpointed — the archive never contains WAL/SHM sidecar files, so the “restored an old WAL onto a new database” corruption class can’t happen. The source database is integrity-checked first; a backup of a damaged database is refused rather than overwriting your last good archive.
What’s in the archive
Section titled “What’s in the archive”altavms-backup-<host>-<timestamp>.tar.gz└── altavms-backup-<host>-<timestamp>/ ├── manifest.json what's inside, schema version, encryption key ids ├── altavms.db consistent database snapshot ├── config.yaml ├── altavms.env secrets — omit with --no-secrets ├── maps/… floor-plan images — omit with --no-maps └── systemd/altavms.service reference only; restore never writes itIncluded by default:
altavms.env(secrets). The encryption key that protects every encrypted column — camera and Alta credentials, storage and SMTP secrets, webhook signing keys — exists only in this file. An archive without it can’t decrypt the database it’s paired with, so secrets are included by default; the archive is written0600.maps/. Floor-plan backgrounds are the only operator-uploaded files outside the database, and the database rows referencing them travel in the same archive — leaving the images out would make a “successful” restore quietly produce maps with missing backgrounds.
Excluded, with the reason recorded in the manifest:
- Clips and screenshots — retention-managed and regenerable; including them would make routine backups multi-gigabyte.
- HLS recordings — they live on the Alta server’s own storage, never on the VMS host.
- The binary — its version is recorded in the manifest, but a backup is a data rollback, not a code rollback.
Restoring
Section titled “Restoring”sudo altavms restore /root/altavms-backup-<host>-<timestamp>.tar.gzThe sequence is deliberately careful:
- Everything is verified before anything on disk changes — the manifest, every file’s checksum, and the archive’s contents are checked before any write. Treat an archive from someone else as you would any untrusted file.
- Schema check. An archive from a newer build is refused outright — upgrade the binary first. An older archive restores with a warning: the service will forward-migrate it on next start, which is irreversible.
- Key check. If the archive has no
altavms.env, its recorded encryption-key ids must match a key you currently hold, or the restore refuses (--force-key-mismatchoverrides this). - Refuses while the service is running. Pass
--stop-serviceto have it stop the service for you — restore never starts it back up afterward, so problems surface before the service does. - Typed confirmation. You must type
restore <this hostname>to proceed — a runbook command pasted onto the wrong machine fails instead of running. - A safety backup of the current state is taken first. If that fails, nothing else happens.
- Files are replaced, stale WAL sidecars are removed, and the restored database’s schema is verified — any failure at this stage rolls everything back.
Afterwards, bring the service back up yourself:
sudo altavms doctorsudo altavms startsudo altavms statusaltavms doctor reminds you to delete the pre-restore-* safety archive once you’re satisfied the restore is good.
The restore drill
Section titled “The restore drill”A backup nobody has restored is not a backup. Run this quarterly:
sudo altavms restore <latest-archive> --dry-run--dry-run runs the full verification — manifest, checksums, schema, and key compatibility — and prints what it would do without writing anything. It proves the archive is intact and restorable on the machine that would actually need it.
Cross-host restore
Section titled “Cross-host restore”Restoring onto different hardware is supported — the command warns when the archive comes from another host, and because the typed confirmation always names the host you’re currently on, a runbook line copied to the wrong machine still fails safely. After a cross-host restore, review http.allowed_origins in the restored config before starting — it may still name the old host.
Scheduling
Section titled “Scheduling”A cron line is enough; the command needs no coordination with the running service:
15 3 * * * root /usr/local/bin/altavms backup --output /var/backups/altavms/ >>/var/log/altavms-backup.log 2>&1Rotate old archives yourself, e.g.:
find /var/backups/altavms -name 'altavms-backup-*.tar.gz' -mtime +30 -deleteEach archive contains your encryption key by default — apply the same access controls to your backup storage that you apply to /etc/altavms/altavms.env.