TLS and trust boundaries
Terminate local HTTPS
Let Caddy issue a local development certificate and proxy protected client traffic to a loopback backend.
10 minute lesson
TLS termination means the client’s protected connection ends at the proxy. The proxy decrypts the traffic, then chooses how to reach the upstream — often over plain HTTP on a private network. The application never touches certificates, and the proxy becomes the one place where TLS is configured, renewed, and debugged.
This split is the main reason reverse proxies exist in so many stacks. Let’s build it locally.
Use Caddy’s internal issuer
Caddy ships with a built-in certificate authority for development. Use Caddy’s internal issuer for the lab:
app.lab.test {
tls internal
reverse_proxy 127.0.0.1:4001
}
No port in the site address means Caddy serves HTTPS on 443 and redirects HTTP on 80. tls internal tells it to issue the certificate from its own local CA instead of contacting a public authority — which would fail anyway, since app.lab.test isn’t a public name.
Map the hostname to loopback in /etc/hosts if you haven’t already, then start Caddy.
Inspect what was issued
curl -v https://app.lab.test/ 2>&1 | grep -E "subject|issuer|SSL certificate"
Depending on your system, this either succeeds or fails with an unknown-issuer error. Both outcomes are informative. The certificate’s subject is app.lab.test, and the issuer is a Caddy local authority — not Let’s Encrypt, not anything your OS trusts by default.
If curl rejects it, Caddy can install its root into your local trust store:
caddy trust
After that, curl https://app.lab.test/ returns the backend response over a verified connection. Trust the local root only on your own development client when needed — that’s the entire intended audience.
Confirm what the backend sees
The backend still receives plain HTTP on 4001. Check its logged headers: X-Forwarded-Proto now says https. That header is how the application learns the client-facing connection was encrypted, even though its own listener never was.
One warning to take seriously. A local CA is powerful: anything that trusts its root will accept any certificate it signs, for any name. Do not copy its root key or install its certificate on unrelated systems. Keep it on your machine, for your lab, and remove the trust when the course is done.
Lesson completed