review: pin the VPS host key; dump store.db only (no secrets in tarball)
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful

- No TOFU: the CronJob writes a pinned known_hosts (ed25519 key captured
  via ssh-keyscan 2026-07-26 and cross-checked against the workstation's
  trusted entry) and uses StrictHostKeyChecking=yes. A reprovisioned VPS
  makes the job fail loudly — desired.
- The dump now contains ONLY store.db: /opt/netbird/config is fully
  regenerable from the role's templates + vault, and including it put
  the plaintext TURN secret into every nightly tarball. Restore is
  role-run (rebuilds config) + untar into /opt/netbird/management/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 09:26:18 +02:00
co-authored by Claude Fable 5
parent 10489eedd0
commit c9009ffd3f
3 changed files with 24 additions and 12 deletions
@@ -2,13 +2,17 @@
# Forced-command target for the netbird-backup SSH key (see the
# "Authorize the cluster backup key" task): takes a CONSISTENT snapshot
# of the management SQLite store via the online-backup API (safe against
# a live writer, unlike copying store.db) plus the config dir, and
# streams a gzipped tar to stdout. The key's authorized_keys entry is
# restricted to exactly this script — the in-cluster puller cannot run
# anything else with it.
# a live writer, unlike copying store.db) and streams a gzipped tar to
# stdout. The key's authorized_keys entry is restricted to exactly this
# script — the in-cluster puller cannot run anything else.
#
# Deliberately store.db ONLY: /opt/netbird/config is fully regenerable
# from the netbird-server role's templates + vault, and including it
# would put the plaintext TURN secret (turnserver.conf) into every
# nightly tarball. Restore = re-run the role (rebuilds config), then
# untar this dump into /opt/netbird/management/.
set -eu
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
sqlite3 /opt/netbird/management/store.db ".backup '$tmp/store.db'"
cp -a /opt/netbird/config "$tmp/config"
tar -C "$tmp" -czf - store.db config
tar -C "$tmp" -czf - store.db
+5 -2
View File
@@ -84,8 +84,11 @@
# ports closed), so the CLUSTER pulls: a CronJob
# (kubernetes/infrastructure/netbird-backup) ssh's in with a dedicated
# key that is locked to the dump script below, and lands the tarball on
# a Ceph PVC that Velero ships offsite. Restore: untar over
# /opt/netbird/{management,config} after the role rebuilt the stack.
# a Ceph PVC that Velero ships offsite. The dump is store.db ONLY —
# /opt/netbird/config is regenerable from this role's templates + vault
# and would otherwise leak the TURN secret into every tarball. Restore:
# re-run this role (rebuilds config), then untar the dump into
# /opt/netbird/management/.
- name: Install the backup dump script
ansible.builtin.copy:
src: netbird-backup-dump
@@ -46,16 +46,21 @@ spec:
# restrict,command=… — the server runs the dump script
# regardless of what we request, streaming a tar.gz.
# ssh demands 0600 on the key; secret mounts are group-
# readable, so copy first. Known-hosts is TOFU on first
# run, then pinned on the PVC.
# readable, so copy first. The host key is PINNED (no
# TOFU): captured 2026-07-26 via ssh-keyscan and
# cross-checked against the workstation's known_hosts.
# If the VPS is ever reprovisioned with a new host key,
# update this line — the job failing loudly on a key
# mismatch is the desired behavior.
install -m 600 /ssh/ssh-key /tmp/key
printf '%s\n' 'netbird.renner.uno ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKCe8LRXbyn6Y+5V4ia4ErnBEcTFzHI1fAnsTvT77HJU' > /tmp/known_hosts
# Leftover .part files from aborted earlier runs are
# outside the retention glob — clear them up front.
rm -f /backup/*.part
ts=$(date +%Y-%m-%d)
ssh -i /tmp/key \
-o StrictHostKeyChecking=accept-new \
-o UserKnownHostsFile=/backup/.known_hosts \
-o StrictHostKeyChecking=yes \
-o UserKnownHostsFile=/tmp/known_hosts \
-o ConnectTimeout=15 \
root@netbird.renner.uno > "/backup/netbird-$ts.tar.gz.part"
gzip -t "/backup/netbird-$ts.tar.gz.part"