#!/usr/bin/env bash # Locks the Swarm ports (2377 control, 7946 gossip, 4789 overlay VXLAN) to the # WireGuard interface only — they must never be reachable from the public # internet. Run on ALL THREE nodes (vps2, vps1, desktop) after joining the # swarm. Existing app-facing rules (80/443, SSH, etc.) are untouched. set -euo pipefail WG_IFACE="${WG_IFACE:-wg0}" if ! command -v ufw >/dev/null 2>&1; then echo "ufw not found — apply the equivalent iptables/nftables rules by hand:" >&2 echo " allow 2377/tcp, 7946/tcp, 7946/udp, 4789/udp only on interface ${WG_IFACE}" >&2 echo " deny 2377/tcp, 7946/tcp, 7946/udp, 4789/udp on every other interface" >&2 exit 1 fi echo "==> Allowing Swarm ports on ${WG_IFACE} only" ufw allow in on "$WG_IFACE" to any port 2377 proto tcp ufw allow in on "$WG_IFACE" to any port 7946 proto tcp ufw allow in on "$WG_IFACE" to any port 7946 proto udp ufw allow in on "$WG_IFACE" to any port 4789 proto udp echo "==> Explicitly denying the same ports on every other interface" ufw deny 2377/tcp ufw deny 7946/tcp ufw deny 7946/udp ufw deny 4789/udp echo echo "Rules added (not yet necessarily active — check ufw status):" ufw status numbered | grep -E "2377|7946|4789|Status" || true echo if ! ufw status | grep -q "^Status: active"; then echo "ufw is currently INACTIVE on this node — 'ufw enable' switches its" echo "default policy to deny-incoming for EVERYTHING, not just the Swarm" echo "ports above. Before enabling, explicitly allow every port this node" echo "already serves publicly (SSH at minimum; on vps2 specifically, also" echo "80/tcp and 443/tcp for the live thermograph.org/beta.thermograph.org" echo "Caddy; on vps1, 80/tcp and 443/tcp for git.thermograph.org," echo "dashboard.thermograph.org and emigriffith.dev) — check 'ss -tlnp' for" echo "what's actually listening first. Enabling ufw without doing this WILL" echo "drop live traffic the moment it activates." fi