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.
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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)
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
ssh -t nh3-docker '
|
||||
sudo resticprofile --config /etc/restic/profiles.yaml schedule --all &&
|
||||
systemctl list-timers "resticprofile*"
|
||||
'
|
||||
```
|
||||
|
||||
### 8. First backup
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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)
|
||||
@@ -0,0 +1,79 @@
|
||||
# resticprofile config for nh3-docker.
|
||||
#
|
||||
# nh3-docker is a VM on nh3-pve, so its disk image IS captured by vzdump
|
||||
# at the hypervisor layer. This file-level restic is additive: it gives
|
||||
# fast per-file restore without mounting the VM image, and ships to the
|
||||
# site-local rest-server for location-resilient recovery.
|
||||
#
|
||||
# Writes to the Synology rest-server at 10.100.50.50:8000 as user
|
||||
# `nh3-docker`. The full REST URL (with HTTP basic-auth creds) lives in
|
||||
# /etc/restic/restic.env. The client-side encryption passphrase lives in
|
||||
# /etc/restic/password.
|
||||
#
|
||||
# No DB dumps needed. None of the stacks on this host (adguard, dockge,
|
||||
# beszel-agent, dozzle-agent, portainer) run a relational DB — AdGuard
|
||||
# stores config as YAML, the rest use tiny SQLite state in their volumes
|
||||
# which restic captures raw (WAL-mode SQLite recovers cleanly).
|
||||
|
||||
version: "1"
|
||||
|
||||
global:
|
||||
priority: low
|
||||
ionice: true
|
||||
ionice-class: 2
|
||||
ionice-level: 7
|
||||
min-memory: 100
|
||||
|
||||
default:
|
||||
env-file: /etc/restic/restic.env # RESTIC_REPOSITORY=rest:http://user:pw@…
|
||||
env:
|
||||
RESTIC_PASSWORD_FILE: /etc/restic/password
|
||||
initialize: false # repo created manually by `restic init`
|
||||
lock: /var/lock/restic-nh3-docker.lock
|
||||
|
||||
backup:
|
||||
verbose: 1
|
||||
run-after:
|
||||
- date +%s > /var/lib/restic/last-success
|
||||
source:
|
||||
- /opt/docker # compose files (~1.6 MB on this host)
|
||||
- /etc # host config (systemd, adguard upstream config, etc.)
|
||||
- /root # root shell history, ssh keys, ad-hoc scripts
|
||||
- /var/lib/docker/volumes # adguard config, agent state, dockge state, etc.
|
||||
exclude:
|
||||
- /var/lib/docker/volumes/backingFsBlockDev
|
||||
- /var/lib/docker/volumes/metadata.db
|
||||
- /opt/docker/compose/*/logs
|
||||
- "**/*.log"
|
||||
- "**/*.log.*"
|
||||
- "**/*.pid"
|
||||
- /root/.cache
|
||||
- /root/.local/share/Trash
|
||||
- /root/.npm
|
||||
- /root/.python_history
|
||||
tag:
|
||||
- host:nh3-docker
|
||||
- site:nh3
|
||||
- fleet:pfi
|
||||
schedule: "*-*-* 01:00:00"
|
||||
schedule-permission: system
|
||||
schedule-log: /var/log/restic-backup.log
|
||||
|
||||
forget:
|
||||
keep-daily: 7
|
||||
keep-weekly: 4
|
||||
keep-monthly: 12
|
||||
keep-yearly: 3
|
||||
# NOTE: no `prune: true` — rest-server runs with --append-only on both
|
||||
# sites. See README.md "Prune ceremony".
|
||||
tag:
|
||||
- host:nh3-docker
|
||||
schedule: "*-*-* 03:00:00"
|
||||
schedule-permission: system
|
||||
schedule-log: /var/log/restic-forget.log
|
||||
|
||||
check:
|
||||
read-data-subset: 10%
|
||||
schedule: "Sun *-*-* 05:00:00"
|
||||
schedule-permission: system
|
||||
schedule-log: /var/log/restic-check.log
|
||||
Reference in New Issue
Block a user