Is setting up ECH manually possible?

1. The problem I’m having:

Is there a way to set up ECH without giving caddy DNS access? Like by preparing the records in a file for the user to manually place into DNS?

I dont want a webserver to have full control over the DNS Server I use to handle my domains and stuff.

The docs seem to indicate that DNS integration is currently needed.

2. Error messages and/or full log output:

Does not apply

3. Caddy version:

2.11.1

4. How I installed and ran Caddy:

a. System environment:

Debian 13

b. Command

If it isn’t already running

Sudo systemctl start caddy

c. Service/unit file

I think this file was already supplied this way by the package.

# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

d. My complete Caddy config:

# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace ":80" below with your
# domain name.

#:80 {
# Set this path to your site's directory.
#       root * /usr/share/caddy

# Enable the static file server.
#       file_server

# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080

# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
#}

# Refer to the Caddy docs for more information:
# https://caddyserver.com/docs/caddyfile

https://ovpn.my1.dedyn.io {
        reverse_proxy https://192.168.5.202:9443 {
                transport http {
                        tls_trust_pool file /etc/caddy/my1-rootca-ec.pem
                        tls_server_name ovpn.my1.dedyn.io
                }
                header_up Host ovpn.my1.dedyn.io
        }
}

https://pwsafe.my1.dedyn.io {
        reverse_proxy https://192.168.5.203:8000 {
                transport http {
                        tls_trust_pool file /etc/caddy/my1-rootca-ec.pem
                        tls_server_name pwsafe.my1.dedyn.io
                }
                header_up Host pwsafe.my1.dedyn.io
        }
        rewrite /admin /404
}

(stupid question while we are at it, why are IPs, domains etc. so important to not redact them?)

Not easily. ECH needs maintenance, like certificates, so manually doing it is a recipe for failure.

Your DNS provider should offer scoped API tokens, like Cloudflare does for example. No need to give Caddy “full control” over the DNS server.

Because Caddy’s behavior differs based on the actual value of IPs and domains. Additionally, we often find that redactions are done inconsistently or incorrectly making troubleshooting a waste of time.

In your case, yours is more of a “General” question about Caddy and could go in the General category which doesn’t enforce the help template. Help is more for if Caddy isn’t working the way you expect, for example, and you need help getting your config to work the way you want it.

Also welcome back, 6 years later!

Oh okay i thought you just get a key which you push to dns and which runs for however long you want to. Similar how you can do it with dnssec or tlsa

Thanks for welcoming me again, never left caddy, just used it without problems so far. But nice to be here again :slight_smile:

ECH keys don’t strictly expire like certificates do, but rotating them is crucial for preserving forward secrecy (and limiting collateral damage if a key is exposed).

oh okay so the key isnt e.g. just used to (EC)DHE stuff where the key only acts as a signer to authenticate ephemeral keys, but rather used straight, I guess.

at desec I dont have that much control over what keys can do just iirc forbidding them from actually logging in or deleting domains, but no granular like say only modify an ACME challenge or a ECH or whatever.

fwiw, I’d think of ECH DNS records a lot like cert lifecycle data. if you hand-copy it, it can drift.

I get not wanting to hand caddy broad dns control, though. the middle ground I’d prefer is a very narrow token: one zone only, minimum read/edit dns permissions, and maybe a delegated subdomain/zone if that gives you cleaner scoping. then audit what records the automation touched from time to time.

if your dns provider can’t scope api tokens tightly enough, manual may be the only acceptable choice for your threat model. but where scoped tokens exist, narrow automation seems less scary to me than manually keeping ECH material in sync.