IPv6 gives every server plenty of globally routable addresses and avoids NAT entirely. Many networks — mobile carriers especially — now carry a large share of traffic over IPv6. If your hosting network provides IPv6, configuring it takes a few lines; this guide covers the setup and the services that need to know about it.
You’ll need from your provider: an IPv6 address or prefix (e.g. 2001:db8:1234::10/64) and the gateway (sometimes a link-local address such as fe80::1).
Check the current state
ip -6 addr
ip -6 route
ping -6 -c 3 2606:4700:4700::1111 # Cloudflare DNS over IPv6
If you only see fe80:: addresses, the interface has link-local IPv6 but no global address yet.
Ubuntu: Netplan
network:
version: 2
ethernets:
eth0:
addresses:
- 203.0.113.10/24
- "2001:db8:1234::10/64"
routes:
- to: default
via: 203.0.113.1
- to: "::/0"
via: "2001:db8:1234::1"
nameservers:
addresses: [1.1.1.1, "2606:4700:4700::1111"]
Quote IPv6 addresses in YAML. If the gateway is link-local (fe80::1), add on-link: true to that route. Apply with sudo netplan try. See Netplan static IP.
Debian: /etc/network/interfaces
iface eth0 inet6 static
address 2001:db8:1234::10/64
gateway 2001:db8:1234::1
Then sudo systemctl restart networking (from the console if possible) or sudo ifup eth0.
AlmaLinux / Rocky: nmcli
sudo nmcli connection modify "System eth0" ipv6.method manual \
ipv6.addresses "2001:db8:1234::10/64" ipv6.gateway "2001:db8:1234::1"
sudo nmcli connection up "System eth0"
Temporary (for testing)
sudo ip -6 addr add 2001:db8:1234::10/64 dev eth0
sudo ip -6 route add default via 2001:db8:1234::1 dev eth0
Lost at reboot — use it to verify settings before writing them permanently.
Test
ping -6 -c 3 google.com
curl -6 https://ifconfig.co
From outside, ping your server’s IPv6 address, or use an online IPv6 test.
Make sure IPv6 isn’t disabled
Some images or hardening scripts disable IPv6 via sysctl:
sysctl net.ipv6.conf.all.disable_ipv6 net.ipv6.conf.default.disable_ipv6
grep -r disable_ipv6 /etc/sysctl.conf /etc/sysctl.d/
Both should be 0. Also check the kernel command line (cat /proc/cmdline) for ipv6.disable=1.
Firewall: IPv6 has its own rules
- UFW: set
IPV6=yesin/etc/default/ufw(default) — rules apply to both families. - firewalld and nftables
inettables: cover both automatically. - iptables: IPv6 uses ip6tables — a server with strict iptables rules and no ip6tables rules is wide open over IPv6.
Allow ICMPv6. Unlike IPv4, IPv6 depends on it for neighbour discovery and path MTU discovery; blocking it breaks connectivity in subtle ways.
Services listening on IPv6
sudo ss -tlnp | grep -E '\[::\]|\*:'
- Nginx: add
listen [::]:80;andlisten [::]:443 ssl;to server blocks (Ubuntu’s default site already has them). - Apache:
Listen 80covers both by default. - SSH: listens on both by default.
- Apps binding to
0.0.0.0listen on IPv4 only; bind to::for both (on Linux,::usually accepts IPv4 too unlessIPV6_V6ONLYis set).
DNS: AAAA records
Add an AAAA record pointing your domain to the IPv6 address. Only do this once the server actually answers over IPv6 — a broken AAAA record makes the site fail for IPv6 users, and Let’s Encrypt prefers IPv6 when it validates. See DNS records explained.
Reverse DNS
Mail servers sending over IPv6 need a PTR record for the IPv6 address too — many receivers reject IPv6 mail without one. Set it up where your provider allows, or force your mail server to send over IPv4. See PTR records.
Troubleshooting
- Address configured but no connectivity — wrong gateway, or a link-local gateway without
on-link. Checkip -6 routeandip -6 neigh. - Works for a while, then stops — router advertisements may be overriding your static config; set
accept-ra: falsein Netplan (ornet.ipv6.conf.eth0.accept_ra=0). - Some sites hang — MTU/PMTU issues, often caused by blocked ICMPv6.
- Docker containers lack IPv6 — Docker needs explicit IPv6 configuration (
"ipv6": trueand a subnet in/etc/docker/daemon.json).
Related: IPv4 vs IPv6 and the ip command. IPv6 availability varies by data center — check with our support team for your location before relying on it.