#!/bin/bash # The units that run 'verify' by themselves. # # Sourced by setup_wireguard_ssh.sh; split out to keep wg_firewall.sh under # the 250-line cap. Sourced rather than run, so it inherits the caller's # strict mode and the variables defined above the source line. # # 'verify' gates on two invariants and exits non-zero, but nothing invoked # it. It reported drift only when a human thought to ask -- and the outage it # exists for is precisely the one nobody thinks to ask about. Twice now the # repo has carried the docker0 forward rule while /etc/nftables.conf did not, # and both times a reboot loaded the stale file and cut every bridged # container off the internet while the host itself stayed online, so nothing # looked broken. # # So it runs at boot, just after the ruleset is loaded, and a failure lands in # `systemctl --failed`, where it is visible without being looked for. It must # FAIL, never warn: a warning in the journal is the same as no check at all. readonly VERIFY_SERVICE="nftables-drift.service" readonly VERIFY_TIMER="nftables-drift.timer" readonly SYSTEMD_UNIT_DIR="/etc/systemd/system" # Rendering is separate from installing so the tests can assert the generated # content without a daemon-reload, the same split render/write_nftables uses. # # The ExecStart deliberately points into the repo checkout rather than a copy # under /usr/local/bin. The check is "does /etc match what THIS repo # generates", so a copy would be one more thing that can go stale -- and a # stale copy of a drift detector agrees with the drift. render_verify_units() { local unit_dir="$1" entry="$2" cat >"${unit_dir}/${VERIFY_SERVICE}" <"${unit_dir}/${VERIFY_TIMER}" </dev/null enable_service "$VERIFY_TIMER" log_ok "${VERIFY_SERVICE} will re-check the ruleset at every boot." log_info "A failure shows up in: systemctl --failed" }