falcon-vpn-only was defined inline in falcon.yaml even though it's a
generic ipAllowList restriction with nothing falcon-specific about it
- security.yaml is where the other reusable middlewares (security-
headers, no-index, rate-limit) already live. Renamed to vpn-only to
match their bare naming style now that it's not tied to one file, and
updated falcon.yaml's two router references to vpn-only@file (same
cross-file pattern already used there for security-headers@file).
Also applies it to the pulsenode stack: it's a dashboard surfacing
container names/health for every service here, and there's no auth in
front of it yet, so gating it to the tailnet is a real mitigation for
that gap rather than leaving it open on the public hostname.
Add a Traefik IP allowlist so *.falcon.pivoine.art rejects any source
outside the Tailscale/Headscale CIDR ranges, even though DNS still
resolves publicly. Pair it with a headscale MagicDNS override so
tailnet clients resolve the hostname straight to the VPS's tailscale
IP and route correctly.
Requires Docker's userland-proxy disabled on the VPS host
(/etc/docker/daemon.json) so Traefik sees real client source IPs
instead of the docker bridge gateway — done manually, not tracked
in this repo.