Why automatic HTTPS is a security decision, not a convenience feature
Three years ago, a fintech startup's staging server was exposed to the internet with a self-signed certificate. The dev team kept meaning to set up Let's Encrypt properly. Then a penetration tester found it during a routine audit — an unencrypted admin endpoint, publicly reachable. Nobody had "forgotten" security; they had deprioritized the friction of certificate management. That friction is exactly what Caddy was built to eliminate.
Setting
Caddy is an open-source web server written in Go, maintained by a small core team and a large contributor community, with the repository accumulating nearly 72,000 stars as of mid-2025. It was created by Matt Holt in 2015 with one design principle that sounds modest but has real security implications: TLS should be on by default, not opt-in. Most web servers — Nginx, Apache, HAProxy — treat HTTPS as a configuration task you perform after installation. Caddy inverts that. You configure HTTP explicitly if you want it; HTTPS is the default state.
The project sits at the intersection of the ACME protocol (Automatic Certificate Management Environment — the standard that Let's Encrypt uses to issue and renew certificates without human intervention) and modern HTTP standards (HTTP/1.1, HTTP/2, and HTTP/3 over QUIC). That combination matters for security teams because it removes an entire class of operational failure: expired certificates.
The Story
Here is what Caddy actually does in a concrete deployment. Say you are running a small SaaS product on a single VPS and you want to serve your API over HTTPS. With Nginx, the standard path involves installing certbot, running a challenge verification dance, editing your server block, setting up a cron job for renewals, and hoping the renewal does not fail silently. With Caddy, your entire configuration file — called a Caddyfile — looks like this:
api.yourdomain.com {
reverse_proxy localhost:3000
}
You start Caddy, it detects the domain, contacts Let's Encrypt (or ZeroSSL as a fallback), completes the ACME HTTP-01 or TLS-ALPN-01 challenge automatically, stores the certificate, serves HTTPS, and schedules renewal at roughly two-thirds of the certificate's lifetime — well before expiration. The process takes under thirty seconds on first run. If the renewal fails, Caddy retries with exponential backoff and logs the failure clearly, rather than silently serving an expired certificate.
Under the hood, the certificate storage is abstracted through a pluggable interface called CertMagic (Caddy's certificate management library). By default, certificates are stored on disk. In a distributed or containerized environment, you can swap the storage backend to Redis, Consul, or S3-compatible object storage — which means your certificate state is centralized, auditable, and not tied to a single instance's filesystem. For security engineers who care about secrets hygiene (treating certificates as secrets that should be versioned and access-controlled), this matters.
Caddy also enforces sane TLS defaults out of the box: TLS 1.2 minimum, strong cipher suites, OCSP stapling (a technique that lets the server prove its certificate has not been revoked, without the client having to contact the certificate authority directly), and automatic HTTP-to-HTTPS redirects. None of these require extra configuration. You can harden further — pin specific cipher suites, enforce TLS 1.3-only, configure mutual TLS (mTLS) for service-to-service authentication — but the baseline is already defensible without any of that.
For teams running internal services, Caddy supports acting as its own ACME certificate authority via its pki app. This lets you issue internal TLS certificates for services on private networks — api.internal, metrics.internal — without routing traffic through a public CA. The internal CA's root certificate can be distributed to clients once, and from that point forward, all internal services get valid TLS automatically.
The Insight
The real security argument for Caddy is not that it does something other servers cannot. Nginx with certbot and a well-maintained Ansible playbook can achieve the same endpoint state. The argument is about the attack surface created by operational complexity. Every manual step in certificate management is a place where human error, deferred maintenance, or miscommunication can introduce a vulnerability — expired certs, misconfigured redirects, forgotten HTTP endpoints. Caddy compresses that surface by making the secure path the path of least resistance. Security through good defaults is not glamorous, but it is what actually holds in production under time pressure.
This makes Caddy particularly relevant for small engineering teams (where there is no dedicated infra engineer watching certificate expiry), for startups deploying fast, and for any organization that wants compliance with standards like PCI-DSS or SOC 2 — both of which require encrypted data in transit — without building a certificate management runbook from scratch.
If you run more than a handful of public-facing services and certificate management is still a manual calendar reminder, Caddy is worth a weekend evaluation. It is not a security silver bullet, but it is a solid, well-maintained tool that removes one persistent, unglamorous source of TLS failures.
More security tooling worth your time is at teum.io/stories.
한국어 요약
Caddy는 Go로 작성된 오픈소스 웹 서버로, TLS 인증서 발급과 갱신을 자동으로 처리합니다. Nginx처럼 certbot과 cron을 별도로 설정할 필요 없이, 도메인만 지정하면 Let's Encrypt 연동이 즉시 완료됩니다. 기본값 자체가 TLS 1.2 이상, OCSP 스테이플링, HTTP→HTTPS 강제 리다이렉트로 설정되어 있어 보안 설정 실수를 줄이는 데 실질적으로 효과적입니다. 인증서 저장 백엔드를 Redis나 S3로 교체할 수 있어 분산 환경에서도 인증서 상태를 중앙 관리할 수 있습니다. 소규모 팀이나 스타트업처럼 인프라 전담 인력이 없는 환경에서 특히 적합한 선택지입니다.
Security through good defaults is not glamorous, but it is what actually holds in production under time pressure.