Restore and Validation
The restore flow has one core goal: validate first, replace second, and never let attachment failures pollute the database.
Supported restore sources
- Upload a local backup ZIP.
- Select a ZIP from a remote WebDAV or S3 target.
Remote restore can browse remote directories in the backup center. Only .zip files can be selected. The server rejects empty paths, directory paths, and non-ZIP paths.
File name hash verification
Backup file names look like:
nodewarden_backup_20260510_031500_abc12.zipThe last 5 characters are the first 5 characters of the ZIP SHA-256. During import, the server recalculates the hash and rejects by default if it does not match.
Administrators can choose to allow a hash mismatch, but the decision is written to the audit log as checksumMismatchAccepted.
ZIP parsing
parseBackupArchive() checks:
- ZIP total size must not exceed the current limit.
- Unzipped total size must not exceed the current limit.
- Entry count must not be too high.
manifest.jsonanddb.jsonmust exist.- Manifest
formatVersionmust be supported. db.jsonmust be valid JSON.- If attachments are inline in the ZIP, every required attachment file must exist.
Content validation
validateBackupPayloadContents() checks:
- Users must have
idandemail. - User IDs must be unique.
- Config keys cannot be empty.
- Revisions must point to existing users.
- Domain settings must point to existing users, and each user can have at most one row.
- Folders must point to existing users, and folder IDs must be unique.
- Ciphers must point to existing users.
- Cipher
folder_idmust exist when present. - Attachments must point to existing ciphers.
- Each attachment must have a corresponding file or remote blob reference.
Fresh instance protection
By default, restore requires the target instance to have no vault or Send data. The server checks:
ciphersfoldersattachmentssends
If data already exists and replace-existing is not selected, restore returns a conflict.
Shadow table restore
Restore does not directly delete official tables and insert backup rows. The flow is:
- Delete old shadow tables.
- Create shadow tables from the current official table
CREATE SQL. - Insert backup rows into shadow tables.
- Validate shadow table row counts.
- Restore attachment blobs.
- Remove rows for attachments that failed to restore from the shadow table.
- Validate shadow table row counts again.
- Clear official tables.
- Insert shadow table contents into official tables.
- Delete shadow tables.
If restore fails before the replacement phase, official data has not been cleared.
Attachment recovery policy
Attachment recovery adapts to the target storage:
- R2: write directly.
- KV: skip attachments larger than 25 MiB.
- No attachment storage: skip all attachments.
When attachments are skipped, the server returns a skipped list and removes those rows from the restored attachments table so the frontend does not show non-existent files.
Cleanup after replace restore
If replace-existing is selected, after restore succeeds NodeWarden compares attachment blob keys before and after restore. Blobs from the old vault that are no longer referenced are cleaned up to avoid orphan storage.
Cleanup failure does not roll back database restore, but NodeWarden still attempts it.