Skip to content

Dual-Stack DNS (A + AAAA)

Dual-stack DNS provides both IPv4 (A) and IPv6 (AAAA) records for the same hostname, enabling clients to connect over whichever protocol is available.

How It Works

dnsweaver treats each provider instance independently. To create both A and AAAA records for the same hostnames, configure two instances pointing to the same DNS provider with different record types and targets:

flowchart LR
    subgraph dnsweaver
        V4[dns-v4 instance<br/>Record: A<br/>Target: 192.0.2.100]
        V6[dns-v6 instance<br/>Record: AAAA<br/>Target: fd00::100]
    end
    V4 --> DNS[(DNS Server)]
    V6 --> DNS
    DNS --> R1["app.example.com → A 192.0.2.100"]
    DNS --> R2["app.example.com → AAAA fd00::100"]

Configuration

Environment Variables

environment:
  - DNSWEAVER_INSTANCES=dns-v4,dns-v6

  # IPv4 records
  - DNSWEAVER_DNS_V4_TYPE=technitium
  - DNSWEAVER_DNS_V4_URL=http://dns-server:5380
  - DNSWEAVER_DNS_V4_TOKEN_FILE=/run/secrets/dns_token
  - DNSWEAVER_DNS_V4_ZONE=example.com
  - DNSWEAVER_DNS_V4_RECORD_TYPE=A
  - DNSWEAVER_DNS_V4_TARGET=192.0.2.100
  - DNSWEAVER_DNS_V4_DOMAINS=*.example.com

  # IPv6 records
  - DNSWEAVER_DNS_V6_TYPE=technitium
  - DNSWEAVER_DNS_V6_URL=http://dns-server:5380
  - DNSWEAVER_DNS_V6_TOKEN_FILE=/run/secrets/dns_token
  - DNSWEAVER_DNS_V6_ZONE=example.com
  - DNSWEAVER_DNS_V6_RECORD_TYPE=AAAA
  - DNSWEAVER_DNS_V6_TARGET=fd00::100
  - DNSWEAVER_DNS_V6_DOMAINS=*.example.com

YAML Config File

global:
  log_level: info
  platform: docker

providers:
  dns-v4:
    type: technitium
    url: http://dns-server:5380
    token_file: /run/secrets/dns_token
    zone: example.com
    record_type: A
    target: 192.0.2.100
    domains:
      - "*.example.com"

  dns-v6:
    type: technitium
    url: http://dns-server:5380
    token_file: /run/secrets/dns_token
    zone: example.com
    record_type: AAAA
    target: "fd00::100"
    domains:
      - "*.example.com"

Both instances use the same DNS server, zone, and domain patterns — only the record type and target differ.

Per-Container Overrides

For services that need different IPv6 targets, use native dnsweaver labels:

services:
  special-app:
    image: myapp:latest
    labels:
      - "traefik.http.routers.app.rule=Host(`app.example.com`)"
      # Override IPv6 target for this specific service
      - "dnsweaver.records.ipv6.hostname=app.example.com"
      - "dnsweaver.records.ipv6.type=AAAA"
      - "dnsweaver.records.ipv6.target=fd00::200"

Combining with Split-Horizon

Dual-stack works alongside split-horizon DNS. Use four instances for full coverage:

environment:
  - DNSWEAVER_INSTANCES=internal-v4,internal-v6,external-v4,external-v6

  # Internal IPv4
  - DNSWEAVER_INTERNAL_V4_TYPE=technitium
  - DNSWEAVER_INTERNAL_V4_RECORD_TYPE=A
  - DNSWEAVER_INTERNAL_V4_TARGET=192.0.2.100
  - DNSWEAVER_INTERNAL_V4_DOMAINS=*.example.com
  # ... (URL, zone, token)

  # Internal IPv6
  - DNSWEAVER_INTERNAL_V6_TYPE=technitium
  - DNSWEAVER_INTERNAL_V6_RECORD_TYPE=AAAA
  - DNSWEAVER_INTERNAL_V6_TARGET=fd00::100
  - DNSWEAVER_INTERNAL_V6_DOMAINS=*.example.com
  # ... (URL, zone, token)

  # External IPv4 (Cloudflare)
  - DNSWEAVER_EXTERNAL_V4_TYPE=cloudflare
  - DNSWEAVER_EXTERNAL_V4_RECORD_TYPE=A
  - DNSWEAVER_EXTERNAL_V4_TARGET=203.0.113.50
  - DNSWEAVER_EXTERNAL_V4_DOMAINS=*.example.com
  # ... (token, zone)

  # External IPv6 (Cloudflare)
  - DNSWEAVER_EXTERNAL_V6_TYPE=cloudflare
  - DNSWEAVER_EXTERNAL_V6_RECORD_TYPE=AAAA
  - DNSWEAVER_EXTERNAL_V6_TARGET=2001:db8::50
  - DNSWEAVER_EXTERNAL_V6_DOMAINS=*.example.com
  # ... (token, zone)

IPv6-Only Services

To create AAAA records without A records for specific services, use exclusion patterns:

environment:
  - DNSWEAVER_INSTANCES=dns-v4,dns-v6

  # IPv4 - exclude ipv6-only subdomain
  - DNSWEAVER_DNS_V4_DOMAINS=*.example.com
  - DNSWEAVER_DNS_V4_EXCLUDE_DOMAINS=*.v6.example.com

  # IPv6 - all subdomains including v6-only
  - DNSWEAVER_DNS_V6_DOMAINS=*.example.com

Services under *.v6.example.com get only AAAA records. All others get both A and AAAA.

Validation

Use the --validate flag to verify dual-stack configuration:

dnsweaver --validate

This confirms both instances are configured correctly with matching record types and valid targets (IPv4 for A, IPv6 for AAAA).

See Also