feat(web-arm): static IPv6 address, route, and Postfix v4-pin #81
Labels
No labels
bug
enhancement
in-progress
needs-info
needs-triage
p0
ready-for-agent
ready-for-human
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/nixos#81
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
Give web-arm its own outbound IPv6 by statically configuring the Hetzner Cloud /64, without regressing outbound mail. This is the foundation both directions build on.
web-arm is a Hetzner Cloud CAX (ARM) host on
enp1s0. It currently has no global IPv6 address and no default v6 route: Hetzner offers no DHCPv6, and SLAAC is unreliable here (the box is a router via docker/podman/wireguard, withaccept_ra=0/autoconf=0). So we declare the address statically — exactly what cloud-init does on a stock image.Apply to
hosts/web-arm/:The Postfix v4-pin must land in the same change as the route. Merging the route alone makes Postfix start preferring an IPv6 source with no rDNS/SPF to dual-stack MXes (Gmail etc.), silently regressing mail that works today.
Also add
docs/adr/0010-static-ipv6-on-web-arm.mdcapturing the decision: static over DHCPv6 (not offered by Hetzner) and over SLAAC (unreliable on a forwarding host; MAC-derived address is a poor inbound AAAA target), plus why mail is pinned to v4.Acceptance criteria
hosts/web-armdeclares static2a01:4f8:c012:43b::1/64onenp1s0+defaultGateway6viafe80::1smtp_address_preference = ipv4) in the same changedocs/adr/0010-static-ipv6-on-web-arm.mdadded with the static-vs-SLAAC/DHCPv6 + mail-pin rationaleip -6 routeshowsdefault via fe80::1;curl -6from the host reaches the v6 internet:::80and:::443(ss -tlnp)Blocked by
None - can start immediately
Agent Brief
Category: enhancement
Summary: Give web-arm a statically-configured global IPv6 address + default route on its WAN interface
enp1s0, and pin Postfix outbound to IPv4 in the same change so mail deliverability does not regress.Current behavior:
web-arm (Hetzner Cloud CAX / ARM) has no global IPv6 and no default IPv6 route. Confirmed live via the read-only diag channel:
enp1s0is the WAN NIC, carrying the public IPv4188.34.191.144/32(DHCP) and only a link-localfe80::address;ip -6 routeshows only on-linkfe80::/64entries — no default route, so outbound IPv6 is currently impossible. Hetzner offers no DHCPv6, and SLAAC is unsuitable: the host forwards for docker/podman/wireguard (RA-acceptance/autoconf off), and a MAC-derived SLAAC address would be an unstable, poor inbound AAAA target. Postfix sets nosmtp_address_preference, so it runs on the Postfix default (any) — meaning the instant a default IPv6 route exists, Postfix will prefer an IPv6 source (which has no rDNS / SPF) when delivering to dual-stack MXes such as Gmail, silently regressing outbound mail that works today.Desired behavior:
web-arm declares its Hetzner-routed /64 statically on
enp1s0plus a default IPv6 route via the Hetzner link-local gateway, giving it working outbound IPv6 — while outbound mail continues to leave over IPv4. The address, the route, and the Postfix v4-pin must ship in one change; the route without the pin is the regression.Key interfaces / contracts:
2a01:4f8:c012:43b::1, prefix length64, on interfaceenp1s0fe80::1with interfaceenp1s0(a link-local gateway must name its interface)smtp_address_preferenceis set toipv4, via whatever attribute the host's Postfix configuration exposes for main.cf settings (the repo configures Postfix throughservices.postfix). Behavioral contract, verifiable on the deployed host:postconf smtp_address_preferencereportsipv4. The dry-build validates the exact Nix attribute.docs/adr/0010-static-ipv6-on-web-arm.mdrecords the decision: static chosen over DHCPv6 (not offered by Hetzner) and over SLAAC (unreliable on a forwarding host; MAC-derived address is a poor inbound AAAA target), and why outbound mail is pinned to IPv4. (0010 is the next free ADR number as of triage; if another ADR has claimed it by implementation time, use the next free number.)Literal values — use verbatim (maintainer-supplied from the Hetzner Cloud console):
2a01:4f8:c012:43b::1/64fe80::1(Hetzner Cloud standard link-local gateway)enp1s0(confirmed live during triage)These are opaque strings the dry-build cannot check for correctness — a wrong value passes
evaland only surfaces post-deploy. Re-confirm the /64 and gateway against the Hetzner console before merge.Acceptance criteria (agent's gate):
2a01:4f8:c012:43b::1/64onenp1s0and a default IPv6 route viafe80::1onenp1s0smtp_address_preference = ipv4) in the same changedocs/adr/0010-static-ipv6-on-web-arm.mdadded with the static-vs-SLAAC/DHCPv6 + mail-pin rationaleAcceptance criteria (post-deploy — human-verified after merge, not part of the PR):
ip -6 routeon web-arm showsdefault via fe80::1 dev enp1s0;curl -6from the host reaches the v6 internet:::80and:::443(ss -tlnp)postconf smtp_address_preference=ipv4, deliverability unchangedOut of scope:
allowedTCPPorts = [ 22 80 443 ]apply to IPv6 too once the address is up, so those three ports become reachable over v6 — same ports as v4, expected and acceptable.)accept_ra/autoconf/tempAddress— keep scope to address + route + mail-pin, matching the issue's own scoping, unless the dry-build or reviewer shows a stray SLAAC address would otherwise coexist with the static one.