A Caddyfile contains only the site block `example.com { reverse_proxy localhost:8080 }`. Describe what Caddy does about HTTPS when it loads that config, and what has to be true of the host for it to work.
answer
- the config never mentions certificates
- the site address decides everything
- challenge needs port 80 or 443 reachable
- certificates persist in the data directory
- localhost and IPs use the internal CA
basics
~20 sCaddy reads the site address as a public domain, so it obtains a certificate for example.com from a public ACME certificate authority, serves the site over HTTPS, redirects plain HTTP to HTTPS, and renews the certificate on its own. No TLS configuration is written anywhere.
solid answer
~50 sThat config never mentions TLS, and that is the point. Because the site address is a public hostname, Caddy's automatic HTTPS kicks in at config load: it asks a public ACME certificate authority (Let's Encrypt by default) for a certificate covering `example.com`, solves the challenge itself, stores the certificate and key in its data directory, serves the site on 443, and puts a permanent redirect on port 80 for the same name. It then renews in the background while the certificate still has roughly a third of its lifetime left. For that to succeed the host needs public DNS for `example.com` resolving to it and inbound reachability on port 80 (HTTP-01) or 443 (TLS-ALPN-01), and the data directory has to survive restarts. Non-public addresses such as `localhost` or a bare IP get a certificate from Caddy's own internal CA instead.
code
bash · 2 lines# Where automatic HTTPS keeps what it obtained (Linux, running as your user)
ls -R ~/.local/share/caddy/certificatesgo deeper
Be ready to say that the domain in the site address is what triggers HTTPS, that Caddy fetches and renews the certificate itself, and that DNS must already point at the machine.
Explain the mechanics: which challenge is solved on which port, that the certificate lands in Caddy's data directory, and that renewal happens in the background well before expiry.
Show that you treat the data directory as state. Talk about what re-issuance on every restart costs you against a CA's rate limits, and how you would confirm from logs whether a failure is DNS, reachability or the CA.
Frame it as a trade: implicit behaviour removes an entire class of expired-certificate incidents but moves the failure mode from a config line to reachability and storage, which your monitoring and runbooks now have to cover.
## What "automatic HTTPS" actually means Caddy's headline feature is that HTTPS is not a feature you turn on — it is what happens by default when you give a site block an address that looks like a public domain name. The two-line config ``` example.com { reverse_proxy localhost:8080 } ``` is a complete, production-shaped HTTPS reverse proxy. Nothing in it names a certificate, a key, a protocol version or a cipher list. ## The decision Caddy makes from the site address The site address is the input to the whole behaviour. Caddy classifies it: - A **public-looking hostname** (`example.com`, `shop.example.com`) means Caddy should manage a publicly trusted certificate for it via ACME. - **`localhost`, a bare IP address, or a `.localhost` name** cannot be validated by a public CA, so Caddy issues a certificate from its own **internal CA** — a local root it generates and stores itself. The `caddy trust` command installs that root into the machine's trust store so browsers stop complaining. The global option `local_certs` forces this behaviour for every site. - A site block that only has an `http://` scheme, or a config with `auto_https off` in the global options, opts out entirely. `auto_https disable_redirects` keeps the certificates but drops the port-80 redirect — which is what you want when something in front of you already handles that. ## What happens at config load For each managed name Caddy runs an ACME order in the background as the servers come up. It solves the challenge with its own listeners rather than by writing files somewhere for another daemon to serve: - **HTTP-01** answers on port 80 at a well-known path. - **TLS-ALPN-01** answers on port 443 inside the TLS handshake itself. - **DNS-01** is available but needs a DNS-provider module compiled into the binary, so it is not something the stock download can do. Because Caddy owns both listeners, it will fall back from one challenge to the other, and it retries with backoff rather than exiting. That is why a Caddy that cannot get a certificate keeps running and keeps failing handshakes for that name instead of refusing to start. Once issued, the certificate and key are written to Caddy's **data directory** — file-system storage under `$XDG_DATA_HOME/caddy` (typically `~/.local/share/caddy` on Linux, or the service user's equivalent), with certificates filed under a `certificates/` subtree per issuer. This directory is the single most operationally important thing in the whole feature: it is the difference between renewing an existing certificate and asking the CA for a brand-new one every time the process starts. ## Renewal and the redirect Caddy keeps a maintenance loop running for the lifetime of the process. It renews well before expiry — roughly when the last third of the certificate's lifetime is reached — so a short-lived certificate is not a scheduling problem you have to own. It also maintains OCSP staples for the certificates it manages. Separately, automatic HTTPS adds an HTTP-to-HTTPS redirect for every managed name. This is why a config that mentions only `example.com` still binds port 80. ## The preconditions, stated plainly 1. **Public DNS** for the name must resolve to this host. A certificate cannot be validated for a name that does not point at you. 2. **Inbound reachability** on port 80, port 443, or both. A security group or firewall that blocks 80 does not block issuance outright — TLS-ALPN-01 over 443 still works — but blocking both does. 3. **Persistent storage.** If the data directory is ephemeral (the classic case is a container with no volume for it) every restart re-issues, and repeated re-issuance for the same names runs into the CA's rate limits. 4. **The name must be one a public CA will issue for.** Internal-only names, IPs and `localhost` get the internal CA instead — which is a feature for local development, not a failure. ## What this replaces On a conventionally configured web server, the same outcome is a certificate-management client, a renewal timer, a deploy hook that reloads the server, a block of TLS directives, and a redirect server block — five things that can each drift or break independently. Caddy collapses them into the fact that you typed a domain name. The cost is that the behaviour is implicit: when it goes wrong the failure is in logs and in reachability, not in a config line you can point at.
- The host has port 80 blocked by a firewall but 443 open. Can Caddy still get a certificate?Yes. Caddy can complete the TLS-ALPN-01 challenge inside the handshake on port 443, so issuance still works. What you lose is the automatic HTTP-to-HTTPS redirect, which needs port 80 to be bound and reachable. DNS-01 would also avoid both ports, but it needs a DNS-provider module compiled into the binary, so the stock download cannot do it.
- What changes if the site address is `localhost` instead of `example.com`?Caddy will not go to a public CA for a name no public CA can validate. It issues from its own internal CA instead and serves that certificate. Browsers will not trust it until the internal root is installed in the system trust store, which `caddy trust` does. The global option `local_certs` forces this behaviour for all sites, which is useful for offline development.
- How would you keep Caddy from binding port 80 at all?Set `auto_https disable_redirects` in the global options if you still want managed certificates but no redirect server, or write the site address with an explicit `http://` scheme if you want that site served in plaintext only. `auto_https off` disables certificate management and redirects together, which is what you use when something upstream already terminates TLS.
It is less like configuring TLS and more like registering a domain with a landlord who also fits the locks: you say which door is yours, and the keys are cut, installed and re-cut before they wear out.
saying these in an interview costs you the question
- Thinks you must run a separate ACME client alongside Caddy
- Says Caddy serves a self-signed certificate for public domains
- Assumes issuance is impossible when port 80 is blocked
- Ignores that the data directory must persist across restarts
- Believes automatic HTTPS also works for a bare IP address