I have had IPv6 "working at home" three times now, and only this third time is it actually working. The first two were the special kind of working where a test page shows a green tick and everything underneath is held together with hope. This time I went in expecting it to be miserable, gave it a whole weekend, and came out with native v6 across every VLAN, a stable prefix, and firewall rules I actually understand. So: eventually, but properly.
The motivation was dull and practical. A couple of services I self-host had started to want reachability without the CGNAT-and-port-forward dance, and IPv6 makes that genuinely pleasant. No NAT, every device globally addressable, the way the internet was supposed to be before we ran out of numbers. The catch is that "globally addressable" and "globally reachable" are very different things, and conflating them is how people accidentally expose their NAS to the entire planet.
what the ISP actually gives you
The first thing to establish is what your ISP delegates, because everything downstream depends on it. In the UK this varies wildly. Some hand you a single /64 and nothing more, which is almost useless if you want more than one subnet, because /64 is the smallest unit SLAAC will work in and you can't subdivide it sensibly. What you want is DHCPv6 Prefix Delegation, ideally a /56, which gives you 256 /64s to carve up per VLAN.
Mine delegates a /56, but, and this is the part the forums warned me about, the prefix is not stable. It changes when the line renegotiates, which it does on reconnects and occasionally for no reason I could find. That single fact dictates a lot of the design, because if you hard-code addresses derived from the prefix anywhere, they all break the next time it rotates.
On OPNsense the WAN side wants:
IPv6 Configuration Type: DHCPv6
Request only an IPv6 prefix: checked
Prefix delegation size: 56
Send IPv6 prefix hint: checked
The "request only a prefix" tickbox matters. Without it the WAN tries to take an address for itself from the delegation and the arithmetic gets confused. You want the WAN to be the courier for the prefix, not a consumer of it.
handing addresses to the LAN
This is where my first two attempts had quietly gone wrong. There are two mechanisms and people muddle them constantly. SLAAC, where the router advertises a prefix and hosts make up their own address from it. DHCPv6, where a server hands out specific addresses. They are not alternatives so much as a spectrum, controlled by flags in the router advertisement.
On each internal VLAN interface I set the IPv6 type to "Track Interface", pointed it at the WAN, and gave each VLAN a different prefix ID (0, 1, 2…) so each one lands in its own /64 within the delegated /56. Then in the Router Advertisements config:
Router Advertisements: Unmanaged
(SLAAC only; hosts autoconfigure, no DHCPv6 needed for general clients)
For the VLANs where I wanted predictable addresses for servers, I switched to "Assisted" (the M and O flags) and ran a DHCPv6 server alongside SLAAC. Most clients are perfectly happy with SLAAC plus the privacy extensions that randomise the host portion. The servers get DHCPv6 reservations keyed on DUID, which is the v6 equivalent of a DHCP reservation, except the DUID is not the MAC and that tripped me up for an hour.
the firewall, where the danger lives
Here is the part that genuinely matters and that the green-tick test pages will never check for you. In IPv4 land, NAT has been doing you a security favour by accident for twenty years. Nothing from outside can reach an internal host unless you explicitly forward a port, because there's no route to a private address. IPv6 removes that accident. Every device now has a globally routable address, and if your firewall default is permissive, every device is now on the internet, fully.
So the very first rule I wrote, before celebrating anything, was the default deny on the WAN for inbound IPv6, and then I tested it from outside. I picked an internal host's brand-new global address and tried to reach it from a VPS in another country. Refused. Good. Then I opened, host by host, the exact ports for the exact services I actually wanted reachable, scoped tightly.
A subtlety worth knowing: because the prefix rotates, firewall rules that hard-code the global address break on renegotiation. OPNsense handles this with aliases that track the interface's network, so the rule reads "allow tcp/443 to the web server's address on this VLAN's prefix" and follows the prefix when it moves. Get this wrong and you'll either expose nothing (annoying) or, far worse, leave a stale allow rule pointing at a prefix that's been reassigned to someone else.
Don't forget ICMPv6 either. The instinct from v4 is to block ping and feel clever. In v6 that breaks you, because Path MTU Discovery and Neighbour Discovery ride on ICMPv6 and the protocol genuinely needs them. Block ICMPv6 wholesale and you get the classic symptom: small things work, large transfers hang. Allow the necessary types and your life improves immediately.
was it worth it
Mostly, yes. The services I wanted reachable are reachable over v6 without any port-forward gymnastics, the addressing is clean, and watching a device pick up a global address by itself still feels faintly magical after all these years. The rotating prefix remains a low hum of annoyance; one day I'll pay for a static allocation or a tunnel and be done with it.
But I'd stop short of telling anyone this is easy. The hard part isn't the configuration, it's that v6 quietly removes a safety net you'd forgotten you were standing on, and it does so without asking. If you take one thing from a weekend I'm not getting back: turn it on, then immediately try to break into your own network from outside, before you trust a single green tick.