What a drill does
A restore drill takes a stored backup and:- Checks the object still exists and has the size that was uploaded (detects a deleted or truncated object without downloading it).
- Downloads it and compares its SHA-256 with the checksum recorded at backup time.
- Restores it into a scratch resource that is not attached to any app.
- Validates the result.
- Destroys the scratch resource, whether the drill passed or failed.
Drills run on the control plane’s own Docker daemon. A volume that lives on another node is restored for the drill from the object store, so the drill still proves the backup itself, not that node.
Run one
Dashboard: open Backups and press Prove restore on a row. CLI:drill run waits for the result and exits non-zero when the drill fails, so it works in a script or a cron job.
Automatic drills
Every resource that has a succeeded backup is drilled on its newest backup once perAPP_BACKUP_DRILL_INTERVAL_HOURS (default 168, one week; 0 turns scheduled drills off). The result history is on the Backups page and in levelrail-cli backups drill list.
A failed drill fires the platform-wide restore_drill_failed alert rule. Create it under Alerts like any other rule; it resolves when the next drill of that resource passes. A resource also shows Failing on the Backups page until then.
Read backup health
The Backups page groups every backed up database and app volume by app:
Terminal view:
levelrail-cli backups health.
Restore
Restores never overwrite by default. Pick Restore on a volume row for the wizard, or:app-volume-backups restore, which asks you to type the volume name.
Encrypted backups are decrypted with this control plane’s key. To restore somewhere with no control plane, decrypt by hand:
Encryption and the key
New volume backups are compressed with zstd and encrypted with age on the control plane before upload, so the bucket never sees plaintext. The key is generated on first use and written tobackup-encryption.key in APP_DATA_DIR (override the path with APP_BACKUP_ENCRYPTION_KEY_FILE).
Set APP_BACKUP_ENCRYPTION=off to keep compression but skip encryption. Older backups taken before this feature stay readable; each backup records how it was encoded.
Consistency hooks
A running database’s files are only consistent if it is quiet. Per volume you can set, from the Policy button orlevelrail-cli backups volumes policy set:
- Command before backup: runs inside the app’s container. A non-zero exit fails the backup, so an inconsistent volume is never archived.
- Command after backup: runs afterwards, even if the backup failed.
- Pause the app: freezes the container while the archive streams. It resumes when the upload ends.
Retention
Besides the schedule’s keep-last and age limits, a volume can keep the newest backup of each of the last N days, weeks and months:Budgets
A live volume cannot be re-read from an offset, so a half-uploaded object is aborted and the volume is archived again rather than resumed. If the control plane stops mid-backup, a sweep finishes the row: an object that reached the bucket is checksummed and recorded as succeeded, a missing one is marked failed as interrupted.
Bucket protection
Check buckets (orlevelrail-cli backups protection --refresh) probes each backup target for object lock and versioning, and writes and deletes one small canary object to learn whether the key can delete. The result is also refreshed daily.
Retention needs delete permission, so the key must be able to delete; object lock is what makes that safe. Backup object names include the backup ID, so a new backup never overwrites an old one.
What was tested
These ran against real Docker volumes and a real S3 compatible server (SeaweedFS), no fakes:
Limits: drills for engines other than Postgres, MySQL and MariaDB check the object, not a replay. Object lock and versioning detection depends on the provider answering those API calls; a provider that does not shows as Open.
Next steps
Backups and storage
Configure backup targets and retention policies.
Managing databases
Database backups, restore-as-new, and point-in-time recovery.