IPv6 on Proxmox VE: Dual-Stack VMs and LXC Containers
Configure native IPv6 dual-stack on Proxmox VE 9.1 for VMs and LXC containers. Covers static addressing, SLAAC, DHCPv6, and firewall rules in one guide.
On this page
IPv6 on Proxmox VE 9.1 is fully supported — the confusion usually comes from not knowing which three layers to touch: the host bridge, individual guest configs, and the firewall. Once you configure all three, dual-stack just works. By the end of this guide every VM and LXC container on your node will have a real IPv6 address, outbound connectivity, and firewall rules that don't accidentally block Neighbor Discovery Protocol and leave you debugging for an hour. Expect about 20 minutes on a single-node homelab.
Key Takeaways
- Host bridge: Add a separate
inet6stanza tovmbr0in/etc/network/interfaces— no extra packages for static addressing - Forwarding required: Set
net.ipv6.conf.all.forwarding=1or guest traffic won't route through the bridge even if the host itself works - LXC containers: Unprivileged containers handle IPv6 natively — no privileged mode required
- Firewall: The Proxmox VE nftables-backed firewall applies rules to IPv4 and IPv6 simultaneously — write once, cover both
- No ISP delegation: Use a ULA prefix in
fd00::/8for internal-only homelab setups that still need IPv6 practice
What Your ISP Actually Gives You (and What to Do With It)
Most ISPs with IPv6 support hand your router a prefix via DHCPv6-PD — commonly a /48, /56, or /60. Your router subdivides this and routes individual /64 subnets downstream. The Proxmox host gets one of those /64s and uses it as the bridge address space.
Before touching any Proxmox config, check what's already on the host:
ip -6 addr show
ip -6 route show default
A global 2xxx: address on any interface means upstream delegation is already working. Only fe80:: link-local addresses means the kernel is running IPv6 but nothing is routing to the host yet — fix that on the router before continuing.
If you're on a homelab with no ISP delegation, pick any prefix in fd00::/8 — for example fd00:1:2::/48 — and subnet it manually. ULA addresses route inside your network only, which is fine for internal services you reach over VPN or from other local hosts.
If you're planning to put IPv6 subnets on separate VLANs, the guide on configuring VLANs on Proxmox with Linux bridges covers the bridge topology before you start assigning prefixes to segments.
How to Configure vmbr0 for Dual-Stack
The host bridge configuration lives in /etc/network/interfaces. The IPv6 block is a separate iface stanza appended below the existing IPv4 block — not nested inside it:
auto lo
iface lo inet loopback
iface lo inet6 loopback
auto enp3s0
iface enp3s0 inet manual
auto vmbr0
iface vmbr0 inet static
address 192.168.1.10/24
gateway 192.168.1.1
bridge-ports enp3s0
bridge-stp off
bridge-fd 0
iface vmbr0 inet6 static
address 2001:db8:1:1::10/64
gateway 2001:db8:1:1::1
Replace 2001:db8:1:1::10 with your actual delegated prefix and 2001:db8:1:1::1 with your router's IPv6 address on that segment. Apply without a full reboot:
ifreload -a
Verify the address is live and the gateway is reachable:
ip -6 addr show vmbr0
ping6 -c 3 2606:4700:4700::1111
If that Cloudflare ping succeeds, the host has outbound IPv6. If it fails at the gateway, the router isn't routing the prefix to the Proxmox host's MAC address — fix that on the router side before touching anything else.
Enable IPv6 Forwarding on the Host
This is the single most common reason VMs have an IPv6 address but can't reach anything. Without forwarding, the host routes its own traffic but won't forward packets for guests behind the bridge:
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.d/99-ipv6.conf
sysctl -p /etc/sysctl.d/99-ipv6.conf
Confirm it took:
sysctl net.ipv6.conf.all.forwarding
# net.ipv6.conf.all.forwarding = 1
Set it. Verify it. Every time.
Assigning IPv6 to VMs
Static Assignment in the Guest OS
For anything you'll point DNS at or need to reach reliably, use static. SLAAC generates an address derived from the interface MAC, which changes if you recreate the VM or swap the virtual NIC.
On Ubuntu 24.04 with netplan — edit /etc/netplan/00-installer-config.yaml:
network:
version: 2
ethernets:
ens18:
dhcp4: true
dhcp6: false
addresses:
- 2001:db8:1:1::100/64
routes:
- to: ::/0
via: 2001:db8:1:1::1
nameservers:
addresses:
- 2606:4700:4700::1111
- 2001:4860:4860::8888
netplan apply
On Debian 12 via /etc/network/interfaces:
iface ens18 inet6 static
address 2001:db8:1:1::100/64
gateway 2001:db8:1:1::1
SLAAC for Automatic Assignment
SLAAC lets VMs self-configure from a router-advertised /64 prefix. No config inside the guest — the Linux kernel handles it. You need Router Advertisements arriving on the bridge, which your upstream router may already send.
If not, install radvd on the Proxmox host to send them:
apt install radvd
# /etc/radvd.conf
interface vmbr0 {
AdvSendAdvert on;
MinRtrAdvInterval 10;
MaxRtrAdvInterval 30;
prefix 2001:db8:1:1::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr on;
};
};
systemctl enable --now radvd
SLAAC is worth it for desktop VMs and ephemeral workloads where you don't care about the specific address. For servers, use static.
Configuring IPv6 in LXC Containers
LXC networking goes through pct or directly into /etc/pve/lxc/<vmid>.conf. A common misconception is that IPv6 in LXC requires privileged containers — it does not. Unprivileged containers handle IPv6 identically.
Static IPv6 via pct
pct set 200 --net0 name=eth0,bridge=vmbr0,ip=192.168.1.200/24,gw=192.168.1.1,ip6=2001:db8:1:1::200/64,gw6=2001:db8:1:1::1
This sets both stacks on eth0 in a single command. Proxmox writes the result to the container config and applies it on next start:
pct reboot 200
Inspect what was written:
grep net0 /etc/pve/lxc/200.conf
# net0: name=eth0,bridge=vmbr0,firewall=1,gw=192.168.1.1,gw6=2001:db8:1:1::1,ip=192.168.1.200/24,ip6=2001:db8:1:1::200/64,type=veth
Test from inside the container:
pct exec 200 -- ping6 -c 3 2606:4700:4700::1111
DHCPv6 in LXC Containers
If you run a DHCPv6 server on your network, use ip6=dhcp and let your DHCP server manage assignments:
pct set 200 --net0 name=eth0,bridge=vmbr0,ip=dhcp,ip6=dhcp
The container runs dhclient -6 on startup. This works well when you want address management centralized on your DHCP server rather than scattered across individual container configs.
Proxmox VE Firewall Rules for IPv6
The Proxmox VE firewall has used nftables as its backend since PVE 8.0 and handles IPv4 and IPv6 in a unified ruleset. You write one rule and it covers both — there's no separate ip6tables configuration.
Enable the firewall at the datacenter level first, then at the node:
pvesh set /cluster/firewall/options --enable 1
pvesh set /nodes/pve/firewall/options --enable 1
Cluster-level rules in /etc/pve/firewall/cluster.fw:
[OPTIONS]
enable: 1
[RULES]
# ICMPv6 must be allowed — NDP breaks silently without it
IN ACCEPT -proto icmpv6
# SSH from your IPv6 management subnet
IN SSH(ACCEPT) -source 2001:db8::/32
# Allow established return traffic
IN ACCEPT -state ESTABLISHED,RELATED
Gotcha: Never add a blanket ICMPv6 deny. IPv6 Neighbor Discovery Protocol (NDP) — the functional equivalent of ARP — runs over ICMPv6. Block it and hosts on the same segment stop resolving each other's MAC addresses, path MTU discovery breaks, and you get mysterious packet loss with no clear error messages.
Because IPv6 global addresses are publicly routable (no NAT), every VM with a 2xxx: address is reachable from the internet. Default-deny at the VM firewall level is not a nice-to-have — it's required. Work through hardening Proxmox VE with fail2ban and SSH security before exposing services over IPv6.
For brute-force protection that covers IPv6 source addresses automatically, CrowdSec on Proxmox handles both protocol families with the same agent — no separate IPv6 configuration needed there either.
How to Troubleshoot IPv6 Connectivity in Proxmox
Most failures fall into one of four buckets:
Host has no global IPv6 address: Run ip -6 addr show vmbr0. If you only see fe80:: link-local, your router isn't routing the delegated prefix to the host. Verify the DHCPv6-PD lease on the router and that the static route points at the Proxmox host.
VMs can't reach external IPv6: Check forwarding first — sysctl net.ipv6.conf.all.forwarding must be 1. Then rule out the Proxmox firewall by temporarily disabling it at the cluster level and retesting.
NDP failures — hosts can't find each other: Run tcpdump -i vmbr0 -n icmp6 while pinging from inside a VM. If you see Neighbor Solicitation without a Neighbor Advertisement reply, the host isn't responding. Confirm the host's IPv6 address falls in the same /64 as the VM's address.
Large packets dropped, small pings work: MTU issue. IPv6 requires a minimum of 1280 bytes and relies on Path MTU Discovery. Set the bridge MTU explicitly in /etc/network/interfaces:
iface vmbr0 inet6 static
address 2001:db8:1:1::10/64
gateway 2001:db8:1:1::1
mtu 1500
Test with a large forced-DF ping:
ping6 -M do -s 1400 2606:4700:4700::1111
If that fails while small pings succeed, trace the path:
tracepath6 2606:4700:4700::1111
The first hop that starts reporting a reduced MTU is where the problem lives.
Conclusion
Dual-stack IPv6 on Proxmox VE comes down to three concrete steps: add the inet6 stanza to the host bridge, enable forwarding with sysctl, and write firewall rules that keep ICMPv6 alive. Everything else — SLAAC, DHCPv6, per-container addressing — layers on top once those three are right. The natural next step is VLAN segmentation: give each service zone its own /64 subnet on a separate bridge so firewall rules stay clean and blast radius stays small.