AAAA Record: How to Add IPv6 to Your Domain Safely

Updated: 4 min read Editorial team vserverhost
Short answer

An AAAA record maps a hostname to an IPv6 address, the same way an A record maps it to IPv4. Add one only when the server is reachable on that IPv6 address, the firewall allows ports 80 and 443 over IPv6 and the web server listens on [::]. A broken AAAA record causes timeouts for IPv6 users and failed Let's Encrypt validations.

Most VPS plans now come with IPv6, often a whole /64. Plenty of admins still skip the AAAA record because IPv4 works fine, and that’s a defensible choice. The dangerous case is the opposite one: an AAAA record that exists but points at a server that doesn’t answer on IPv6.

What an AAAA record does

The AAAA record, defined in RFC 3596, is the IPv6 counterpart of the A record. The four As refer to the address being four times as long: 128 bits instead of 32. Otherwise it works identically.

$ORIGIN example.com.
@      3600  IN  A     192.0.2.10
@      3600  IN  AAAA  2001:db8:10::1
www    3600  IN  CNAME example.com.

A dual-stack client looks up both records and usually tries IPv6 first. If IPv6 doesn’t connect quickly, it falls back to IPv4. That algorithm is Happy Eyeballs (RFC 8305), and it’s why a broken AAAA record often goes unnoticed in a browser.

When to add an AAAA record

Add it when all three of these hold:

  1. The server has a public IPv6 address configured on its interface.
  2. The firewall allows 80 and 443 over IPv6.
  3. Your web server or reverse proxy listens on [::].

If one is missing, leave the AAAA record out for now. A missing record costs you a few IPv6-only visitors, most of whom get through NAT64 anyway. A wrong record costs you certificates and page load time.

Check IPv6 on the server

ip -6 addr show scope global
ping -6 -c 3 2001:4860:4860::8888

If the address is there but pings fail, the default route is often missing. Some providers assign the address in their panel but don’t configure it in the image. On Debian with ifupdown it belongs in /etc/network/interfaces, on Ubuntu in the Netplan YAML.

Which address from the /64

With a /64 you choose which address goes into DNS. Short, readable ones such as 2001:db8:10::1 for the web server and 2001:db8:10::25 for mail make logs and firewall rules easier to read. Each one must be configured on the interface. An address that exists only in DNS is exactly the broken AAAA record this guide is about.

Make nginx, Caddy and Docker listen on IPv6

nginx needs a separate IPv6 listen line for every port:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com;
}

Run nginx -T | grep listen and check that every server block has both lines. One block without [::] is enough for that one site to serve the wrong content over IPv6.

Caddy binds to all addresses by default, IPv6 included.

Docker usually publishes ports such as -p 443:443 on the host’s IPv6 addresses too in its default setup. Don’t assume, check:

ss -tlnp | grep -E ':(80|443)\s'
LISTEN 0 4096   0.0.0.0:443   0.0.0.0:*   users:(("nginx",pid=812,fd=7))
LISTEN 0 4096      [::]:443      [::]:*   users:(("nginx",pid=812,fd=8))

No [::] line means the service listens on IPv4 only.

The firewall is where IPv6 gets forgotten

ufw only manages IPv6 if /etc/default/ufw contains IPV6=yes. That’s the Debian and Ubuntu default, but not every provider image keeps it.

grep IPV6 /etc/default/ufw
ufw status verbose | grep -E '80|443'

Each rule should appear twice, once marked (v6). With raw nftables or iptables you need separate ip6tables rules. And some providers’ cloud firewalls keep IPv4 and IPv6 rules apart, so allowing 443 from 0.0.0.0/0 doesn’t open it for ::/0.

Add the AAAA record and test it

In your DNS panel create a record of type AAAA, name @ or the subdomain, value the IPv6 address. At betadomain that’s in the customer area with the domain’s other DNS records, just like setting an A record.

dig example.com AAAA +short
curl -6 -sI https://example.com | head -n 1
curl -4 -sI https://example.com | head -n 1

Both curl calls should print the same status line, for example HTTP/2 200. A timeout on -6 means the AAAA record is broken, whatever the browser shows. If your laptop has no IPv6, run the test from another server.

Let’s Encrypt shows a broken AAAA record first

During HTTP-01 validation Let’s Encrypt looks up both records and prefers IPv6. If the server doesn’t answer there, certbot reports something like:

Detail: 2001:db8:10::1: Fetching http://example.com/.well-known/acme-challenge/...: Timeout during connect (likely firewall problem)

The IPv6 address at the start of the line is the giveaway. Fix IPv6 on the server or remove the AAAA record temporarily. More failure patterns are in the Let’s Encrypt certificate guide.

AAAA records and outgoing mail

Mail is its own case. Once your mail hostname has an AAAA record and Postfix runs with inet_protocols = all, it delivers over IPv6 where it can. Gmail rejects IPv6 senders without a matching PTR record. Set up reverse DNS for the IPv6 address before giving the mail host an AAAA record, or restrict Postfix with inet_protocols = ipv4.

AAAA and A records during a migration

When you move to a new server, both records change. It’s easy to update the A record and forget the AAAA, which leaves IPv6 visitors on the old machine until you notice. The cutover plan in server migration without downtime lists every record that carries an address.

Once curl -6 answers cleanly, the AAAA record belongs in the zone for good. If you’re setting up a new project, you can look up a domain name at betadomain. An .io domain is €61.99 a year and a .org €15.99, with renewals at the same price, and both A and AAAA records live in the same panel.

Found your domain? You can check and register it directly at betadomain – yearly price from €2.99.

FAQ

Do I need an AAAA record if I already have an A record?

It isn't required. Without one, IPv6-only clients reach you through NAT64 if their network provides it, which many mobile networks do. If your VPS has IPv6, publishing it costs nothing once it works.

Can an AAAA record point to an IPv4 address?

No. The value must be an IPv6 address. IPv4-mapped forms like ::ffff:192.0.2.10 can be entered but are meaningless in public DNS.

Why does my site work in the browser but certbot fails?

Your browser uses Happy Eyeballs and silently falls back to IPv4 when IPv6 fails. Let's Encrypt prefers IPv6 when an AAAA record exists, so it hits the broken path and times out.

How do I write an IPv6 address in an AAAA record?

Use the normal compressed form, such as 2001:db8:10::1. Leading zeros in a group and one run of all-zero groups can be dropped. Nameservers store the full 128-bit value either way.