A reverse proxy sits in front of the services you run and gives them all one front door with a real certificate. Every self-hosting guide tells you to put one there. Fewer explain what happens when you do.
Caddy is the one to reach for if you have never done this, because it obtains and renews certificates without being asked. You give it a hostname and it does the rest.
What "automatic HTTPS" actually means
When Caddy sees a real hostname in its configuration — not a bare port, not an IP address — it treats that as an instruction to secure it. It registers an account with the certificate authority, proves it controls the name by answering a challenge on port 80, moves the site to 443, and renews before expiry without further involvement from you.
This is a good default, and it is the reason to choose Caddy for a first proxy. It is also the source of most confusion: the automation does several things, and any of them can fail for networking reasons that have nothing to do with Caddy itself.
The data volume is not disposable
Caddy stores its certificates, its private keys and its account details in a data directory. If that lives in a container with no volume behind it, every restart throws it away.
The consequence is not just inconvenience. On restart, Caddy finds no certificates and asks for new ones for everything it serves. Do that a few times in a week while debugging a compose file and you will hit the certificate authority's rate limits. At that point you cannot get a certificate for that name for days, no matter what you fix.
Give the data directory a named volume before you start, and treat it as something you back up rather than something you clear when a restart misbehaves.
Mount the directory, not the file
The obvious way to give Caddy its configuration is to bind-mount the Caddyfile straight to its path. It works, and then reloading the configuration does not.
The reason is that a bind mount of a single file points to the original file, not its path. The process inside the container never sees edits made on the host, so a reload command succeeds but changes nothing.
Mount the directory that contains the Caddyfile instead. Reloads then pick up edits, which matters because reloading is how you add a service without dropping the ones already running.
Port 80 is not optional, until it is
The default challenge requires a public response on port 80. The port must be open on the firewall, forwarded by the router, not taken by another process, and not blocked by an upstream address-sharing arrangement.
Carrier-grade NAT is where this stops being solvable by configuration. If your connection shares a public address with other customers, no port forward will help, and no amount of correct Caddy configuration will substitute.
The alternative is a DNS challenge, which proves control by writing a record rather than answering a request, and works from behind anything. It has one requirement that catches people: the stock Caddy image does not include the necessary modules. DNS providers are compiled in, the published image ships without them, and using a DNS challenge means building an image that includes the module for your provider. Building a custom image is a documented, standard step, but it is not what a copied-and-pasted compose file will give you.
What a working configuration is shaped like
Less than people expect. A block per hostname, each naming the service it should reach, addressed by its name on the Docker network rather than by a published port.
Once the proxy is in front, the services behind it should stop publishing ports to the host. They only need to be reachable from the proxy, on the internal network the compose file already gives them. Leaving the old published ports in place means the services are still reachable directly, bypassing the proxy and defeating the exercise.
Where this comes from, and what will date
Composed from the project's own documentation on automatic HTTPS, reloading and DNS challenges together with several independent published setups, cross-checked against each other on 31 August 2026. Certificate authority rate limits and challenge types are set by the authority rather than by Caddy and change on their own schedule.
A proxy is not a firewall. It gives you one encrypted entrance and a place to add authentication. It does not make what is behind it safe, and putting an application on the internet is a decision to make deliberately rather than a side effect of getting a certificate.