Forgejo's runner spins up a per-workflow Docker network for every job,
which lives on a br-XXXXXX bridge — not docker0. Without this rule, the
in-container git clone (and anything else outbound) hits the forward
chain's default-deny and times out. Match docker0 plus the br-* glob in
both input and forward so any Docker network model works.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Containers connecting to host services on 10.0.0.1 (e.g. Profilarr → Radarr
at 10.0.0.1:7878) hit the input chain, not forward, because the destination
is a local IP. The forward chain already trusts docker0 for outbound; this
adds the matching input rule so the return path stops getting dropped.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
NixOS's nftables module rebuilds the tables it owns on every activation,
which previously wiped Docker's DOCKER/PREROUTING chains in ip nat
(both Docker and the router were defining 'ip nat'). Renaming our
table sidesteps the collision — kernel hooks across separate tables
at the same priority all run, so functionality is unchanged.
Eliminates the need to run 'systemctl restart docker' after every
nixos-rebuild to restore container port-forwards.
The forward rule only accepted iifname=eno1 oifname=eth0 ct status=dnat,
which worked when port-forwards always landed on a LAN host. Docker
DNAT routes to docker0, so external traffic to 26900 was being DNAT'd
correctly but then dropped at the forward filter. Drop the oifname
constraint — the prerouting DNAT rule already controls what gets
forwarded; the filter doesn't need to second-guess it.
Container outbound (image pulls, LinuxGSM bootstrap fetches) was
dropped by the inet filter forward chain — only eth0 and DNAT'd
WAN traffic were whitelisted. Add iifname "docker0" accept so
containers can reach the internet.
Also add the coop server's 26910/26911-26912 forwards to ports.toml
so WAN players can connect.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- trustedLegacyCidrs now empty; eno1 is strictly WAN
- AdGuard rewrite retargets nordhammer.it → 10.0.0.1 (the new router IP)
- dnsmasq pins the bedroom camera (f0:a7:31:6c:50:4b) to 10.0.0.39
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Input chain now accepts WAN traffic for every port in ports.toml so
external access (SSH, HTTP, HTTPS, game ports) works through the eero's
upstream port forwards during phase 1, and via our own DNAT in phase 2.
- Add AdGuard DNS rewrite nordhammer.it → 192.168.4.25 so LAN clients
hit the mediaserver directly instead of relying on eero hairpin NAT.
Target changes to 10.0.0.1 at phase 2 cutover.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Without this, the default-drop input policy blocked SSH and AdGuard DNS
from existing 192.168.4.x clients because they arrive on eno1 (still
acting as a client on the eero network until phase 2 cutover).
The trustedLegacyCidrs list is meant to be emptied in phase 2 when
eno1 becomes the ISP-facing WAN.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds services/router.nix with systemd-networkd (eno1=WAN via DHCP,
eth0=LAN 10.0.0.1/24), nftables (NAT + firewall, default drop on WAN
in), dnsmasq (DHCP only — AdGuard Home keeps :53 for DNS), and sysctl
IP forwarding. NetworkManager is forced off on this host.
Port forwards live in ports.toml at the repo root and are imported via
builtins.fromTOML. Supports single ports, ranges ("26901-26902"), and
"both" protocol. Initial forwards: 22, 80, 443, 26900, 26901-26902.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>