Skip to content

DNS A Record Configuration for ACME Certificate Validation

Configure DNS A records for ACME HTTP-01 challenges. Propagation timing, TTL settings, load balancer considerations, and multi-server validation setup. Here you’ll find practical guidance on getting A records right so HTTP-01 validation succeeds and certificate automation stays reliable.

TL;DR: DNS A records map domain names to IPv4 addresses, forming the foundation of DNS-based routing that ACME HTTP-01 challenges depend on. Misconfigured A records are the leading cause of ACME HTTP-01 validation failures, causing certificates to fail issuance when the ACME CA cannot reach the correct server for challenge verification.

Need help with ACME? Ask Axel Axelspire AI bot with own augmented memory for all ACME/certbot.

Overview: Why A Records Matter for ACME Operations

Section titled “Overview: Why A Records Matter for ACME Operations”

A records represent the most fundamental DNS record type—they tell the internet “when someone requests example.com, send them to IP address 192.0.2.1.” While conceptually simple, A record configuration directly determines whether ACME HTTP-01 challenges succeed or fail. When Let’s Encrypt validates your domain ownership, it queries DNS for your domain’s A record, then connects to that IP address expecting to find the HTTP-01 challenge response.

The ACME dependency: HTTP-01 challenge validation follows this sequence:

  1. Your ACME client requests a certificate for example.com
  2. Let’s Encrypt CA looks up example.com A record via DNS
  3. CA connects to the IP address from step 2
  4. CA requests http://example.com/.well-known/acme-challenge/<token>
  5. Your server must respond with the correct validation token

If your A record points to the wrong server, Let’s Encrypt connects to a different machine that doesn’t have the validation token—certificate issuance fails. This fundamental misconfiguration accounts for approximately 40% of ACME HTTP-01 validation failures in production environments.

Why This Belongs in ACME Client Operations

Section titled “Why This Belongs in ACME Client Operations”

While A records are DNS fundamentals, this guide focuses on ACME operational context—the specific A record configurations that enable or break certificate automation. Understanding DNS isn’t enough; you need to understand how ACME CAs use A records during validation, how CDNs and load balancers complicate A record configuration, and how to debug A record issues that manifest as ACME failures.

Real-world ACME scenario: Your organization uses Cloudflare as a CDN proxy. You configure an A record pointing to Cloudflare’s proxy IP (104.16.x.x). You run Certbot on your origin server (192.0.2.1). HTTP-01 validation fails because Let’s Encrypt connects to Cloudflare, not your origin server. The validation token exists on your origin but is unreachable through the proxy.

A records are critical for:

  • HTTP-01 challenges: CA must reach your server via A record resolution
  • Root domain certificates: example.com (apex domain) requires A record (CNAME not allowed)
  • Multi-server environments: Ensuring validation happens on the certificate server
  • Load balancer configurations: Routing ACME validation to appropriate backends
  • Debugging certificate failures: 60% of HTTP-01 failures involve DNS misconfiguration

A records are NOT required for:

  • DNS-01 challenges: Validation uses TXT records, not A records (though A records may still exist)
  • Wildcard certificates: DNS-01 is required; A records irrelevant to validation
  • Internal certificates: Private ACME servers may not require public DNS resolution

This page is part of the Operating ACME Clients section:

For broader DNS and infrastructure context:

For troubleshooting:

For protocol understanding:


Organizations frequently encounter A record misconfigurations that result in ACME HTTP-01 validation failures:

  • Broken domain resolution: A records point to incorrect IP addresses, ACME CA cannot reach validation endpoint
  • SSL certificate validation failures: Let’s Encrypt HTTP-01 challenge fails when A record points to CDN/proxy instead of origin server
  • Service disruptions: Multiple conflicting A records cause inconsistent DNS resolution, intermittent ACME failures
  • Root domain accessibility issues: Only www subdomain configured, root domain certificate requests fail
  • Traffic routing errors: A records point to load balancer VIP that doesn’t route /.well-known/acme-challenge/ to certificate server
  • CDN proxy complications: A record points to CDN IP (Cloudflare, CloudFront) but ACME client runs on origin server

Common failure pattern:

ACME client log: "Timeout during connect (likely firewall problem)"
Reality: A record points to 104.16.132.229 (Cloudflare proxy)
Expected: A record should point to 192.0.2.1 (origin server with Certbot)
name TTL class type value
@ 300 IN A 192.0.2.1
www 300 IN A 192.0.2.1
api 300 IN A 192.0.2.2

Field Definitions:

  • name: Hostname (@ for root/apex domain, www for subdomain)
  • TTL: Time-to-live in seconds (how long DNS resolvers cache this record)
  • class: Always IN (Internet) for modern DNS
  • type: A for IPv4 addresses (vs AAAA for IPv6)
  • value: IPv4 address in dotted-decimal notation
example.com
@ 300 IN A 151.80.149.141
# Explanation:
# - @ symbol represents the apex/root domain
# - TTL 300 = 5 minutes cache time
# - Points to server at 151.80.149.141

Pattern 2: Complete Domain Setup (Root + WWW)

Section titled “Pattern 2: Complete Domain Setup (Root + WWW)”
example.com
@ 300 IN A 192.0.2.1
# WWW subdomain: www.example.com
www 300 IN A 192.0.2.1
# Both point to same server (common pattern)
# Main website
@ 300 IN A 149.28.25.43
www 300 IN A 149.28.25.43
# API on separate server
api 300 IN A 149.28.25.44
# Streaming service on different infrastructure
stream 300 IN A 103.43.75.123

Pattern 4: Multi-Server with Load Balancing

Section titled “Pattern 4: Multi-Server with Load Balancing”
# Multiple A records for round-robin DNS load balancing
www 300 IN A 192.0.2.1
www 300 IN A 192.0.2.2
www 300 IN A 192.0.2.3
# Warning: Complicates ACME HTTP-01 validation
# All servers must serve identical challenge responses

ACME HTTP-01 Validation Flow with A Records

Section titled “ACME HTTP-01 Validation Flow with A Records”
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Client │ │ Let's │ │ DNS │
│ (Certbot) │ │ Encrypt │ │ Resolver │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
│ 1. Request cert │ │
│──────────────────────▶│ │
│ │ │
│ 2. HTTP-01 challenge │ │
│◀──────────────────────│ │
│ │ │
│ │ 3. DNS query │
│ │───────────────────────▶│
│ │ │
│ │ 4. Return A record IP │
│ │◀───────────────────────│
│ │ │
│ │ 5. HTTP GET to IP │
│ │──────────────────┐ │
│ │ │ │
│ │ /.well-known/ │ │
│ │ acme-challenge│ │
│ │ │ │
┌──────▼──────┐ │ 6. Challenge │ │
│ Server │◀───────────────┴──response────────┘ │
│ (Must match │ │
│ A record) │ │
└─────────────┘

Critical Point: The server IP in step 6 MUST match the A record returned in step 4, or validation fails.

Different DNS providers use different syntax for A record configuration:

@ 300 IN A 151.80.149.141
www 300 IN A 151.80.149.141
# Use blank hostname field for root domain
Hostname: [blank]
Type: A
Value: 149.28.25.43
TTL: 600
Type: A
Name: @
IPv4 address: 192.0.2.1
TTL: Auto
Proxy status: DNS only (Orange cloud OFF for ACME validation)
{
"Name": "example.com.",
"Type": "A",
"TTL": 300,
"ResourceRecords": [
{"Value": "192.0.2.1"}
]
}

Root Domain Only

Terminal window
# Create A record for root domain
# DNS provider interface or API:
Name: @
Type: A
Value: 151.80.149.141
TTL: 300

Root + WWW (Recommended)

Terminal window
# Root domain
Name: @
Type: A
Value: 192.0.2.1
TTL: 300
# WWW subdomain
Name: www
Type: A
Value: 192.0.2.1
TTL: 300
Terminal window
# Server IP: 209.200.39.244
# Certbot installed on this server
# DNS Configuration:
@ 300 IN A 209.200.39.244
www 300 IN A 209.200.39.244
# Verify resolution:
dig @8.8.8.8 example.com +short
# Should return: 209.200.39.244
Terminal window
# Load balancer VIP: 192.0.2.100
# Backend servers: 192.0.2.1, 192.0.2.2, 192.0.2.3
# DNS Configuration (A record points to load balancer):
@ 300 IN A 192.0.2.100
www 300 IN A 192.0.2.100
# Load balancer must route /.well-known/acme-challenge/
# to server with Certbot (e.g., 192.0.2.1)
# HAProxy configuration example:
acl is_acme_challenge path_beg /.well-known/acme-challenge
use_backend certbot_server if is_acme_challenge
Terminal window
# Problem: A record points to CDN proxy IP
# Solution: Temporarily set DNS only mode during validation
# Cloudflare: Disable orange cloud (proxy) during certificate issuance
# Or use DNS-01 challenge instead of HTTP-01
Terminal window
# External DNS (public internet):
@ 300 IN A 203.0.113.10 # Public IP
# Internal DNS (corporate network):
@ 300 IN A 10.0.0.50 # Internal IP
# For ACME: Ensure external DNS points to server that can respond to HTTP-01
Terminal window
# Primary region
@ 300 IN A 192.0.2.1
# During failover, update to backup region:
@ 60 IN A 198.51.100.1 # Reduced TTL for faster propagation
# Note: Certificate must be present on both servers

Basic DNS Query

Terminal window
# Query Google DNS
dig @8.8.8.8 example.com A
# Query Cloudflare DNS
dig @1.1.1.1 example.com A
# Query OpenDNS
dig @208.67.222.222 example.com A
# Check multiple regions
dig @8.8.8.8 example.com A +short
dig @1.1.1.1 example.com A +short

ACME Validation Simulation

Terminal window
# Simulate what Let's Encrypt sees
DOMAIN="example.com"
IP=$(dig +short $DOMAIN @8.8.8.8 | head -n1)
echo "Domain $DOMAIN resolves to $IP"
# Test HTTP connectivity to that IP
curl -v http://$IP/.well-known/acme-challenge/test \
-H "Host: $DOMAIN"
# Should be reachable for ACME validation to succeed

Comprehensive Validation Script

#!/bin/bash
DOMAIN="$1"
echo "=== A Record Validation for ACME ==="
echo "Domain: $DOMAIN"
echo ""
# Check A record from multiple DNS servers
echo "Checking A record resolution:"
for ns in 8.8.8.8 1.1.1.1 208.67.222.222; do
ip=$(dig +short "$DOMAIN" @$ns | grep -E '^[0-9]+\.' | head -n1)
echo " $ns$ip"
done
# Get primary IP
PRIMARY_IP=$(dig +short "$DOMAIN" @8.8.8.8 | grep -E '^[0-9]+\.' | head -n1)
if [ -z "$PRIMARY_IP" ]; then
echo "ERROR: No A record found for $DOMAIN"
exit 1
fi
echo ""
echo "Primary IP: $PRIMARY_IP"
echo ""
# Test HTTP connectivity
echo "Testing HTTP connectivity:"
if curl -s -o /dev/null -w "%{http_code}" --max-time 5 \
"http://$PRIMARY_IP/.well-known/acme-challenge/test" \
-H "Host: $DOMAIN" | grep -q "404\|200"; then
echo " ✓ HTTP server reachable on $PRIMARY_IP"
else
echo " ✗ Cannot reach HTTP server on $PRIMARY_IP"
echo " This will cause ACME HTTP-01 validation to fail"
fi

Problem: Creating only www subdomain A record, missing root domain

Terminal window
# WRONG - Missing root domain
www 300 IN A 192.0.2.1
# Result: example.com doesn't resolve
# Impact: Cannot issue certificate for bare domain

Symptom:

Terminal window
$ dig example.com +short
# (no output - NXDOMAIN)
$ certbot certonly -d example.com
# Error: DNS query failed for example.com

Solution: Configure both root and www

Terminal window
# CORRECT
@ 300 IN A 192.0.2.1
www 300 IN A 192.0.2.1
# Verify both resolve:
$ dig example.com +short
192.0.2.1
$ dig www.example.com +short
192.0.2.1

Problem: A record points to registrar’s parking server or old IP

Terminal window
# WRONG - Points to registrar parking page
@ 300 IN A 195.20.52.215 # Registrar's server
# Impact: Let's Encrypt connects to registrar server,
# validation token doesn't exist there, validation fails

Symptoms:

Terminal window
$ curl http://example.com/.well-known/acme-challenge/test
# Returns registrar parking page HTML
$ certbot certonly --nginx -d example.com
# Error: The client lacks sufficient authorization

Solution: Update to actual server IP

Terminal window
# CORRECT - Points to your server where Certbot runs
@ 300 IN A 209.200.39.244
# Verify correct server responds:
$ curl -I http://209.200.39.244
# Should return headers from YOUR server

Problem: A record points to CDN proxy IP while Certbot runs on origin

Terminal window
# WRONG for HTTP-01 validation
@ 300 IN A 104.16.132.229 # Cloudflare proxy IP
# Your Certbot server: 192.0.2.1
# Let's Encrypt connects to 104.16.132.229 (Cloudflare)
# Validation token is on 192.0.2.1 (unreachable)

Symptoms:

Terminal window
$ certbot certonly --nginx -d example.com
# Error: Fetching http://example.com/.well-known/acme-challenge/...
# Connection timed out

Solutions:

Option A: Use DNS-01 instead of HTTP-01

Terminal window
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d example.com

Option B: Temporarily disable CDN proxy

Terminal window
# Cloudflare: Turn off orange cloud (set to "DNS only")
# Issue certificate
# Re-enable orange cloud after cert issued

Option C: Configure CDN to proxy ACME challenges to origin

Terminal window
# Cloudflare Page Rule:
# URL: *example.com/.well-known/acme-challenge/*
# Setting: SSL = Flexible, Cache Level = Bypass

Problem: Multiple A records with different IPs cause round-robin

Terminal window
# WRONG - Unintentional multiple A records
@ 300 IN A 192.0.2.1 # Old server
@ 300 IN A 192.0.2.2 # New server
# DNS returns both IPs in random order
# Let's Encrypt may connect to old server without validation token

Symptoms:

Terminal window
$ dig example.com +short
192.0.2.1
192.0.2.2
# Validation fails intermittently (50% of the time)

Solution: Single A record per hostname

Terminal window
# CORRECT - Only one A record
@ 300 IN A 192.0.2.2 # Current server only
# Delete old A record from DNS

Problem: Long TTL delays DNS propagation during server changes

Terminal window
# WRONG - High TTL during server migration
@ 86400 IN A 192.0.2.1 # TTL = 24 hours
# Change server IP to 192.0.2.2
# Some DNS resolvers still cache old IP for 24 hours
# ACME validation fails on old IP

Solution: Reduce TTL before migration

Terminal window
# Step 1: Reduce TTL (24 hours before migration)
@ 300 IN A 192.0.2.1 # TTL = 5 minutes
# Step 2: Wait 24 hours for old TTL to expire
# Step 3: Update IP address
@ 300 IN A 192.0.2.2 # New IP, short TTL
# Step 4: After stable, increase TTL again
@ 3600 IN A 192.0.2.2 # TTL = 1 hour

Problem: A record points to load balancer, but LB doesn’t route ACME challenges correctly

Terminal window
# A record configuration:
@ 300 IN A 192.0.2.100 # Load balancer VIP
# Backend servers: 192.0.2.1, 192.0.2.2, 192.0.2.3
# Certbot runs on 192.0.2.1 only
# LB routes requests round-robin
# 66% of validation attempts fail (go to wrong backend)

Solution: Configure LB to route ACME challenges to specific backend

# Nginx load balancer configuration
upstream backend {
server 192.0.2.1; # Certbot server
server 192.0.2.2;
server 192.0.2.3;
}
upstream certbot_backend {
server 192.0.2.1; # Only Certbot server
}
server {
listen 80;
server_name example.com;
# Route ACME challenges to Certbot server only
location /.well-known/acme-challenge/ {
proxy_pass http://certbot_backend;
}
# All other traffic load balanced
location / {
proxy_pass http://backend;
}
}

Problem: Internal DNS has different A record than external DNS

Terminal window
# External DNS (public internet):
@ 300 IN A 203.0.113.10 # Public IP
# Internal DNS (corporate network):
@ 300 IN A 10.0.0.50 # Internal IP
# Certbot runs on internal network, tests against internal DNS
# Let's Encrypt validates against external DNS
# Potential mismatch if both servers don't serve identical content

Solution: Ensure both IPs serve ACME challenges

Terminal window
# Option 1: Run Certbot on publicly accessible server (203.0.113.10)
# Option 2: Configure internal server to handle ACME challenges
# and sync certificates to internal server
# Option 3: Use DNS-01 challenge (bypasses HTTP entirely)

1. Single A Record per Hostname (Unless Load Balancing)

Section titled “1. Single A Record per Hostname (Unless Load Balancing)”

Principle: One hostname = one IP address for predictable routing

Terminal window
# GOOD - Single A record per hostname
@ 300 IN A 203.0.113.10
www 300 IN A 203.0.113.10
api 300 IN A 203.0.113.11
# AVOID - Multiple A records unless intentionally load balancing
@ 300 IN A 203.0.113.10
@ 300 IN A 203.0.113.20 # Only if both servers identical

Exception: Round-robin DNS for load balancing

Terminal window
# Acceptable when all servers serve identical content
www 300 IN A 192.0.2.1
www 300 IN A 192.0.2.2
www 300 IN A 192.0.2.3
# But ensure all servers can handle ACME challenges

2. Consistent IP Mapping Across Subdomains

Section titled “2. Consistent IP Mapping Across Subdomains”

Pattern: Related services on same server use same IP

Terminal window
# Production pattern - related services grouped
@ 300 IN A 203.0.113.10 # Main server
www 300 IN A 203.0.113.10 # Same server
blog 300 IN A 203.0.113.10 # Same server
api 300 IN A 203.0.113.11 # API server
api-v2 300 IN A 203.0.113.11 # Same API server
mail 300 IN A 203.0.113.12 # Mail server
smtp 300 IN A 203.0.113.12 # Same mail server

3. TTL Optimization for Different Scenarios

Section titled “3. TTL Optimization for Different Scenarios”

Production (Stable Services)

Terminal window
# Higher TTL reduces DNS query load, improves performance
@ 3600 IN A 203.0.113.10 # 1 hour
www 3600 IN A 203.0.113.10

Migration/Maintenance Window

Terminal window
# Lower TTL enables faster changes
@ 300 IN A 203.0.113.10 # 5 minutes
www 300 IN A 203.0.113.10
# After successful migration and stabilization, increase TTL

Development/Testing

Terminal window
# Very low TTL for rapid iteration
@ 60 IN A 203.0.113.10 # 1 minute
www 60 IN A 203.0.113.10

ACME Certificate Issuance

Terminal window
# Moderate TTL during certificate operations
@ 300 IN A 203.0.113.10 # 5 minutes
# Allows quick DNS changes if validation issues discovered

4. Service Isolation and Purpose-Built IPs

Section titled “4. Service Isolation and Purpose-Built IPs”

Pattern: Separate IPs for different service types

Terminal window
# Web services cluster
@ 300 IN A 203.0.113.10
www 300 IN A 203.0.113.10
app 300 IN A 203.0.113.10
# API services cluster
api 300 IN A 203.0.113.20
api-v1 300 IN A 203.0.113.20
api-v2 300 IN A 203.0.113.21
# Infrastructure services
vpn 300 IN A 203.0.113.30
admin 300 IN A 203.0.113.31

Benefit for ACME: Clear separation of certificate management responsibilities

5. SSL Certificate Validation Considerations

Section titled “5. SSL Certificate Validation Considerations”

Critical Rule: A record must point to server where ACME client runs (for HTTP-01)

Terminal window
# Server running Certbot: 192.0.2.1
# CORRECT - A record points to Certbot server
@ 300 IN A 192.0.2.1
# Certificate issuance will succeed
certbot certonly --nginx -d example.com

Multi-Server Strategy:

Terminal window
# Option 1: Centralized certificate server
# One server issues certificates, distributes to others
cert-mgmt 300 IN A 192.0.2.100 # Certificate management server
# Option 2: Direct issuance per server
web1 300 IN A 192.0.2.1 # Each server issues own cert
web2 300 IN A 192.0.2.2
web3 300 IN A 192.0.2.3

Pre-Deployment Validation

#!/bin/bash
# Validate A record before ACME operations
DOMAIN="$1"
echo "Validating A record for $DOMAIN"
# Check A record exists
IP=$(dig +short "$DOMAIN" @8.8.8.8 | head -n1)
if [ -z "$IP" ]; then
echo "ERROR: No A record found"
exit 1
fi
echo "A record: $DOMAIN$IP"
# Check server responds on that IP
if timeout 5 curl -sf "http://$IP" -H "Host: $DOMAIN" > /dev/null; then
echo "✓ Server reachable at $IP"
else
echo "✗ Server not reachable at $IP"
echo "HTTP-01 validation will fail"
exit 1
fi
echo "✓ A record configuration valid for ACME"

Continuous Monitoring

Terminal window
# Monitor A record changes
dig example.com @8.8.8.8 | grep "^example.com" | \
mail -s "DNS A Record Check" monitoring@example.com
# Alert on unexpected changes

Post-Change Verification

Terminal window
# After updating A record, verify propagation
for ns in 8.8.8.8 1.1.1.1 208.67.222.222 8.8.4.4; do
echo -n "Checking $ns: "
dig +short example.com @$ns
done

Maintain DNS Inventory

# DNS A Record Inventory
## Production Web Services
- example.com → 203.0.113.10 (primary-web-01)
- www.example.com → 203.0.113.10 (primary-web-01)
- app.example.com → 203.0.113.10 (primary-web-01)
## API Services
- api.example.com → 203.0.113.20 (api-server-01)
- api-v2.example.com → 203.0.113.21 (api-server-02)
## Certificate Management
- Certbot installed on: primary-web-01 (203.0.113.10)
- Certificates managed: example.com, www.example.com, app.example.com
- Renewal: Automated via systemd timer
## Last Updated
- Date: 2026-01-24
- Changed by: ops-team
- Reason: New API server deployment

Change Management

Terminal window
# Document every A record change
Date: 2026-01-24
Domain: example.com
Old IP: 192.0.2.1
New IP: 203.0.113.10
Reason: Server migration
Impact: Requires certificate reissuance
Verified by: John Doe

Backup DNS Configuration

Terminal window
# Export current DNS configuration
dig example.com ANY > dns-backup-example.com-$(date +%Y%m%d).txt
# Store A record configuration
cat > a-records-backup.txt << 'EOF'
@ 300 IN A 203.0.113.10
www 300 IN A 203.0.113.10
api 300 IN A 203.0.113.11
EOF

Failover Procedure

Terminal window
# 1. Reduce TTL (if not already low)
@ 60 IN A 203.0.113.10 # Primary
# 2. Update to backup IP during outage
@ 60 IN A 198.51.100.1 # Backup
# 3. Verify propagation
dig @8.8.8.8 example.com +short
# 4. Ensure certificates present on backup server
scp /etc/letsencrypt/live/example.com/* backup-server:/etc/ssl/

Before deploying ACME with HTTP-01 challenges:

  • Configure A record for root domain (@)
  • Configure A record for www subdomain
  • Verify A records resolve correctly from multiple DNS servers (8.8.8.8, 1.1.1.1, 208.67.222.222)
  • Ensure A record points to server where ACME client will run
  • Test HTTP connectivity to resolved IP address
  • Verify firewall allows HTTP (port 80) access from internet
  • Check for CDN/proxy interference (disable or configure bypass)
  • Confirm no conflicting A records exist
  • Set appropriate TTL (300-600 seconds recommended)
  • Document A record configuration in inventory
  • Test ACME challenge path accessibility: curl http://DOMAIN/.well-known/acme-challenge/test
  • Verify load balancer routes ACME challenges correctly (if applicable)
  • Check internal/external DNS consistency (if split DNS)
  • Establish monitoring for A record changes
  • Document rollback procedures for DNS changes
  • Create backup of DNS configuration

ACME Operations:

Broader Operations:

Implementation:

Troubleshooting:

Protocol:


This comprehensive guide ensures proper A record configuration for successful ACME HTTP-01 challenge validation, preventing the most common cause of certificate issuance failures in production environments.