DuckDNS Certificate error: URL domain=net and not my actual domain

1. The problem I’m having:

I’m trying to set up external access to services such as Frigate and Home Assistant. I could set up access to one service easily, but after I found that No-IP doesn’t support subdomains, I’m to switching to DuckDNS. Now can’t get Caddy to successfully negotiate with the domain. Starting the docker container generates the errors below and the domain cannot be reached in a browser.

For now, I’m only trying with Home Assistant, and I’ll deal with subdomains and the other services once I get past this.

Nothing in the logs seems to point me in a particular direction except that the URL presented in the error messages contains

domains=net

Simply copy-pasting the entire URL into my browser but replacing ‘net’ with the correct domain provides an ‘OK’ response, but I have no idea where Caddy is getting ‘net’ from or how to correct it.

Also I am completely new to networking in general, so while I’m decent with Linux and Docker, I fully admit that I have no idea what I’m doing here.

2. Error messages and/or full log output:

caddy-1  | 2026/09/28 17:43:05.635	INFO	maxprocs: Leaving GOMAXPROCS=4: CPU quota undefined
caddy-1  | 2026/09/28 17:43:05.635	INFO	GOMEMLIMIT is updated	{"GOMEMLIMIT": 14794795008, "previous": 9223372036854775807}
caddy-1  | 2026/09/28 17:43:05.635	INFO	using config from file	{"file": "/etc/caddy/Caddyfile"}
caddy-1  | 2026/09/28 17:43:05.635	INFO	adapted config to JSON	{"adapter": "caddyfile"}
caddy-1  | 2026/09/28 17:43:05.635	INFO	redirected default logger	{"from": "stderr", "to": "stdout"}
caddy-1  | 2026/09/28 17:43:05.636	INFO	admin	admin endpoint started	{"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]}
caddy-1  | 2026/09/28 17:43:05.636	INFO	http.auto_https	server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS	{"server_name": "srv0", "https_port": 443}
caddy-1  | 2026/09/28 17:43:05.636	INFO	http.auto_https	enabling automatic HTTP->HTTPS redirects	{"server_name": "srv0"}
caddy-1  | 2026/09/28 17:43:05.636	INFO	tls.cache.maintenance	started background certificate maintenance	{"cache": "0x9edcf5ac80"}
caddy-1  | 2026/09/28 17:43:05.636	DEBUG	http.auto_https	adjusted config	{"tls": {"automation":{"policies":[{"subjects":["{domain}.duckdns.net"]},{}]}}, "http": {"servers":{"remaining_auto_https_redirects":{"listen":[":80"],"routes":[{},{}]},"srv0":{"listen":[":443"],"routes":[{"handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"reverse_proxy","upstreams":[{"dial":"192.168.1.154:8123"}]}]}]}],"terminal":true}],"tls_connection_policies":[{}],"automatic_https":{}}}}}
caddy-1  | 2026/09/28 17:43:05.637	DEBUG	http	starting server loop	{"address": "[::]:443", "tls": true, "http3": false}
caddy-1  | 2026/09/28 17:43:05.637	INFO	http	enabling HTTP/3 listener	{"addr": ":443"}
caddy-1  | 2026/09/28 17:43:05.637	INFO	http.log	server running	{"name": "srv0", "protocols": ["h1", "h2", "h3"]}
caddy-1  | 2026/09/28 17:43:05.637	DEBUG	http	starting server loop	{"address": "[::]:80", "tls": false, "http3": false}
caddy-1  | 2026/09/28 17:43:05.637	WARN	http	HTTP/2 skipped because it requires TLS	{"network": "tcp", "addr": ":80"}
caddy-1  | 2026/09/28 17:43:05.637	WARN	http	HTTP/3 skipped because it requires TLS	{"network": "tcp", "addr": ":80"}
caddy-1  | 2026/09/28 17:43:05.637	INFO	http.log	server running	{"name": "remaining_auto_https_redirects", "protocols": ["h1", "h2", "h3"]}
caddy-1  | 2026/09/28 17:43:05.637	INFO	http	enabling automatic TLS certificate management	{"domains": ["{domain}.duckdns.net"]}
caddy-1  | 2026/09/28 17:43:05.637	DEBUG	events	event	{"name": "started", "id": "dbc7dd27-394c-4098-9974-c96fbf957ff8", "origin": "", "data": null}
caddy-1  | 2026/09/28 17:43:05.637	INFO	autosaved config (load with --resume flag)	{"file": "/config/caddy/autosave.json"}
caddy-1  | 2026/09/28 17:43:05.637	INFO	serving initial configuration
caddy-1  | 2026/09/28 17:43:05.640	INFO	tls.obtain	acquiring lock	{"identifier": "{domain}.duckdns.net"}
caddy-1  | 2026/09/28 17:43:05.643	INFO	tls	storage cleaning happened too recently; skipping for now	{"storage": "FileStorage:/data/caddy", "instance": "e4fa6d30-8367-48b1-87f6-995f3c79497e", "try_again": "2026/09/29 17:43:05.643", "try_again_in": 86399.999999703}
caddy-1  | 2026/09/28 17:43:05.643	INFO	tls	finished cleaning storage units
caddy-1  | 2026/09/28 17:43:05.643	INFO	tls.obtain	lock acquired	{"identifier": "{domain}.duckdns.net"}
caddy-1  | 2026/09/28 17:43:05.643	INFO	tls.obtain	obtaining certificate	{"identifier": "{domain}.duckdns.net"}
caddy-1  | 2026/09/28 17:43:05.643	DEBUG	events	event	{"name": "cert_obtaining", "id": "c5fa3bc4-3281-4954-b023-7124cc189720", "origin": "tls", "data": {"identifier":"{domain}.duckdns.net"}}
caddy-1  | 2026/09/28 17:43:05.643	DEBUG	tls	created CSR	{"identifiers": ["{domain}.duckdns.net"], "san_dns_names": ["{domain}.duckdns.net"], "san_emails": [], "common_name": "", "extra_extensions": 0}
caddy-1  | 2026/09/28 17:43:05.644	DEBUG	tls.obtain	trying issuer 1/1	{"issuer": "acme-v02.api.letsencrypt.org-directory"}
caddy-1  | 2026/09/28 17:43:05.646	DEBUG	http	using existing ACME account because key found in storage associated with email	{"email": "default", "ca": "https://acme-v02.api.letsencrypt.org/directory"}
caddy-1  | 2026/09/28 17:43:05.646	DEBUG	http	using existing ACME account because key found in storage associated with email	{"email": "", "ca": "https://acme-v02.api.letsencrypt.org/directory"}
caddy-1  | 2026/09/28 17:43:05.646	INFO	http	waiting on internal rate limiter	{"identifiers": ["{domain}.duckdns.net"], "ca": "https://acme-v02.api.letsencrypt.org/directory", "account": ""}
caddy-1  | 2026/09/28 17:43:05.646	INFO	http	done waiting on internal rate limiter	{"identifiers": ["{domain}.duckdns.net"], "ca": "https://acme-v02.api.letsencrypt.org/directory", "account": ""}
caddy-1  | 2026/09/28 17:43:05.646	INFO	http	using ACME account	{"account_id": "https://acme-v02.api.letsencrypt.org/acme/acct/3801910666", "account_contact": []}
caddy-1  | 2026/09/28 17:43:05.884	DEBUG	http.acme_client	http request	{"method": "GET", "url": "https://acme-v02.api.letsencrypt.org/directory", "headers": {"User-Agent":["Caddy/2.11.4 CertMagic acmez (linux; amd64)"]}, "response_headers": {"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["961"],"Content-Type":["application/json"],"Date":["Mon, 28 Sep 2026 17:43:05 GMT"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}, "status_code": 200}
caddy-1  | 2026/09/28 17:43:05.885	DEBUG	http.acme_client	creating order	{"account": "https://acme-v02.api.letsencrypt.org/acme/acct/3801910666", "identifiers": ["{domain}.duckdns.net"]}
caddy-1  | 2026/09/28 17:43:05.931	DEBUG	http.acme_client	http request	{"method": "HEAD", "url": "https://acme-v02.api.letsencrypt.org/acme/new-nonce", "headers": {"User-Agent":["Caddy/2.11.4 CertMagic acmez (linux; amd64)"]}, "response_headers": {"Cache-Control":["public, max-age=0, no-cache"],"Date":["Mon, 28 Sep 2026 17:43:05 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Replay-Nonce":["ZNNrQVmEkVypnuh2_5IqwMoUSlIWvbf9qinD34ADEflE4TRrj9w"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}, "status_code": 200}
caddy-1  | 2026/09/28 17:43:06.080	DEBUG	http.acme_client	http request	{"method": "POST", "url": "https://acme-v02.api.letsencrypt.org/acme/new-order", "headers": {"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.11.4 CertMagic acmez (linux; amd64)"]}, "response_headers": {"Boulder-Requester":["3801910666"],"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["358"],"Content-Type":["application/json"],"Date":["Mon, 28 Sep 2026 17:43:06 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Location":["https://acme-v02.api.letsencrypt.org/acme/order/3801910666/562911743466"],"Replay-Nonce":["ZNNrQVmEvsf7sekwXkXysBMQw_W-tXMQsc2JqwVFoLcsXyxWoGg"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}, "status_code": 201}
caddy-1  | 2026/09/28 17:43:06.133	DEBUG	http.acme_client	http request	{"method": "POST", "url": "https://acme-v02.api.letsencrypt.org/acme/authz/3801910666/789152183216", "headers": {"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.11.4 CertMagic acmez (linux; amd64)"]}, "response_headers": {"Boulder-Requester":["3801910666"],"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["832"],"Content-Type":["application/json"],"Date":["Mon, 28 Sep 2026 17:43:06 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Replay-Nonce":["ZNNrQVmEqzFttuUPmXdM-WISQGolUOpFGG-ZTIx3bXbBVaDJWSM"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}, "status_code": 200}
caddy-1  | 2026/09/28 17:43:06.133	INFO	http.acme_client	trying to solve challenge	{"identifier": "{domain}.duckdns.net", "challenge_type": "dns-01", "ca": "https://acme-v02.api.letsencrypt.org/directory"}
caddy-1  | 2026/09/28 17:43:06.135	DEBUG	tls.issuance.acme.dns_manager.dns_manager.soa_lookup	fetched SOA	{"msg": ";; opcode: QUERY, status: NOERROR, id: 39723\n;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1\n\n;; OPT PSEUDOSECTION:\n; EDNS: version 0; flags:; udp: 65494\n\n;; QUESTION SECTION:\n;_acme-challenge.{domain}.duckdns.net.\tIN\t SOA\n\n;; ANSWER SECTION:\n_acme-challenge.{domain}.duckdns.net.\t81998\tIN\tSOA\tns1.sedoparking.com. hostmaster.sedo.de. 2018051601 86400 10800 604800 86400\n"}
caddy-1  | 2026/09/28 17:43:06.136	DEBUG	tls.issuance.acme.dns_manager.dns_manager	creating DNS record	{"dns_name": "_acme-challenge.{domain}.duckdns.net", "zone": "_acme-challenge.{domain}.duckdns.net.", "record_name": "@", "record_type": "TXT", "record_data": "JuteU7OmfrdWiAtf--61-W9-BrN-EXHWXrn6sBVgZtE", "record_ttl": 0}
caddy-1  | 2026/09/28 17:43:06.308	ERROR	http.acme_client	cleaning up solver	{"identifier": "{domain}.duckdns.net", "challenge_type": "dns-01", "error": "no memory of presenting a DNS record for \"_acme-challenge.{domain}.duckdns.net\" (usually OK if presenting also failed)"}
caddy-1  | 2026/09/28 17:43:06.388	DEBUG	http.acme_client	http request	{"method": "POST", "url": "https://acme-v02.api.letsencrypt.org/acme/authz/3801910666/789152183216", "headers": {"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.11.4 CertMagic acmez (linux; amd64)"]}, "response_headers": {"Boulder-Requester":["3801910666"],"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["836"],"Content-Type":["application/json"],"Date":["Mon, 28 Sep 2026 17:43:06 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Replay-Nonce":["b_8FQRl9KLOhnrINUmEfZ8B_wn-bgiAGc-6rki8LvVKAmSxaBX4"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}, "status_code": 200}
caddy-1  | 2026/09/28 17:43:06.389	ERROR	tls.obtain	could not get certificate from issuer	{"identifier": "{domain}.duckdns.net", "issuer": "acme-v02.api.letsencrypt.org-directory", "error": "[{domain}.duckdns.net] solving challenges: presenting for challenge: adding temporary record for zone \"_acme-challenge.{domain}.duckdns.net.\": DuckDNS request failed, expected (OK) but got (KO), url: [https://www.duckdns.org/update?domains=net&token={token}&txt=JuteU7OmfrdWiAtf--61-W9-BrN-EXHWXrn6sBVgZtE&verbose=true], body: KO (order=https://acme-v02.api.letsencrypt.org/acme/order/3801910666/562911743466) (ca=https://acme-v02.api.letsencrypt.org/directory)"}
caddy-1  | 2026/09/28 17:43:06.389	DEBUG	events	event	{"name": "cert_failed", "id": "95517aca-a7fd-437e-bbcd-88cf476ec8ca", "origin": "tls", "data": {"error":{},"identifier":"{domain}.duckdns.net","issuers":["acme-v02.api.letsencrypt.org-directory"],"renewal":false}}
caddy-1  | 2026/09/28 17:43:06.389	ERROR	tls.obtain	will retry	{"error": "[{domain}.duckdns.net] Obtain: [{domain}.duckdns.net] solving challenges: presenting for challenge: adding temporary record for zone \"_acme-challenge.{domain}.duckdns.net.\": DuckDNS request failed, expected (OK) but got (KO), url: [https://www.duckdns.org/update?domains=net&token={token}&txt=JuteU7OmfrdWiAtf--61-W9-BrN-EXHWXrn6sBVgZtE&verbose=true], body: KO (order=https://acme-v02.api.letsencrypt.org/acme/order/3801910666/562911743466) (ca=https://acme-v02.api.letsencrypt.org/directory)", "attempt": 1, "retrying_in": 60, "elapsed": 0.745959225, "max_duration": 2592000}

3. Caddy version:

v2.11.4 h1:XKxkMTgNSizEvKG6QHue6cAsFOteU2qA61w2tKkCWi0=

4. How I installed and ran Caddy:

Docker compose. docker-compose.yaml posted below.

a. System environment:

Zorin OS 18.1 Kernel 7.0.0-31-generic.

b. Command:

sudo docker compose up caddy

c. docker-compose.yaml file:

services:
  homeassistant:
    container_name: homeassistant
    image: "ghcr.io/home-assistant/home-assistant:stable"
    volumes:
      - /home/randy/homeassistant/config:/config
      - /etc/localtime:/etc/localtime:ro
      - /run/dbus:/run/dbus:ro
    restart: unless-stopped
    #privileged: true
    network_mode: host
    environment:
      TZ: America/Indianapolis
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
  frigate:
    container_name: frigate
    runtime: nvidia
    restart: unless-stopped
    stop_grace_period: 30s
    image: ghcr.io/blakeblackshear/frigate:stable-tensorrt
    shm_size: "256mb"
    volumes:
      - /home/randy/frigate/config:/config
      - /mnt/surveil/media:/media/frigate
      - type: tmpfs # 1GB In-memory filesystem for recording segment storage
        target: /tmp/cache
        tmpfs:
          size: 1000000000
    ports:
      - "8971:8971"
      - "8554:8554" # RTSP feeds
      - "1984:1984" # go2rtc web interface
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - NVIDIA_DRIVER_CAPABILITIES=compute,utility,video
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
  matterjs-server:
    container_name: matterjs-server
    image: ghcr.io/matter-js/matterjs-server:stable
    read_only: true
    network_mode: host
    restart: unless-stopped
    # Optional Node.js heap hint. No default — size depends on the number of
    # commissioned nodes. See docs/docker.md "Node.js Memory Limit".
    # environment:
    #   NODE_OPTIONS: "--max-old-space-size=512"
    volumes:
      - /home/randy/matterjs-server:/data            
  music-assistant-server:
    image: ghcr.io/music-assistant/server:stable
    container_name: music-assistant-server
    restart: unless-stopped
    # Network mode must be set to host for MA to discover and stream to players (see networking note below)
    network_mode: host
    volumes:
      - /home/music-assistant-server/data:/data/
      # Optional: expose local music to MA by bind-mounting it read-only
      - /mnt/media/Music:/media:ro
    environment:
      # Provide logging level as environment variable.
      # default=info, possible=(critical, error, warning, info, debug)
      - LOG_LEVEL=info    
  mosquitto:
    image: eclipse-mosquitto
    container_name: mosquitto
    volumes:
      - /home/randy/mosquitto:/mosquitto
      - /home/randy/mosquitto/data:/mosquitto/data
      - /home/randy/mosquitto/log:/mosquitto/log
    ports:
      - 1883:1883
      - 9001:9001        
  caddy:
    image: serfriz/caddy-duckdns:latest
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - /home/randy/caddy/conf:/etc/caddy
      - /home/randy/caddy/data:/data
      - /home/randy/caddy/config:/config
      
  duckdns:
    image: lscr.io/linuxserver/duckdns:latest
    container_name: duckdns
    network_mode: host #optional
    environment:
      #- PUID=1000 #optional
      #- PGID=1000 #optional
      #- TZ=Etc/UTC #optional
      - SUBDOMAINS={domain}
      - TOKEN={token}
      - UPDATE_IP= #optional
      - LOG_FILE=false #optional
    volumes:
      - /home/randy/duckdns/config:/config #optional
    restart: unless-stopped

d. My complete Caddy config:

{
	debug
	log {
		output stdout
		format console
	}
}
{domain}.duckdns.net {
	reverse_proxy 192.168.1.154:8123
	tls {
		dns duckdns {token}
	}
}

5. Links to relevant resources:

Type here