IPv6 on cPanel has a bad reputation, and until recently it deserved one. The original 2013 implementation could not use SNI on a shared IPv6 address, and it refused to let the server's own address and the customer pool live inside the same prefix — so every operator either burned two separate prefixes or gave up. Both restrictions are gone as of v126, which means every supported branch today (v134 LTS, v136 RELEASE) can do a normal dual-stack deployment.
This is the end-to-end path for a shared or reseller box: the OS-level address, WHM's shared-versus-dedicated model, AAAA records without breaking AutoSSL, the mail changes that matter, and the firewall side. Roughly 45 minutes on a single server, most of it waiting for DNS.
The one hard constraint: licensing is IPv4
cPanel & WHM cannot run IPv6-only. The server needs at least one routable IPv4 address, and
that address is what the license binds to — verify.cpanel.net checks are IPv4 only. Adding
IPv6 does not change, invalidate, or require a re-issue of your license, and it does not
affect which cPanel license tier you need; account counts are what drive
tier, not address families.
The rest of the stack is more relaxed. Imunify360 and the CloudLinux Network gained full IPv6 support in late 2025 — key-based licenses auto-register the IPv6 address, and IP-based license records now accept IPv6 as well as IPv4. That does not change Imunify360 tier selection either.
Step 1 — Bring the address up at the OS level
Get a prefix from your provider first. A /64 is the practical minimum and what cPanel's
range validation expects; a /48 is better if you plan on per-customer allocations.
On AlmaLinux 9 and CloudLinux OS 9+ with NetworkManager:
nmcli connection show
nmcli connection modify "System eth0" \
ipv6.method manual \
ipv6.addresses "2001:db8:1a34:56cf::100/64" \
ipv6.gateway "2001:db8:1a34:56cf::1"
nmcli connection up "System eth0"
Confirm the kernel and the default route agree before touching WHM:
ip -6 addr show scope global
ip -6 route show default
ping6 -c3 ipv6.google.com
If ping6 fails here, stop. Nothing in WHM fixes a missing route or an unannounced prefix.
Step 2 — Tell WHM about the address
Three interfaces, in this order:
- Server Configuration → Basic WebHost Manager Setup — put the address in the field for the shared IPv6 address used for virtual hosts. One address, and it is the one nearly every account should end up using.
- Networking Setup → Resolver Configuration — add an IPv6 resolver so the box can resolve over v6 rather than falling back to v4 for every lookup.
- Server Configuration → Tweak Settings → System — set Listen on IPv6 Addresses to
On so
cpsrvdanswers on ports 2082–2087 over v6. Without this, cPanel and WHM themselves stay v4-only even though the sites are dual-stack.
Step 3 — Add an IPv6 range
IP Functions → IPv6 Address Ranges → Add Range. Give it a name (64 characters max), the prefix in CIDR notation, and a type of Available or Reserved.
Name: customer-v6
Range: 2001:0db8:1a34:56cf::/64
Type: Available
Since v126 the range may overlap the prefix the server itself sits in, so a single /64
covers both. Reserve individual addresses — the gateway, the shared address, anything your
load balancer owns — by adding them as /128 Reserved ranges. cPanel has no concept of
"reserve this one address inside an available range" other than that.
whmapi1 ipv6_range_list
Step 4 — Assign addresses to accounts
IP Functions → Assign IPv6 Address, pick the account, then choose either a named range or the server's shared IPv6 address.
Pick shared unless you have a specific reason not to. A shared IPv6 address with SNI serves
every account, needs no routing work, and keeps outbound traffic coming from one predictable
source. Dedicated /128 per account works, but the kernel picks a source address for
outbound connections on its own, so unless you add per-account source routing your outbound
IPv6 traffic will not match the address you assigned — which quietly breaks SPF alignment
and any IP-reputation assumptions you were making.
whmapi1 ipv6_enable_account user=acmecorp range=customer-v6
whmapi1 ipv6_disable_account user=acmecorp
Step 5 — Publish AAAA records carefully
An AAAA record that points anywhere other than a working IPv6 listener is worse than no AAAA record at all. Clients on v6 networks will prefer it, and AutoSSL's HTTP domain control validation will follow it too — a stale AAAA left over from a migration is one of the most common causes of DCV failures that look inexplicable in the AutoSSL logs.
Add AAAA only after the vhost answers:
curl -6 -sI https://example.com | head -1
dig +short AAAA example.com
If you run a DNS cluster, add records on the writeable node and let the cluster sync rather than editing zones on each box — see the DNSONLY cluster guide. Zones signed with DNSSEC re-sign automatically when you add the AAAA; no manual key work is needed.
Step 6 — Mail, which is where dual-stack actually hurts
Google, Microsoft, and most large mailbox providers apply stricter rules to IPv6 senders than to IPv4 ones. Mail from an IPv6 address with no matching reverse DNS is commonly rejected outright rather than filtered.
Before you let Exim send over IPv6:
- Get rDNS on the sending address. Your provider sets the PTR for the
/64; many will not do it per-/128without a ticket. - Add
ip6:to every SPF record. An SPF record with onlyip4:mechanisms fails the moment mail leaves over v6. The SPF, DKIM, and DMARC guide covers the record syntax. - Add the IPv6 addresses in Exim Configuration Manager, and enable IPv6 under Mailserver Configuration so Dovecot listens on v6 for IMAP and POP3.
If rDNS is not in place yet, leave Exim sending over IPv4 and publish AAAA records for web traffic only. Inbound IPv6 SMTP is safe to enable immediately; it is outbound that carries the deliverability risk.
Step 7 — Firewall and security stack
CSF manages ip6tables alongside iptables, but the port lists are separate. Set
IPV6 = "1" in /etc/csf/csf.conf, then mirror your port lists — a rule added to TCP_IN
does nothing for v6 traffic:
grep -E '^(IPV6|TCP6_IN|TCP6_OUT)' /etc/csf/csf.conf
csf -ra
Verify the ruleset is actually populated rather than trusting the config:
ip6tables -L -n | head -20
The same split applies to the rest of the stack. Imunify360 configures ports separately for
v4 and v6, and its blocklists work at /64 granularity — ipset will not accept a single
IPv6 host, so a blocked address takes its whole /64 with it. That is normally what you
want for abuse, occasionally not what you want for a false positive on a residential
connection. See CSF and Imunify360 coexistence if
you're running both, which most hosts are.
Verify the whole path
curl -6 -sI https://example.com | head -1
curl -6 -sI https://server1.example.com:2087 | head -1
dig +short AAAA example.com
ip6tables -L -n | wc -l
exim -bV | head -1
Then test from outside your own network — a v6-enabled mobile connection is the fastest honest check, since your office link may be v4-only or tunnelled.
Can cPanel run on an IPv6-only server?+
Does adding IPv6 require a new cPanel license?+
Should each cPanel account get its own IPv6 address?+
Why did AutoSSL start failing after I enabled IPv6?+
What IPv6 prefix size does WHM need?+
Does enabling IPv6 break CSF or Imunify360?+
Next steps
- If mail is the reason you're doing this, tighten the authentication records first with
the SPF, DKIM, and DMARC setup for cPanel
— adding
ip6:mechanisms before Exim starts using v6 avoids a bad first week. - Running two firewalls is the norm on cPanel boxes; the CSF installation guide covers the port-list layout you need to mirror for v6.
- Planning a fleet-wide rollout across dozens of servers? Talk to us about license counts before you re-IP anything — batching IP changes across a fleet is far easier to handle in one pass than one ticket at a time.