From 038017d9eb523dbca58ad223df7186e346e2dea1 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sun, 4 Oct 2026 21:15:34 +0200 Subject: [PATCH] wg firewall: replace only inet filter (no docker restart), persist DoT 853 via ALLOW_DOT Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Cqv4ckcaStUFpUkcJKmmNz --- ...-no-docker-restart-dot-853-2026-10-04.json | 16 +++ ...r-serialise-under-pressure-2026-08-23.json | 44 -------- ...-no-docker-restart-dot-853-2026-10-04.json | 41 +++++++ .../features/lib/dot_resolver_install.sh | 10 +- .../lib/tests/test_dot_resolver_install.sh | 36 +++--- .../features/lib/tests/test_wg_firewall.sh | 103 ++++++++++++++++++ .../features/lib/wg_firewall.sh | 44 ++++++-- linux_configuration/features/lib/wg_sshd.sh | 1 + .../features/setup_wireguard_ssh.sh | 8 +- 9 files changed, 226 insertions(+), 77 deletions(-) create mode 100644 docs/superpowers/contracts/wg-firewall-no-docker-restart-dot-853-2026-10-04.json delete mode 100644 docs/superpowers/evidence/ci-mirror-serialise-under-pressure-2026-08-23.json create mode 100644 docs/superpowers/evidence/wg-firewall-no-docker-restart-dot-853-2026-10-04.json create mode 100755 linux_configuration/features/lib/tests/test_wg_firewall.sh diff --git a/docs/superpowers/contracts/wg-firewall-no-docker-restart-dot-853-2026-10-04.json b/docs/superpowers/contracts/wg-firewall-no-docker-restart-dot-853-2026-10-04.json new file mode 100644 index 00000000..fad9c26e --- /dev/null +++ b/docs/superpowers/contracts/wg-firewall-no-docker-restart-dot-853-2026-10-04.json @@ -0,0 +1,16 @@ +{ + "title": "Firewall applies leave Docker alone; DoT 853 persisted", + "objective": "Any setup_wireguard_ssh.sh allow-* apply must replace only the inet filter table, never restart docker or its containers while docker's own rules are intact, and keep tcp/853 on wg0 (DoT) across every re-apply and reboot via a persisted ALLOW_DOT flag.", + "acceptance_criteria": [ + "Rendered ruleset has no 'flush ruleset' and declares-then-deletes inet filter before defining it (test_wg_firewall.sh)", + "restore_docker_rules restarts docker only when 'iptables -t nat -S DOCKER' fails (test_wg_firewall.sh)", + "ALLOW_DOT=true renders iifname wg0 tcp dport 853 accept; open_firewall goes through allow-dot (test_wg_firewall.sh, test_dot_resolver_install.sh)", + "vmbox: re-apply leaves docker, a probe container and a foreign nft table untouched; first-boot load works", + "Host: allow-dot applied with docker and gitea-caddy start times unchanged; verify reports no drift" + ], + "out_of_scope": [ + "The publicly bound DoT branch's runtime rate-limited rule", + "Changing which ports are open beyond adding 853 on wg0" + ], + "verifier": "lib/tests/run_all.sh in shell_coverage_jail.sh, vmbox guest dotfw, setup_wireguard_ssh.sh verify on the host" +} diff --git a/docs/superpowers/evidence/ci-mirror-serialise-under-pressure-2026-08-23.json b/docs/superpowers/evidence/ci-mirror-serialise-under-pressure-2026-08-23.json deleted file mode 100644 index 61c02c7b..00000000 --- a/docs/superpowers/evidence/ci-mirror-serialise-under-pressure-2026-08-23.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "intent": "Stop the pre-push gate failing with 'tests passed, then Killed' when the machine is under memory pressure, so a push is blocked by the code and not by unrelated load.", - "scope": [ - "meta/scripts/ci_mirror.sh - run the two heavy gates serially when memory is tight", - "meta/scripts/ci_mirror_mem.sh - new lib holding the probe, the threshold and the predicate", - "Non-goal: the 2G pytest cap in pytest_changed_packages.py, which measurement showed is correct and was left alone." - ], - "changes": [ - "Diagnosed the real cause: ci_mirror.sh runs `pre-commit run --all-files` and the pytest gate concurrently with & and wait. Measured tree peaks are ~1.75 GiB for pre-commit (mypy/pylint repo-wide) and ~0.29 GiB for pytest, so the pair wants ~2 GiB at the same instant. The pytest scope runs under MemoryMax=2G with MemorySwapMax=0, so under pressure it is the one the kernel kills - the log reads '1798 passed' then 'Killed', which the gate reports as a test failure.", - "Added available_mem_mib (reads MemAvailable from /proc, no fork) and should_serialise_gates, and made the concurrency conditional on it. Above 4 GiB available the fast parallel path is unchanged.", - "Extracted the probe into ci_mirror_mem.sh following the existing ci_mirror_range.sh / ci_mirror_shell.sh pattern, which also kept ci_mirror.sh under the 250-line cap (245).", - "Exposed the threshold as a predicate rather than a bare constant so SC2034 is resolved by giving the value a real use in its own file, not by a suppression." - ], - "verification": [ - { - "command": "systemd-run --scope -p MemoryMax=2G -p MemorySwapMax=0 /usr/bin/time -v python -m pytest ... (live tree and clean worktree)", - "result": "pass", - "evidence": "1798 passed, Maximum RSS 293928 KB (~0.29 GiB) both times. Proves the suite is nowhere near its own 2G ceiling, so the ceiling was not the problem and did not need raising." - }, - { - "command": "systemd-run --scope -p MemoryMax=8G bash -c 'pre-commit run --all-files; cat .../memory.peak'", - "result": "pass", - "evidence": "1751576576 bytes = ~1.75 GiB across the process tree. /usr/bin/time reported only ~0.29 GiB because it measures the parent, not the forked mypy/pylint children - the cgroup peak is the honest number." - }, - { - "command": "Stubbed available_mem_mib at 1000 and 99999 MiB against should_serialise_gates", - "result": "pass", - "evidence": "1000 -> SERIAL, 99999 -> PARALLEL. Boundary table also checked: 4095 SERIAL, 4096 PARALLEL. Confirms the new branch is reachable and not dead code." - }, - { - "command": "pre-commit run --files meta/scripts/ci_mirror.sh meta/scripts/ci_mirror_mem.sh", - "result": "pass", - "evidence": "No failures. file-length-cap satisfied at 245 lines; SC2034 resolved without a suppression." - } - ], - "risks": [ - "Under 4 GiB available the gate is slower, since the stages no longer overlap. That is the intended trade against a false failure.", - "MemAvailable is a snapshot: memory can be consumed after the check by another process, so this reduces the failure window rather than closing it absolutely. The 2G cap with MemorySwapMax=0 still bounds the damage to a clean kill rather than zram thrashing." - ], - "rollback": [ - "git revert the commit and delete meta/scripts/ci_mirror_mem.sh; the gate returns to unconditional concurrency.", - "After rollback, confirm ci_mirror.sh still sources cleanly (bash -n) and that a push runs the gate." - ] -} diff --git a/docs/superpowers/evidence/wg-firewall-no-docker-restart-dot-853-2026-10-04.json b/docs/superpowers/evidence/wg-firewall-no-docker-restart-dot-853-2026-10-04.json new file mode 100644 index 00000000..5838cf83 --- /dev/null +++ b/docs/superpowers/evidence/wg-firewall-no-docker-restart-dot-853-2026-10-04.json @@ -0,0 +1,41 @@ +{ + "intent": "A firewall apply (setup_wireguard_ssh.sh allow-*) no longer bounces Docker and its containers, and the DoT rule (tcp/853 on wg0) survives every re-apply instead of vanishing.", + "scope": [ + "linux_configuration/features/lib/wg_firewall.sh: ruleset replaces only 'table inet filter'; restore_docker_rules restarts docker only when its nat DOCKER chain is gone; ALLOW_DOT renders 853 on wg0; allow_dot()", + "linux_configuration/features/setup_wireguard_ssh.sh, lib/wg_sshd.sh: ALLOW_DOT default/save_config, allow-dot subcommand and usage", + "linux_configuration/features/lib/dot_resolver_install.sh: wg-bound branch goes through 'setup_wireguard_ssh.sh allow-dot' instead of a runtime 'nft add rule'", + "Tests: new lib/tests/test_wg_firewall.sh; test_dot_resolver_install.sh wg-branch cases rewritten", + "Non-goal: the publicly bound DoT branch still adds its rate-limited rule at runtime" + ], + "changes": [ + "'flush ruleset' replaced by 'table inet filter' + 'delete table inet filter' before the definition: atomic, leaves Docker's (iptables-nft) and Tailscale's tables alone, and loads on a first boot", + "restore_docker_rules checks 'iptables -t nat -S DOCKER' and only restarts docker when that chain is missing", + "sshd-death rollback deletes only inet filter instead of flushing the whole ruleset", + "ALLOW_DOT persisted in .wireguard_ssh.conf; open_firewall calls allow-dot so the rule is rendered on every apply" + ], + "verification": [ + { + "command": "vmbox guest dotfw (iptables-nft, docker 29 + busybox probe, an extra 'inet sentinel' table): old HEAD allow-homeassistant vs new allow-dot", + "result": "pass", + "evidence": "old: all non-inet-filter tables deleted, docker + probe restarted; new re-apply from healthy state: docker ActiveEnterTimestamp and probe StartedAt unchanged, sentinel and docker tables kept; verify clean; systemctl restart nftables and first-boot load (no table) rc=0" + }, + { + "command": "sudo setup_wireguard_ssh.sh allow-dot (host, iptables legacy)", + "result": "pass", + "evidence": "'docker's own firewall rules are intact; containers untouched'; docker since 2026-09-28 12:41:15 and gitea-caddy StartedAt unchanged; live input chain gains iifname wg0 tcp dport 853 accept; verify: nftables.conf matches; anki/gitea HTTPS 200" + }, + { + "command": "lib/tests/test_wg_firewall.sh (root in vmbox) ; shell_coverage_jail.sh --subject lib/tests/run_all.sh --min 0 --fail-on-case-error", + "result": "pass", + "evidence": "12 passed incl. real nft -c; jailed suite rc=0" + } + ], + "risks": [ + "Tables left over from an older ruleset outside inet filter are no longer flushed by an apply (none exist on the host).", + "If docker's rules live somewhere other than the nat DOCKER chain, a missing-rules state would not trigger the rebuild." + ], + "rollback": [ + "git revert this commit, then sudo setup_wireguard_ssh.sh allow-web to re-render (old code restarts docker once)", + "After rollback: setup_wireguard_ssh.sh verify, and confirm containers reach the network" + ] +} diff --git a/linux_configuration/features/lib/dot_resolver_install.sh b/linux_configuration/features/lib/dot_resolver_install.sh index f5bd0d59..fbc0161a 100755 --- a/linux_configuration/features/lib/dot_resolver_install.sh +++ b/linux_configuration/features/lib/dot_resolver_install.sh @@ -100,12 +100,12 @@ open_firewall() { # added explicitly, scoped to the tunnel interface. if [[ "$BIND_ADDR" != "0.0.0.0" ]]; then if command -v nft >/dev/null 2>&1 && sudo nft list table inet filter >/dev/null 2>&1; then - if sudo nft list table inet filter | grep -q "iifname \"wg0\" tcp dport $DOT_PORT"; then - log "nftables already permits $DOT_PORT on wg0" + # Through the firewall's owner, which persists ALLOW_DOT and renders + # the rule: an 'nft add rule' here vanished at the next re-apply. + if sudo bash "${WG_SCRIPT:-${SCRIPT_DIR}/setup_wireguard_ssh.sh}" allow-dot; then + log "Permitted TCP $DOT_PORT on wg0 only (persisted)" else - sudo nft add rule inet filter input iifname wg0 tcp dport "$DOT_PORT" accept || - log "WARNING: could not add nftables rule for $DOT_PORT on wg0" - log "Permitted TCP $DOT_PORT on wg0 only" + log "WARNING: could not open $DOT_PORT on wg0 (setup_wireguard_ssh.sh allow-dot)" fi fi log "No router port-forward needed - $BIND_ADDR is WireGuard-only." diff --git a/linux_configuration/features/lib/tests/test_dot_resolver_install.sh b/linux_configuration/features/lib/tests/test_dot_resolver_install.sh index 710eb334..b42ac021 100755 --- a/linux_configuration/features/lib/tests/test_dot_resolver_install.sh +++ b/linux_configuration/features/lib/tests/test_dot_resolver_install.sh @@ -104,25 +104,31 @@ _t_called 'daemon-reload' "units are followed by a daemon-reload" out="$(open_firewall 2>&1)" _t_has "$out" 'WireGuard-only' "wg-bound install needs no router forward" -# nft present and the rule already there: must not add a duplicate. +# nft present: the rule goes through the firewall owner's allow-dot, which +# persists ALLOW_DOT so a later re-apply keeps it (a bare 'nft add rule' was +# silently dropped by the next one). _t_stub nft -printf '#!/usr/bin/env bash\nprintf "nft %%s\\n" "$*" >>"%s/calls.log"\nif [[ $* == *list* ]]; then printf "iifname \\"wg0\\" tcp dport %s accept\\n" ; fi\nexit 0\n' \ - "$TEST_TMPDIR" "$DOT_PORT" >"$TEST_TMPDIR/bin/nft" -chmod +x "$TEST_TMPDIR/bin/nft" +WG_SCRIPT="$TEST_TMPDIR/bin/wg_owner" +printf '#!/usr/bin/env bash\nprintf "wg_owner %%s\\n" "$*" >>"%s/calls.log"\nexit 0\n' \ + "$TEST_TMPDIR" >"$WG_SCRIPT" +chmod +x "$WG_SCRIPT" out="$(open_firewall 2>&1)" -_t_has "$out" 'already permits' "an existing wg0 rule is not duplicated" +_t_has "$out" 'wg0 only (persisted)' "the wg0 rule is opened through the firewall owner" +_t_called 'wg_owner allow-dot' "open_firewall runs setup_wireguard_ssh.sh allow-dot" +if grep -q 'add rule inet filter input iifname wg0' "$TEST_TMPDIR/calls.log"; then + _t_fail "no unpersisted runtime 'nft add rule' for the wg0 branch" +else + _t_pass "no unpersisted runtime 'nft add rule' for the wg0 branch" +fi -# nft present and the rule missing: must add it, scoped to wg0. -printf '#!/usr/bin/env bash\nprintf "nft %%s\\n" "$*" >>"%s/calls.log"\nexit 0\n' \ - "$TEST_TMPDIR" >"$TEST_TMPDIR/bin/nft" -chmod +x "$TEST_TMPDIR/bin/nft" +# allow-dot fails (e.g. sshd check rolled it back): warn and carry on. +printf '#!/usr/bin/env bash\nexit 1\n' >"$WG_SCRIPT" out="$(open_firewall 2>&1)" -_t_has "$out" 'wg0 only' "a missing wg0 rule is added" -_t_called 'add rule inet filter input iifname wg0' "the added rule is scoped to the tunnel" +_t_has "$out" 'WARNING: could not open' "a failed allow-dot warns instead of aborting" +unset WG_SCRIPT -# nft present but the ADD fails (a locked-down or read-only ruleset): the -# install must warn and carry on, never abort. `nft list` still has to succeed -# or the outer guard short-circuits before the add is attempted. +# The public branch still adds its rule at runtime; its add-failure path +# needs an nft whose 'list' succeeds and 'add' fails. cat >"$TEST_TMPDIR/bin/nft" <<'NFT' #!/usr/bin/env bash printf 'nft %s\n' "$*" >>"$TEST_TMPDIR/calls.log" @@ -130,8 +136,6 @@ printf 'nft %s\n' "$*" >>"$TEST_TMPDIR/calls.log" exit 0 NFT chmod +x "$TEST_TMPDIR/bin/nft" -out="$(open_firewall 2>&1)" -_t_has "$out" 'WARNING: could not add nftables rule' "a failed wg0 rule add warns instead of aborting" # --- open_firewall: the publicly-bound branch ------------------------------- # A public bind is an open resolver, so the rule MUST carry a rate limit. diff --git a/linux_configuration/features/lib/tests/test_wg_firewall.sh b/linux_configuration/features/lib/tests/test_wg_firewall.sh new file mode 100755 index 00000000..171f8c17 --- /dev/null +++ b/linux_configuration/features/lib/tests/test_wg_firewall.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +# Tests for wg_firewall.sh -- the rendered ruleset and the docker restart. +# +# Every apply used to start with 'flush ruleset' and end with a docker +# restart, so opening one port bounced every container on the host. The +# subject now replaces only its own table and restarts docker only when +# docker's own rules are really gone; both are asserted on generated content +# and on the commands actually called. +# +# Rendering writes only where it is told and every command is stubbed, so +# this suite needs no jail, but it runs inside one with its siblings. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=./features_harness.sh +. "$SCRIPT_DIR/features_harness.sh" + +_t_setup_env +trap _t_teardown EXIT + +# The globals setup_wireguard_ssh.sh defines above its source line. +WG_IFACE="wg0" +WG_PORT="51820" +LAN_SUBNET="192.168.1.0/24" +NFT_CONF="$TEST_TMPDIR/nftables.conf" +ALLOW_WEB="true" +ALLOW_DNS="false" +ALLOW_HOMEASSISTANT="true" +ALLOW_DOT="true" +detect_lan_subnet() { :; } +log_ok() { log "$1"; } +log_warn() { log "$1"; } +log_error() { log "$1"; } +die() { + log "$1" + exit 1 +} +is_service_active() { [[ ${DOCKER_ACTIVE:-yes} == yes ]]; } + +# shellcheck source=../wg_firewall.sh +. "$FEATURES_LIB_DIR/wg_firewall.sh" + +printf '\n-- only our own table is replaced --\n' +RULES="$TEST_TMPDIR/rules.nft" +render_nftables_ruleset "$RULES" +if grep -q '^flush ruleset' "$RULES"; then + _t_fail "no 'flush ruleset' (it deletes Docker's and Tailscale's tables)" +else + _t_pass "no 'flush ruleset' (it deletes Docker's and Tailscale's tables)" +fi +_t_eq "table inet filter|delete table inet filter" \ + "$(grep -E '^(delete )?table inet filter$' "$RULES" | paste -sd'|')" \ + "declare-then-delete precedes the definition, so a first boot loads" + +printf '\n-- flags render their rules --\n' +_t_file_has "$RULES" 'iifname "wg0" tcp dport 853 accept' "ALLOW_DOT opens 853 on wg0" +_t_file_has "$RULES" 'iifname "wg0" tcp dport 8123 accept' "ALLOW_HOMEASSISTANT keeps 8123" +_t_file_has "$RULES" 'tcp dport { 80, 443 } accept' "ALLOW_WEB keeps 80/443" +ALLOW_DOT="false" +render_nftables_ruleset "$RULES" +if grep -q 'dport 853' "$RULES"; then + _t_fail "ALLOW_DOT=false renders no 853 rule" +else + _t_pass "ALLOW_DOT=false renders no 853 rule" +fi +if command -v nft >/dev/null 2>&1; then + ALLOW_DOT="true" + render_nftables_ruleset "$RULES" + if nft -c -f "$RULES" >/dev/null 2>&1; then + _t_pass "nft -c accepts the rendered ruleset" + else + # nft -c needs CAP_NET_ADMIN; outside the jail it cannot check at all. + printf ' (skipped: nft -c not permitted here)\n' + fi +fi + +printf '\n-- docker is restarted only when its rules are gone --\n' +_t_stub systemctl +printf '#!/usr/bin/env bash\nprintf "iptables %%s\\n" "$*" >>"%s/calls.log"\nexit 0\n' \ + "$TEST_TMPDIR" >"$TEST_TMPDIR/bin/iptables" +chmod +x "$TEST_TMPDIR/bin/iptables" +out="$(restore_docker_rules 2>&1)" +_t_has "$out" 'intact; containers untouched' "intact docker rules are left alone" +if grep -q 'systemctl restart docker' "$TEST_TMPDIR/calls.log"; then + _t_fail "no docker restart while its rules are intact" +else + _t_pass "no docker restart while its rules are intact" +fi + +printf '#!/usr/bin/env bash\nexit 1\n' >"$TEST_TMPDIR/bin/iptables" +out="$(restore_docker_rules 2>&1)" +_t_has "$out" 'restarted' "missing docker rules trigger a rebuild" +_t_called 'systemctl restart docker' "the rebuild is a docker restart" + +: >"$TEST_TMPDIR/calls.log" +DOCKER_ACTIVE=no restore_docker_rules +if grep -q 'iptables\|systemctl' "$TEST_TMPDIR/calls.log"; then + _t_fail "an inactive docker is not touched" +else + _t_pass "an inactive docker is not touched" +fi + +_t_report "test_wg_firewall.sh" diff --git a/linux_configuration/features/lib/wg_firewall.sh b/linux_configuration/features/lib/wg_firewall.sh index e6ce01f2..902735cf 100755 --- a/linux_configuration/features/lib/wg_firewall.sh +++ b/linux_configuration/features/lib/wg_firewall.sh @@ -12,14 +12,14 @@ render_nftables_ruleset() { local target="$1" detect_lan_subnet local web_rule="" - if [[ $ALLOW_WEB == "true" ]]; then + if [[ ${ALLOW_WEB:-false} == "true" ]]; then web_rule=$'\n\t\ttcp dport { 80, 443 } accept' fi # DNS blocker (setup_dns_blocker.sh): serve DNS (53) -- and DHCP (67) when # this PC is the LAN DHCP server -- to LAN clients only. Restricted to the # LAN subnet so nothing is ever exposed to the internet. local dns_rule="" dhcp_rule="" - if [[ $ALLOW_DNS == "true" ]]; then + if [[ ${ALLOW_DNS:-false} == "true" ]]; then dns_rule=$'\n\t\tip saddr '"${LAN_SUBNET}"$' udp dport 53 accept' dns_rule+=$'\n\t\tip saddr '"${LAN_SUBNET}"$' tcp dport 53 accept' # DHCP clients have no IP yet (saddr 0.0.0.0 -> 255.255.255.255) and the @@ -35,9 +35,20 @@ render_nftables_ruleset() { ha_rule=$'\n\t\tip saddr '"${LAN_SUBNET}"$' tcp dport 8123 accept' ha_rule+=$'\n\t\tiifname "'"${WG_IFACE}"$'" tcp dport 8123 accept' fi + # DNS-over-TLS (setup_dot_resolver.sh, bound to the WireGuard address): + # rendered here so a re-apply keeps it -- a runtime 'nft add rule' did not. + local dot_rule="" + if [[ ${ALLOW_DOT:-false} == "true" ]]; then + dot_rule=$'\n\t\tiifname "'"${WG_IFACE}"$'" tcp dport 853 accept' + fi cat >"$target" </dev/null 2>&1; then + log_ok "docker's own firewall rules are intact; containers untouched." + return 0 + fi + log_warn "docker's nat rules are missing; restarting docker to rebuild them." systemctl restart docker log_ok "docker restarted; its firewall rules are back." } @@ -141,7 +155,7 @@ verify_nftables_then_apply() { nft -f "$NFT_CONF" sleep 2 if ! is_service_active sshd; then - nft flush ruleset + nft delete table inet filter die "sshd died after applying nftables -- rolled back. Investigate before retrying." fi log_ok "nftables applied; sshd is still active." @@ -149,3 +163,11 @@ verify_nftables_then_apply() { log_warn "Before closing this terminal, open a SECOND ssh session now and confirm it connects." enable_service nftables } + +allow_dot() { + export ALLOW_DOT=true + save_config + write_nftables_ruleset + verify_nftables_then_apply + log_ok "Opened tcp/853 on ${WG_IFACE} (persisted)." +} diff --git a/linux_configuration/features/lib/wg_sshd.sh b/linux_configuration/features/lib/wg_sshd.sh index 3a285471..f2145115 100755 --- a/linux_configuration/features/lib/wg_sshd.sh +++ b/linux_configuration/features/lib/wg_sshd.sh @@ -235,6 +235,7 @@ Commands: add-peer Provision a new phone/laptop and print its QR code. allow-web Open tcp/80 and tcp/443 in the firewall (for a web server on this host). allow-dns Open udp/tcp 53 from the LAN in the firewall (for the DNS blocker on this host). + allow-dot Open tcp/853 on wg0 in the firewall (for the DoT resolver on this host). verify Check /etc/nftables.conf matches this script and that the live forward chain still lets Docker through. install-verify Install the units that run 'verify' at every boot, so diff --git a/linux_configuration/features/setup_wireguard_ssh.sh b/linux_configuration/features/setup_wireguard_ssh.sh index a82d75ba..61a0c6f6 100755 --- a/linux_configuration/features/setup_wireguard_ssh.sh +++ b/linux_configuration/features/setup_wireguard_ssh.sh @@ -40,6 +40,7 @@ LAN_SUBNET="${LAN_SUBNET:-}" export ALLOW_WEB="${ALLOW_WEB:-false}" export ALLOW_DNS="${ALLOW_DNS:-false}" export ALLOW_HOMEASSISTANT="${ALLOW_HOMEASSISTANT:-false}" +export ALLOW_DOT="${ALLOW_DOT:-false}" die() { log_error "$1" @@ -54,6 +55,7 @@ LAN_SUBNET="${LAN_SUBNET}" ALLOW_WEB="${ALLOW_WEB}" ALLOW_DNS="${ALLOW_DNS}" ALLOW_HOMEASSISTANT="${ALLOW_HOMEASSISTANT}" +ALLOW_DOT="${ALLOW_DOT}" EOF chmod 600 "$CONFIG_FILE" } @@ -93,7 +95,7 @@ main() { # off -- exec sudo "$0" "$@" inside require_root must re-launch with the # subcommand still present, or sudo would silently run with no args. case "$cmd" in - setup | add-peer | revoke | allow-web | allow-dns | allow-homeassistant | verify | install-verify) + setup | add-peer | revoke | allow-web | allow-dns | allow-homeassistant | allow-dot | verify | install-verify) require_root "$@" ;; esac @@ -134,6 +136,10 @@ main() { allow_homeassistant install_verify_units ;; + allow-dot) + allow_dot + install_verify_units + ;; verify) verify_nft ;;