Enable IPv6 if your ISP delegates a stable prefix; treat it as optional everywhere else. Prefix stability is nearly the whole decision: with a stable /56, IPv6 removes NAT hacks and gives every service a globally routable address behind a proper firewall. With a prefix that changes on every reconnect, you'll rewrite DNS and firewall rules forever for no visible benefit. And behind CGNAT the calculus flips entirely — IPv6 may be your only inbound path, and then it's worth real effort.

Find out what you have (ten minutes)

ip -6 addr show scope global   # any 2xxx:: address = you have v6
ip -6 route | grep default     # a default route via your router
curl -6 -s https://ifconfig.co # working v6 egress end-to-end

Then test-ipv6.com from a browser for the full verdict, and check your router for the delegated prefix size. A /64 is a single network — usable but you can't subnet it properly. A /56 gives you 256 networks, one per VLAN, which is what you want. As for stability: ISP documentation rarely commits either way, so observe across a week of router reboots. If the prefix survives, build on it; if it rotates, don't build anything static on v6 at all.

Firewall first: no NAT does not mean exposed

The mental unlearning IPv6 requires: on IPv4, NAT was accidentally your inbound filter. On IPv6 every device has a public address, and the router's stateful firewall — not address translation — is what stands between it and the internet. Every consumer router of the last decade defaults to deny-inbound for v6, so the out-of-box posture is fine. What changes is how you punch holes: per-host, per-port rules against specific addresses instead of port-forwards.

One trick makes those rules survivable: interface tokens. Hosts normally generate rotating privacy addresses (good for clients, useless for servers), but a token pins the host part:

ip token set ::10 dev eth0

Now the server always lives at <whatever-prefix>::10, your firewall rule references ::10/-64-style suffix matching where supported, and even a prefix change doesn't invalidate the rule's logic.

The gotchas that actually bite

Happy Eyeballs hides breakage. Dual-stack clients race v4 and v6 and quietly fall back, so half-broken IPv6 doesn't fail — it adds 100–250ms of hesitation to every connection. If the internet "feels slow" after enabling v6, that's the signature. Test services individually with curl -6.

AAAA records are a promise. Publish an AAAA for a host whose firewall blocks v6 and v6-capable visitors get timeouts before fallback. Publish AAAA records only after testing the path, and remember your internal DNS needs to answer over v6 too — otherwise devices pick up whatever resolver the router advertises via RDNSS and bypass Pi-hole entirely. Point the RA's DNS option at your resolver or turn RDNSS off; the broader split-horizon setup is in DNS for self-hosters.

Docker treats v6 as opt-in. Containers get no IPv6 by default, which is usually fine — the reverse proxy terminates v6 at the edge and speaks v4 to containers behind it. Only enable Docker's v6 ("ipv6": true plus a ULA fixed-cidr-v6 in daemon.json) if a container itself must talk v6; it remains the fiddliest corner of the stack.

Android doesn't do DHCPv6. It's SLAAC-only, by long-standing design. Build your addressing plan on SLAAC plus RDNSS, and treat DHCPv6 as a bonus for the devices that support it, never a requirement.

Who gets real value

CGNAT subscribers get the most: with no public IPv4 at all, a delegated v6 prefix restores inbound connectivity — pair it with a proxy that fronts v4 for legacy visitors, or share services to yourself directly. Households full of modern devices get modest wins: v6 skips the CGNAT hop and occasionally shaves latency, and roughly half of client traffic to major services already rides it (Google's adoption graph has hovered around the 45–50% mark). And anyone using Tailscale or similar already has the practical benefit people want from v6 — stable addressing for every device, everywhere — which is why overlay networks quietly removed the urgency for the rest of us.

When to skip it

Rotating prefix and no CGNAT: stay v4-only plus an overlay network, and revisit when the ISP grows up. Fleet of legacy IoT that misbehaves on dual-stack: segment it to a v4-only VLAN, run v6 on the networks with modern clients. Under time pressure: v6 is a satisfying project, not an urgent one — nothing in a LAN-only homelab requires it in 2026.

What I'd do

Stable /56: enable dual-stack, leave the router at default-deny, set tokens on servers, publish AAAA only for tested services, keep Docker on v4 behind the proxy, and give each VLAN its own /64. Rotating prefix: skip it, use Tailscale, feel nothing. CGNAT: this is your way out — enable it, learn it, and stop paying for a static IPv4 you can't get anyway.