ks4/incus-copy: finish the nuc -> nas migration of leg 2

ef88ef9 updated the headings but left the body describing the old setup,
so the two docs contradicted each other on the same procedure.

The one that would actually have failed: `incus storage create ks4backup
zfs source=usb4t/backup/ks4` — that pool no longer exists, the disk moved
to nas and the pool was renamed to `tank` on import. Also corrects the
WireGuard peer (nas is 10.8.0.22/32, not nuc's 10.8.0.20/32, which is
retired once nas is seeded), the host for the cron and the restore test,
and drops the "replicas live only on the USB drive" framing — direct SATA
was the entire point of the rebuild.

Adds a pointer to ks2/nas-seed.md as the authoritative seed procedure.
Historical notes (the 2026-08-09 verification, the homeassistant VM
measurement) are left as-is: they are dated observations, not steps.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Julien Lutran
2026-08-31 10:29:06 +02:00
co-authored by Claude Opus 5
parent 81d22c5daf
commit 3c6b762038
+30 -15
View File
@@ -9,7 +9,7 @@ push to `ks2` (decommissioning):
1. **local** — replicas + dumps on a dedicated `backup` zpool on ks4's 1. **local** — replicas + dumps on a dedicated `backup` zpool on ks4's
second disk (`sdb5`), survives `sda` death second disk (`sdb5`), survives `sda` death
2. **off-site** — replicas pulled by **nas** into pool `ks4backup` 2. **off-site** — replicas pulled by **nas** into pool `ks4backup`
(dataset `usb4t/backup/ks4`), survives losing ks4 entirely (dataset `tank/backup/ks4`), survives losing ks4 entirely
## The script ## The script
@@ -76,22 +76,29 @@ the live containers' static `192.168.1.x` addresses.
## Leg 2 — off-site pull from nas (was nuc until 2026-08-30) ## Leg 2 — off-site pull from nas (was nuc until 2026-08-30)
Storage pool on nuc (done 2026-08-09): `ks4backup`, backed by the Storage pool on **nas** (recreated 2026-08-30): `ks4backup`, backed by
dataset `usb4t/backup/ks4` on the USB 4 TB pool (quota on `usb4t/backup` the dataset `tank/backup/ks4` the same 4 TB disk, now on **direct
removed 2026-08-09 — full replica set is ~1.75 TiB): SATA** instead of the USB enclosure whose bridge kept suspending the pool
([nuc/usb4t-dropouts.md](../nuc/usb4t-dropouts.md)). Full replica set is
~1.75 TiB.
```sh ```sh
incus storage create ks4backup zfs source=usb4t/backup/ks4 incus storage create ks4backup zfs source=tank/backup/ks4
``` ```
Replicas live only on the USB drive — if it fails, only backups are ⚠️ Originally this lived on nuc as `usb4t/backup/ks4`. That pool no
lost; nuc's own instances (pool `data` on the SSD) are unaffected. longer exists — the disk moved to nas and the pool was renamed on import
([nas/nas-install.md](../nas/nas-install.md) §5b). Following the old
command fails with "no such pool".
`tank` is a single vdev, so if the disk fails only backups are lost —
nas's own instances live on the `incus` SSD mirror and are unaffected.
**Direction: nas pulls, through the WireGuard tunnel.** Verified **Direction: nas pulls, through the WireGuard tunnel.** Verified
2026-08-09: ks4's API listens on wildcard `:8443` (so it answers on 2026-08-09: ks4's API listens on wildcard `:8443` (so it answers on
`192.168.1.1`, the `incusbr0` host address) but is **firewalled from `192.168.1.1`, the `incusbr0` host address) but is **firewalled from
the internet** — the VPN path keeps it that way, needs no inbound port the internet** — the VPN path keeps it that way, needs no inbound port
at home, and doesn't care that nuc's public IP is dynamic. The at home, and doesn't care that the home public IP is dynamic. The
`wireguard` container (`192.168.1.18`, `wg0` `10.8.0.1/24`) is exposed `wireguard` container (`192.168.1.18`, `wg0` `10.8.0.1/24`) is exposed
via a proxy device on public UDP `51845`. via a proxy device on public UDP `51845`.
@@ -99,13 +106,16 @@ Setup (✅ **done 2026-08-09**, verified end-to-end with
`incus list ks4:` from nuc): `incus list ks4:` from nuc):
- **wireguard container** (ks4): forwards + masquerades wg0→eth0 - **wireguard container** (ks4): forwards + masquerades wg0→eth0
(pre-existing); nuc added as peer `10.8.0.20/32` (pre-existing). **nas** is the peer for this leg —
(`wg set wg0 peer 31Tlgloc… allowed-ips 10.8.0.20/32` + `wg set wg0 peer <nas-pubkey> allowed-ips 10.8.0.22/32` +
`wg-quick save wg0`). `wg-quick save wg0`. (`10.8.0.20/32` was nuc's peer for the same leg
and is retired once nas is seeded; `10.8.0.21` is transmission-bt's
own in-container tunnel and is unrelated.)
- **ufw** (ks4): `ufw allow in on incusbr0 from 192.168.1.18 to any - **ufw** (ks4): `ufw allow in on incusbr0 from 192.168.1.18 to any
port 8443 proto tcp` — the API stays firewalled from the internet port 8443 proto tcp` — the API stays firewalled from the internet
and the connection arrives masqueraded as the WG container. and the connection arrives masqueraded as the WG container.
- **nuc**: `/etc/wireguard/wg-ks4.conf` (`wg-quick@wg-ks4` enabled; - **nas**: `/etc/wireguard/wg-ks4.conf` (`wg-quick@wg-ks4` enabled,
`Address = 10.8.0.22/32`;
peer = container pubkey `TVs6d7…`, endpoint `193.70.35.17:51845`, peer = container pubkey `TVs6d7…`, endpoint `193.70.35.17:51845`,
`AllowedIPs = 10.8.0.0/24, 192.168.1.1/32`, keepalive 25s) and `AllowedIPs = 10.8.0.0/24, 192.168.1.1/32`, keepalive 25s) and
`incus remote add ks4 https://192.168.1.1:8443 --accept-certificate `incus remote add ks4 https://192.168.1.1:8443 --accept-certificate
@@ -117,7 +127,8 @@ container over its own tunnel is fine (crash-consistent, tiny, no
interruption); if the tunnel is down the cron job fails loudly instead interruption); if the tunnel is down the cron job fails loudly instead
of hanging. of hanging.
Then cron (root on nuc) — stagger after ks4's local leg: Then cron (root on **nas**) — stagger after ks4's local leg and after
nas's own 04:00 local replication:
```cron ```cron
30 2 * * * /root/scripts/incus-copy.sh -r ks4 -s ks4backup >> /var/log/incus-copy.log 2>&1 30 2 * * * /root/scripts/incus-copy.sh -r ks4 -s ks4backup >> /var/log/incus-copy.log 2>&1
@@ -130,7 +141,7 @@ cron once it completes.
## Cutover checklist (then kill ks2) ## Cutover checklist (then kill ks2)
1. First full cycle of all three jobs clean (logs above). 1. First full cycle of all three jobs clean (logs above).
2. Restore test: on nuc, start a small replica (e.g. `freshrss`) with 2. Restore test: on nas, start a small replica (e.g. `freshrss`) with
its NIC detached, check app data, then stop it. its NIC detached, check app data, then stop it.
3. Remove both ks2 cron lines on ks4, `incus remote remove ks2`, 3. Remove both ks2 cron lines on ks4, `incus remote remove ks2`,
cancel the server (`164.132.173.57` = ks2, rsync target of the old cancel the server (`164.132.173.57` = ks2, rsync target of the old
@@ -139,11 +150,15 @@ cron once it completes.
## Restore ## Restore
```sh ```sh
# from nuc (off-site replica): # from nas (off-site replica):
incus copy <instance> ks4:<instance> --mode push incus copy <instance> ks4:<instance> --mode push
# from the local backup project (sda replaced, pool data rebuilt): # from the local backup project (sda replaced, pool data rebuilt):
incus copy <instance> <instance> --project backup --target-project default -s data incus copy <instance> <instance> --project backup --target-project default -s data
``` ```
The step-by-step seed procedure, including the WireGuard move and the
gate it depends on, is [ks2/nas-seed.md](../ks2/nas-seed.md) — that is
the authoritative version for this leg.
Remember replicas have `boot.autostart=false`; re-enable after a real Remember replicas have `boot.autostart=false`; re-enable after a real
failover, and re-check it after copying back to ks4. failover, and re-check it after copying back to ks4.