Caddy redirects HTTP to HTTPS automatically because it’s designed to make secure connections the default, no questions asked.
Let’s watch Caddy in action. Imagine you have a simple Caddyfile:
example.com {
reverse_proxy localhost:8080
}
When Caddy starts and receives a request for http://example.com, it doesn’t just serve content from localhost:8080. Instead, it immediately sends back a 301 Moved Permanently redirect to https://example.com. If you then try to access https://example.com, Caddy will attempt to obtain an SSL certificate for example.com (usually via Let’s Encrypt) and then proxy that request to localhost:8080.
This behavior stems from Caddy’s core philosophy. It’s built around the idea that HTTPS should be the standard, and the operational burden of managing certificates and redirects should be minimal for the user. Caddy manages the entire lifecycle: it listens on ports 80 and 443, intercepts HTTP requests to initiate the redirect, and handles the ACME (Automated Certificate Management Environment) protocol to obtain and renew TLS certificates for your domains.
The "magic" happens in Caddy’s automatic HTTPS feature. When Caddy starts up and sees a domain name in its configuration (like example.com), it automatically tries to secure it.
- ACME Challenge: For a new domain, Caddy will listen for requests on port 80. When an ACME client (like Let’s Encrypt) tries to verify domain ownership using the HTTP-01 challenge, Caddy responds with the correct token.
- Certificate Acquisition: Upon successful verification, Caddy obtains a TLS certificate for that domain.
- HTTPS Listener: Caddy then starts listening on port 443 for that domain, serving traffic over HTTPS using the acquired certificate.
- HTTP Redirect: Crucially, Caddy also continues to listen on port 80. Any incoming HTTP requests to the configured domain are automatically served with a
301 Moved Permanentlyresponse, directing the client to use the HTTPS version.
The key configuration directive that enables this is implicitly present when you specify a domain name. You don’t need a tls block or explicit redirect directives for this basic HTTP-to-HTTPS behavior. Caddy handles it out of the box.
# This is all you need for automatic HTTP->HTTPS redirection and certificate management
yourdomain.com {
reverse_proxy localhost:8000
}
When Caddy starts with this configuration, it will:
- Listen on port 80 for
yourdomain.com. - If an HTTP request comes in, it will redirect to
https://yourdomain.com. - It will attempt to get a certificate for
yourdomain.comfrom Let’s Encrypt (or another ACME CA). - It will then listen on port 443 for
yourdomain.com, serving traffic tolocalhost:8000over TLS.
The internal mechanism involves Caddy’s pluggable transport system and its TLS management module. When a request arrives on port 80 for a domain Caddy knows about, it checks its internal state. If it has a valid certificate for that domain, it immediately issues the redirect. If it doesn’t have a certificate, it might still initiate the ACME challenge flow via port 80 to obtain the certificate before serving the redirect. This ensures a smooth transition and immediate security for users.
The surprising part is that Caddy doesn’t just serve a placeholder page or error out if it can’t immediately get a certificate. It actively participates in the certificate acquisition process using the very HTTP requests it’s supposed to be redirecting. This makes it incredibly resilient to initial deployment scenarios where no certificate exists yet.
The next thing you’ll likely want to configure is how Caddy handles specific paths or subdomains differently, or perhaps how to manage multiple domains with varying TLS requirements.