Skip to content

DNS Providers

X4Applegate edited this page Sep 10, 2026 · 1 revision

DNS Providers

Managed DNS does two things with one set of credentials:

  1. A records — when you save a proxy host, redirection or advanced route with a provider and zone selected, CaddyUI creates the A record(s) pointing at the server's public IP, remembers the record reference, updates it on edit and deletes it with the row. Multi-domain routes get a per-hostname pre-flight showing which records will be created and which already exist. Records CaddyUI did not create are never overwritten.
  2. DNS-01 — the same credentials are handed to Caddy for ACME DNS-01 challenges, which is what wildcard certificates and hosts unreachable on port 80 need. Turn off Create public A records on a resource to keep DNS-01 while managing the A record elsewhere (internal names, split DNS).

Set the Server IP for each Caddy Fleet entry at the top of Settings → DNS; every provider writes that address into its A records. Changing it re-points every managed record in one background pass.

The connected Caddy must be built with the matching caddy-dns module for DNS-01. The repository's Dockerfile.caddy includes all eight providers below; the stock caddy:2-alpine image includes none.

Provider Credentials Notes
Cloudflare API token Recommended; optional proxied (orange cloud) mode
Porkbun API key + secret key API Access must be toggled on per domain
Namecheap API user, API key, whitelisted IP Whole-zone writes; account gate
GoDaddy API key + secret 10-domain account gate
DigitalOcean Personal access token Zone must exist in DO
Hetzner DNS Console token Separate from Hetzner Cloud
Amazon Route 53 IAM access key + secret Public zones only
Gandi Personal Access Token LiveDNS v5, added in v2.45.0

Cloudflare

Fast, well documented and free. Create a token at dash.cloudflare.com → API Tokens with Zone:Read and DNS:Edit for the zones to manage, paste it into Settings → DNS → Cloudflare. Enable Proxied to route traffic through Cloudflare's CDN (orange cloud); disable for DNS-only. When creating a host pick Cloudflare and the zone; CaddyUI creates the record, stores its ID and cleans up on delete.

Porkbun

Create an API key pair at porkbun.com/account/api: a public key (pk1_…) and a secret key (sk1_…). Paste both into Settings → DNS → Porkbun.

The step everyone misses: for each domain, open Porkbun → Domain Management → Details → toggle API Access on. The API rejects every request on a domain where it is off, even with valid keys.

Porkbun clamps TTLs below 600 seconds and has no proxying mode. The Certificates page can also Import SSL from Porkbun.

Namecheap

The most finicky API of the set. Enable API access at Profile → Tools → API Access, generate a key, and add your server's public IP to the Whitelisted IPs list; every request carries the IP and mismatches are rejected. Fill in API user (your username), API key and Whitelisted IP.

Namecheap has no per-record CRUD: every create or delete fetches the full host list, mutates it and posts the whole set back. CaddyUI serialises its own calls, but hand-editing records in the Namecheap panel while an IP re-target job runs can make one side overwrite the other. Namecheap also requires at least 20 active domains or a positive account balance before it unlocks API access; "No Permission" is that gate.

GoDaddy

Create a Production key at developer.godaddy.com/keys and paste key and secret into Settings → DNS → GoDaddy.

Tier gate: since April 2024 GoDaddy restricts API access to accounts with 10 or more domains or a Discount Domain Club membership. Smaller accounts get 403 ACCESS_DENIED, which CaddyUI surfaces verbatim in the form. GoDaddy exposes no stable record IDs, so CaddyUI tracks records by type|name; if you rename a record in the GoDaddy panel, remove the orphan manually after deleting the host.

DigitalOcean

Free for any account. Create a Personal Access Token with read and write scopes at cloud.digitalocean.com → API → Tokens. The domain must already exist under Networking → Domains; CaddyUI creates records inside existing zones only. Minimum TTL is 30 seconds. Records only resolve once the registrar's nameservers point at ns1/ns2/ns3.digitalocean.com.

Hetzner

Hetzner DNS Console is a free product separate from Hetzner Cloud. Create a token at dns.hetzner.com → API Tokens with full DNS permissions and paste it in; CaddyUI sends the Auth-API-Token header for you. The zone must exist in the console and the registrar must delegate to hydrogen.ns.hetzner.com, helium.ns.hetzner.de and oxygen.ns.hetzner.com. Hetzner returns opaque zone IDs; CaddyUI stores the name alongside so lists and logs stay readable.

Amazon Route 53

Create a dedicated IAM user or role (never the account root) with a least-privilege policy, then an access key, and paste Access Key ID and Secret Access Key into Settings → DNS → Route 53. Leave Region blank for the standard partition (us-east-1 is used); a session token is only for temporary STS credentials.

{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": ["route53:ListHostedZones", "route53:ListHostedZonesByName"], "Resource": "*" },
    { "Effect": "Allow", "Action": ["route53:ListResourceRecordSets", "route53:ChangeResourceRecordSets"],
      "Resource": "arn:aws:route53:::hostedzone/Z0123456789EXAMPLE" },
    { "Effect": "Allow", "Action": "route53:GetChange", "Resource": "arn:aws:route53:::change/*" }
  ]
}

Add one hosted-zone ARN per zone CaddyUI may manage. Private hosted zones are hidden on purpose: public ACME validation cannot query them, and hiding them prevents picking the wrong zone in split-horizon setups. The selected zone ID is passed to Caddy so _acme-challenge TXT records land in the right zone. Route 53 has no record IDs, so CaddyUI stores the complete definition of every record it creates and uses exactly that during cleanup; existing records are reported as collisions and never overwritten, and Traffic Flow-managed records are never deleted.

Gandi

CaddyUI drives Gandi's LiveDNS v5 API (v2.45.0, from discussion #72). In admin.gandi.net open User settings → Personal Access Token (PAT), create a token for the organisation that owns the domains with permission to manage domain name technical configurations, and paste it into Settings → DNS → Gandi. It is sent as a Bearer token; the older Apikey scheme is not supported. Domains must use Gandi's LiveDNS nameservers (the default for Gandi-registered domains); domains delegated elsewhere do not appear in the picker.

LiveDNS stores records as sets keyed by name and type, so CaddyUI's record reference is name/type (app/A, @/A for the apex). Creating a record where a set of that name and type already exists is refused rather than merged; remove or change the existing set in the Gandi console, then save again. TTLs below 300 seconds are raised to the LiveDNS minimum. For DNS-01 the connected Caddy needs github.com/caddy-dns/gandi, built into Dockerfile.caddy from v2.45.0.

Adding a provider

Providers live in internal/dns/, one file each, registered through a descriptor (ID, display name, docs anchor, credential fields, factory) and implementing Ping, ListZones, CreateRecord, DeleteRecord and FindRecord. The Gandi implementation with its fake-API test is the smallest complete example. Open a discussion if you want a provider added; see Development and Releases.

Clone this wiki locally