メインコンテンツまでスキップ

Backup and Restore

Admin → Backup (/admin/backup) is where you configure the built-in backup worker, watch that it is actually running, and — in an emergency — request a restore.

Two menu entries lead here:

Menu entryWhat it isPermission
BackupThe screen itselfperm:backup:admin
Restore (child of Backup)Not a separate screen. The row exists only to carry the restore permission; the restore action appears on the snapshot list of the Backup screen for users who hold it.perm:backup:restore

There is no admin bypass: without perm:backup:admin the screen is not reachable at all, and without perm:backup:restore the restore action is not rendered and the restore endpoints refuse the call. Downloading a snapshot additionally requires perm:backup:export.

Before you start​

Backups are executed by the dedicated opsee-backup container, not by the application. That container ships idle — a fresh install never silently writes backups nowhere. See Deployment Overview and, for the closed bundle, Closed Release. If the container is not running, the settings on this screen are stored but nothing acts on them.

Credentials you enter here are encrypted with the server's MASTER_ENCRYPTION_KEY. If that key is missing or invalid, the screen shows a banner saying credential storage is unavailable and existing backups keep running from their legacy environment references.

The three tabs​

TabContents
OverviewThe "am I protected?" summary — last successful backup, next scheduled run, destination, snapshot count and retention — plus the read-only snapshot list.
HistoryBackup requests and restore requests, with their status and messages.
SettingsSchedule, retention, destination and credentials.

The active tab and the History filter are kept in the URL (?tab=, ?history=), so a link to a specific view can be shared.

Configuring backups​

Everything below lives on the Settings tab. The Save configuration button stays disabled until something changes, and leaving the page with unsaved changes asks for confirmation.

Schedule​

  • Enabled — the master switch. While off, the Overview shows Backups are disabled.
  • Start hour (UTC) and Interval — backups run every N hours from the start hour. The interval must divide 24, so the choices are 1, 2, 3, 6, 12 and 24 hours. The screen previews the resulting slots in your local time and in UTC.
  • Leaving the schedule unset means backups only run manually, from the Request backup button.
  • Stale after (hours) is only an alert threshold: a backup older than this is flagged Stale on the Overview. It does not trigger anything.

Retention​

Keep daily, Keep weekly and Keep monthly define how many snapshots survive. Older snapshots are removed automatically by the worker; the Overview restates the rule in words and shows when it was last applied.

Destination​

Pick a Destination type; the form then asks only for the fields that type needs. All types write a restic repository, so the data is encrypted before it leaves the container — the destination only ever holds ciphertext. Every type therefore needs a Repository password in the Credential section.

Destination typeFields you must supplyCredential
Encrypted local folderPath is fixed to /var/opsee/backups inside the backup container (the infra_opsee-backup-local docker volume)Repository password
SFTP serverHost, port (default 22), username, pathSSH private key
S3 / object storageBucket, endpoint URL, region, path/prefixAWS access key ID + secret access key
SMB / Windows shareHost, share name, username, optional folder, port (default 445), optional domain/workgroupDestination password
FTPS (FTP over TLS)Host, port (default 21), pathDestination password
SFTP (password)Host, port (default 22), username, pathDestination password
WebDAV (HTTPS)Endpoint URL (must start with https://), optional username, optional sub-folderDestination password

The last four go through rclone and are encrypted transports only: plain FTP, SMB1 and http:// WebDAV are not offered at all, not even as a toggle.

To change where a local folder backup physically lands on the host, override the docker volume — the in-container path is deliberately locked in the UI, because any other value would be written to the container's ephemeral layer and lost on the next rebuild.

Credentials​

Credentials are write-only. Once saved, the screen shows Set; the API never returns the stored value. Use Replace to enter a new one and Clear to remove it — clearing warns you that backups will fail until a new credential is provided.

Switching destination type clears nothing automatically but does prompt you to re-enter the credentials the new type needs.

If required fields are missing, the Save area lists them ("Destination required: …", "Credentials required: …") instead of failing silently.

Running a backup on demand​

Request backup (top right) queues a request; the backup host picks it up on its next cycle. It does not run a backup immediately, and it is never a restore.

Queued and finished requests appear under History, with their origin (Scheduled or Manual), status, duration and message. From there you can:

  • Cancel a pending request. In-flight and finished requests are unaffected.
  • Clear history — permanently deletes done, failed and cancelled rows older than a threshold you choose (1–3650 days, default 30). Pending and in-progress requests are never deleted.

Verifying that you are protected​

The Overview tab is the check:

  • Last successful backup — with a Stale chip when it is older than the stale threshold.
  • Next scheduled backup — the next slot, or No schedule set.
  • Snapshots — how many exist in the repository and the size of the newest.

The snapshot list is the authoritative proof that data actually reached the destination: it is read from the repository itself (cached, refreshed roughly every 15 minutes) and shows the snapshot ID, creation time, host, size and tags. An empty list with a green schedule means the worker is not writing where you think it is — check its logs on Workers and System Logs.

There is deliberately no "test restore" button. The only true verification of a restore is running one against a throwaway or staging environment.

Downloading a snapshot​

The download action on a snapshot row asks the worker to stage a .tar.gz export and then downloads it. It can take a while for a large backup, only one export runs at a time, and the prepared link expires — start it again if it does. This is a download, not a restore; it requires perm:backup:export because it is full-database egress.

Deleting a snapshot​

The delete action permanently removes that snapshot from the backup repository. It is irreversible — the repository has no trash — and you must type the snapshot ID to confirm. It removes a restore point only: no live OpSee or Keycloak data is touched.

Restore​

:::danger A restore destroys data A restore drops and recreates the live OpSee and Keycloak databases and reloads them from the snapshot. Everything created since that snapshot is permanently lost. There is no undo. :::

Restore is emergency-only, opt-in and operator-assisted. Requesting one from this screen only queues it — it is not a one-click restore, and a request sitting at Pending (awaiting operator) is the normal, expected state.

Requesting a restore​

Visible only to users with perm:backup:restore.

  1. On the Overview tab, find the snapshot in the snapshot list and use its restore action.
  2. The dialog restates the warning and shows the snapshot ID, creation time, source host and size.
  3. Type the snapshot ID exactly to confirm.
  4. Leave Create a fresh backup before restoring ticked (recommended) so the current databases are captured before they are overwritten.
  5. Request restore. Track it under History → Restore requests.

A pending restore can be cancelled from the same list, as long as it has not started.

Why a request stays pending​

The restore worker runs only when three independent gates all hold:

GateSet where
The BACKUP_RESTORE_ENABLED system parameter is true (defaults to false)System Parameters — while false the worker never even claims the request
RESTORE_DB_SUPERUSER and RESTORE_DB_SUPERUSER_PASSWORD are present in the opsee-backup container's environmentServer-side, for the duration of the restore window only
The snapshot's source host matches this instanceAutomatic — the worker refuses a snapshot taken on another environment

When the first gate is off, the screen says so explicitly: "Restore requests will stay pending: the restore worker is disabled on this instance."

The application must also be stopped before the restore runs, and the restore superuser must be removed again afterwards. The full sequence — stop the stack, enable the gate, run, restart, verify, tear the opt-in back down — is in the repository runbook docs/runbooks/restore-from-backup.md. Do not improvise around it.

Restore applies to the full self-hosted Compose and Kubernetes stacks only. Edge and local stacks do not run the backup worker, so there is no restore path there.

  • Workers — the backup worker's health, interval and last error
  • System Logs — what the backup worker logged, filtered by source
  • System Parameters — BACKUP_RESTORE_ENABLED and the retention parameters
  • Deployment Overview — where the opsee-backup container fits