Files
vh de1eac2904 restic/nh3-docker: profile + deployment guide
Adds file-level restic for the NH3 Docker VM. Targets the Synology
rest-server (rest-server-nh3 at 10.100.50.50:8000) as user nh3-docker —
site-local writes matching the fleet pattern.

No pre-backup hook needed: none of the stacks on this host (adguard,
dockge, beszel-agent, dozzle-agent, portainer) run relational DBs. The
SQLite state in their named volumes is WAL-mode and restores cleanly
from raw restic capture.

Source paths mirror ana-ml2's template (/opt/docker, /etc, /root,
/var/lib/docker/volumes) with the same exclude list (docker internals,
logs, pids, root's shell/caches). ~1.6 MB of compose files + small
volumes — expected snapshot size a few hundred MB at most, dominated
by any AdGuard query log history.

README walks through reuse (existing repo + htpasswd) vs fresh init
paths, resticprofile install, timer generation, and verification via
the Backrest UI.
2026-04-21 01:13:35 -07:00

4.9 KiB

restic / nh3-docker

VM on nh3-pve at the NH3 site. Backed up two ways:

  • VM image via Proxmox vzdump (covered 5/5 on nh3-pve). Good for full-VM restore after catastrophic failure.
  • File-level restic (this config). Fast per-file restore and site-resilient off-site copy. Writes to the Synology rest-server (10.100.50.50:8000) as user nh3-docker.

What's backed up

Path Purpose
/opt/docker Compose files (~1.6 MB)
/etc Host config — systemd, ssh, chrony, apparmor, apt, etc.
/root Root's ad-hoc scripts, shell history, ssh keys
/var/lib/docker/volumes AdGuard confdir + workdir, beszel-agent, dozzle-agent, dockge state, portainer state

Not backed up

  • *.log, *.pid, .../logs/ directories
  • /root/.cache, /root/.npm, shell-noise caches

No pre-backup hook needed

Unlike ana-docker, nh3-docker runs no relational databases. The volumes captured above contain SQLite files for dockge / beszel-agent / dozzle-agent / portainer — all low-transaction, WAL-mode, and restic's raw-file capture restores cleanly.

AdGuard config lives in /var/lib/docker/volumes/adguard_adguard-confdir/ as plain YAML. No consistency concerns.

Deploy (one-time setup)

1. Check for existing repo + htpasswd

The Synology rest-server at 10.100.50.50 may already have an nh3-docker entry in its .htpasswd and a repo at /nh3-docker/ from an earlier setup pass. See stacks/rest-server-nh3/README.md for the Synology-side layout.

If a repo + htpasswd exist and you have the passphrase: follow the reuse path (skip init, install the existing secrets).

If not: follow the fresh path below.

2. Install restic creds on nh3-docker

ssh -t nh3-docker '
  sudo install -d -o root -g root -m 0700 /etc/restic /var/lib/restic
'

# REST URL (with HTTP basic-auth creds embedded) — paste from password manager
ssh -t nh3-docker 'sudo bash -c "cat > /etc/restic/restic.env && chmod 600 /etc/restic/restic.env"'
# paste: RESTIC_REPOSITORY=rest:http://nh3-docker:<HTPASSWD-PW>@10.100.50.50:8000/nh3-docker/
# Ctrl-D

# Encryption passphrase — paste from password manager
ssh -t nh3-docker 'sudo bash -c "cat > /etc/restic/password && chmod 600 /etc/restic/password"'
# paste: <REPO-PASSPHRASE>
# Ctrl-D

3. Verify creds against the repo

ssh -t nh3-docker '
  sudo bash -c "
    set -a; . /etc/restic/restic.env; set +a
    RESTIC_PASSWORD_FILE=/etc/restic/password restic snapshots
  "
'

Expected: either a list of existing snapshots, or no snapshots found on a fresh repo. Both are fine.

If you get wrong password or no key found, the passphrase doesn't match. Check your password manager or follow the "Recreating the repo" path below.

4. Fresh-init (only if no repo exists yet on the Synology)

ssh -t nh3-docker '
  sudo bash -c "
    set -a; . /etc/restic/restic.env; set +a
    restic init
  "
'
# enter passphrase twice at the prompt

5. Install resticprofile

ssh -t nh3-docker '
  curl -sfL https://raw.githubusercontent.com/creativeprojects/resticprofile/master/install.sh \
    | sudo sh -s -- -b /usr/local/bin
  /usr/local/bin/resticprofile version
'

6. Deploy the profile

scp configs/restic/nh3-docker/profiles.yaml nh3-docker:/tmp/profiles.yaml

ssh -t nh3-docker '
  sudo install -o root -g root -m 0644 /tmp/profiles.yaml /etc/restic/profiles.yaml &&
  rm /tmp/profiles.yaml &&
  sudo resticprofile --config /etc/restic/profiles.yaml show
'

7. Enable systemd timers

ssh -t nh3-docker '
  sudo resticprofile --config /etc/restic/profiles.yaml schedule --all &&
  systemctl list-timers "resticprofile*"
'

8. First backup

ssh -t nh3-docker 'sudo resticprofile --config /etc/restic/profiles.yaml backup --verbose'

Expected size: a few hundred MB (adguard's data dir can hold cache + query log, which is the bulk). If you see >2 GB on first run, check for old AdGuard query logs under /var/lib/docker/volumes/adguard_adguard-workdir/ and decide whether to exclude them.

Verify in Backrest UI (http://10.250.50.70:9898) — nh3-docker repo should show the new snapshot within a minute.

Restoring

ssh -t nh3-docker '
  sudo bash -c "
    set -a; . /etc/restic/restic.env; set +a
    RESTIC_PASSWORD_FILE=/etc/restic/password \
      restic restore --target /tmp/restore latest --path /opt/docker
  "
'

Recreating the repo (lost passphrase)

Same pattern as ana-ml2 but targets the Synology rest-server. See configs/restic/ana-ml2/README.md for the wipe-and-reinit recipe; substitute:

  • rest-server host 10.100.50.50 instead of 10.250.50.70
  • repo path /nh3-docker/ under the Synology's rest-server data root (location depends on that stack's DATA_DIR — see stacks/rest-server-nh3/README.md)
  • SSH into the Synology directly requires enabling SSH in DSM + key setup (tabled in an earlier session)