Skip to main content

backup

Where config backups are written — local paths, an external disk, and remote destinations through rclone — and whether each one is reachable.

📄️Change a backup destination's enabled flag or retention

Changes `enabled` and `retention` in place; a field left out is left as it is. Its type, path, options and credentials cannot be changed — remove the destination and add it again. Disabling never removes an archive or the credentials, and the next backup run uses the new values without a restart. Retention is bounded as in `createBackupDestination` (each count 0 to 1000, at least one archive kept) and, as always, applies only to archives this installation wrote. Switching a disabled destination back on restarts its staleness clock, so it is not reported stale until two days after that. 404 `backup_destination_not_found` for an unknown id; 400 `backup_destination_invalid` for a retention out of bounds.

📄️Run a restore drill now

Queues a `restore_drill` job (service class), the job the monthly schedule queues. It fetches the newest config archive this installation wrote to each enabled destination, opens it the way a restore would (an encrypted one through its identity sidecar and the backup passphrase alone), checks its checksums and that `state.db` opens and passes `PRAGMA integrity_check`, and discards everything it fetched. It never writes to a destination and never reads the live database. A destination that cannot be read, or holds no archive written by this installation, fails the drill. The result replaces the one `getRestoreDrill` returns, and a failed drill publishes a `restore_drill_failed` notification. A drill behind another one queues rather than failing.

📄️Appdata backup policy

Every container with a bind-mounted directory inside the appdata location (the cache disk's `appdata` directory), each with whether the backup stops it while its directory is copied and whether it is in the backup at all. A container the operator has not configured is stopped and included. A known database image that is not stopped carries `warning`: copying a database's files while it runs can produce an archive that does not restore. 501 `not_configured` when this daemon has no Docker Engine client, and 503 when the Engine is not reachable.

📄️Start an appdata backup

Queues an `appdata_backup` job (service class): every container that is running and set to be stopped is stopped, each included container's appdata directories are archived, one archive per container, on the same device as the appdata location, the stopped containers are started again in reverse order, and only then are the archives verified and written to the enabled backup destinations (never the boot device's default destination, which is too small for appdata). `containers` limits the run to the named containers; omit it for every included one. Refused with 409 `array_stopped` while the array is stopped or its storage is not ready — with the cache disk unmounted the appdata directories are empty — and 404 `container_not_found` for a name that is not in scope. A run that fails publishes an `appdata_backup_failed` notification.

📄️Restore one container's appdata

Queues an `appdata_restore` job (service class). The archive is fetched, decrypted and verified before anything is changed. Then the container is stopped if it is running, a snapshot of its current appdata is written to the enabled backup destinations, and only when that snapshot is written is the appdata replaced by the archive's content; if the snapshot cannot be written the live appdata is not touched. The container is started again afterwards. Requires `confirm: true`: the restore overwrites the container's appdata (400 `confirmation_required` otherwise). 404 `archive_not_found` for an archive the named destination does not hold, and 409 `array_stopped` while the array is stopped or its storage is not ready.

📄️Preview restoring one container's appdata

Queues an `appdata_restore_preview` job (service class, scoped to the container) that reports what `restoreAppdata` would overwrite for the same archive on the same destination, before anything is changed. Read the result with `getAppdataRestorePreview` once the job has succeeded. The job fetches, decrypts and verifies the archive exactly as the restore does and fails with the restore's own error when the archive is corrupt, is another container's, names a directory outside the appdata location, or holds entries a restore could not unpack. It then compares each archived directory with the live one, walking the live appdata only for this job: files present in both are `replaced`, files only in the archive are `added`, and files only in the live appdata are `removed`, because the restore replaces each directory as a whole. It stops no container, writes nothing under the appdata location and leaves no fetched archive on disk, on success or failure. It queues behind a backup or restore of the same container and runs beside those of others. Cancelling it stops the fetch, the reading of the archive and the walk of the live directories; the decryption and the verification read that follow the fetch run to their end first. 404 `archive_not_found` for an archive the named destination does not hold, 404 `backup_destination_not_found`, 400 `appdata_archive_invalid` for a request that names no archive of this installation and container, and 409 `array_stopped` while the array is stopped or its storage is not ready.

📄️Get a restore preview

The result of the `appdata_restore_preview` job `previewAppdataRestore` queued. The daemon holds the sixteen most recent results in memory, so a result is gone after a restart and after sixteen newer previews: preview again. 404 `job_not_found` for an id that is not a restore preview job, 409 `appdata_preview_not_ready` while the job is queued or running, 409 `appdata_preview_failed` when it failed, was cancelled or was interrupted (the message says why; `getJob` and `getJobLog` have the rest), and 404 `appdata_preview_gone` when the job succeeded but its result is no longer held.