unsubbed.co

Caddy

A fast, extensible web server with automatic HTTPS — zero-config TLS certificates for every site, built-in reverse proxy, and a simple Caddyfile config format.

Best for: Developers and self-hosters who want a web server that handles TLS certificates automatically, serves as a reverse proxy, and doesn't require extensive nginx configuration knowledge — particularly homelab users and anyone managing multiple domains.

TL;DR

  • What it is: An open-source (Apache-2.0) web server and reverse proxy written in Go. Its defining feature: automatic HTTPS for every site, with zero configuration. 70K+ GitHub stars, backed by sponsors and commercial support through Ardan Labs.
  • Who it’s for: Developers and self-hosters who want a web server that handles TLS certificates automatically, serves as a reverse proxy, and doesn’t require a deep understanding of nginx configuration syntax.
  • Cost comparison: Caddy replaces nginx + Certbot + cron jobs with a single binary. No SaaS competitor to compare against — the savings are in engineering time, not subscription fees.
  • Key strength: Automatic HTTPS. Point a domain at Caddy, and it obtains, installs, and renews TLS certificates from Let’s Encrypt or ZeroSSL without any configuration. It also manages internal PKI for localhost and private IPs.
  • Key weakness: Lower raw throughput than nginx under extreme load. In benchmarks, nginx’s fail-fast approach maintains response times better under stress, while Caddy slows down rather than rejecting connections.

What is Caddy

Caddy is a web server and reverse proxy that was built with one opinionated premise: HTTPS should be the default, and it should be automatic. Created by Matt Holt in 2015, it’s written in Go and ships as a single binary with no external dependencies — not even libc.

The pitch is simple: in a world where nginx requires you to set up Certbot, configure cron jobs for certificate renewal, write TLS directives, and debug certificate chain issues, Caddy does all of this automatically. You write a three-line Caddyfile, and Caddy handles the rest — obtaining certificates from Let’s Encrypt or ZeroSSL, renewing them before expiry, and even managing OCSP stapling.

But Caddy is more than an HTTPS proxy. It supports HTTP/1.1, HTTP/2, and HTTP/3 by default, serves static files, reverse proxies to backend services, handles load balancing, and can be extended with a modular plugin architecture. The configuration system offers both a human-readable Caddyfile syntax and a powerful JSON API for dynamic, programmatic configuration.

The project has 70,883 stars on GitHub and is licensed under Apache-2.0. The README’s tone is confident: “Production-ready after serving trillions of requests and managing millions of TLS certificates” and “Scales to hundreds of thousands of sites as proven in production.”


Why people choose it over nginx, Traefik, and Apache

Versus nginx

This is the comparison 90% of Caddy adopters face. A Caddy reverse proxy is 3 lines in a Caddyfile; the equivalent nginx config is 15–20 lines with explicit TLS directives, proxy headers, and WebSocket upgrade handling. Caddy handles WebSockets automatically; nginx requires explicit proxy_set_header Upgrade configuration.

Benchmark testing at concurrency levels from 10 to 10,000 clients shows both perform comparably under normal load. Under extreme stress, they differ architecturally: nginx adopts a fail-fast approach, refusing new connections to maintain response times for accepted ones. Caddy maintains zero error rates but sacrifices latency, slowing all responses rather than rejecting any. For most self-hosted applications, Caddy’s “slow down gracefully” approach is arguably better than dropping connections.

Resource consumption differs: nginx uses minimal memory across all configurations, while Caddy’s Go runtime and garbage collection adds measurable overhead. For a reverse proxy handling a few hundred requests per second (the vast majority of self-hosted use cases), this difference is negligible.

Versus Traefik

Traefik is the other modern reverse proxy popular in Docker/Kubernetes environments. Traefik’s strength is auto-discovery — it reads Docker labels and Kubernetes ingress resources to configure routes automatically. Caddy can do similar things with plugins but doesn’t have Traefik’s out-of-the-box container orchestration integration. Traefik is more complex to configure for non-container use cases.

Versus Apache

Apache has been around since 1995 and powers LAMP stacks worldwide. Its Multi-Processing Module (MPM) architecture can handle concurrency well with modern configurations, but Apache’s configuration sprawl (httpd.conf, .htaccess, virtual hosts) is legendary. Caddy’s Caddyfile replaces all of that with a cleaner, more opinionated syntax. Apache still dominates in legacy PHP hosting; Caddy is the modern choice for new deployments.

The automatic HTTPS argument

Caddy’s HTTPS isn’t just “auto-renewing Let’s Encrypt certificates.” It includes:

  • OCSP stapling by default
  • PCI, HIPAA, and NIST compliant TLS defaults
  • Automatic HTTPS for localhost and internal IPs using a local CA
  • Cluster coordination for certificate management across multiple instances
  • Encrypted ClientHello (ECH) support
  • On-Demand TLS for SaaS platforms with customer domains

No other web server handles all of this out of the box.


Features: what it actually does

Web server core:

  • HTTP/1.1, HTTP/2, and HTTP/3 support by default
  • Static file server with directory listings, precompressed file serving
  • Reverse proxy with load balancing (round-robin, first, least_conn, random, and more)
  • WebSocket proxying without explicit configuration
  • Request matchers for routing based on path, headers, method, query parameters
  • Response manipulation (headers, compression, encoding)

Automatic HTTPS:

  • Let’s Encrypt and ZeroSSL certificate issuance and renewal
  • On-Demand TLS — certificates obtained at TLS handshake time for unknown domains
  • Internal PKI with automatic local CA for localhost and private IPs
  • OCSP stapling by default
  • Multi-issuer fallback
  • Cluster-aware certificate coordination across instances
  • Encrypted ClientHello (ECH)

Configuration:

  • Caddyfile: human-readable config format
  • Native JSON config for full control
  • Dynamic configuration via REST API
  • Config adapters for alternative formats
  • Environment variable substitution in configs
  • Snippets and named routes for reusable config blocks

Extensibility:

  • Modular architecture — all functionality is a Caddy module
  • Plugin system via xcaddy build tool
  • DNS challenge providers for wildcard certificates
  • FrankenPHP integration for PHP applications

Deployment:

  • Single static binary with no dependencies
  • Runs on Linux, macOS, Windows, FreeBSD, and more
  • Docker images available
  • No init system required — can run as a systemd service

Deployment reality check

Caddy’s deployment is genuinely simple — it’s one of the easiest self-hosted tools to get running.

What you actually need:

  • A VPS with a public IP and ports 80/443 open
  • DNS records pointing your domains to the server
  • That’s it.

Basic reverse proxy setup (the entire config):

A Caddyfile for reverse proxying two services:

app.example.com {
    reverse_proxy localhost:3000
}

api.example.com {
    reverse_proxy localhost:8080
}

Caddy reads this, obtains TLS certificates for both domains, and starts serving HTTPS. No certbot, no cron jobs, no TLS directives.

What can go sideways:

  • DNS propagation delays. Caddy tries to obtain a certificate immediately. If DNS hasn’t propagated yet, the ACME challenge fails. It retries, but the first few minutes can show TLS errors for new domains.
  • Firewall blocking ports 80/443. Caddy needs port 80 for HTTP-01 challenges (or configure DNS-01 challenges instead). Cloud providers sometimes block port 80 by default.
  • Rate limits. Let’s Encrypt has rate limits: 50 certificates per registered domain per week, 300 new orders per account per 3 hours. For normal use this is fine, but rapid testing can hit limits.
  • Memory overhead vs. nginx. Caddy uses more RAM than nginx (Go runtime + GC). Typical usage: 50–100MB for Caddy vs. 5–20MB for nginx. On a 1GB VPS, this matters. On anything larger, it doesn’t.
  • Plugin installation requires rebuilding. Unlike nginx modules that can be loaded dynamically, Caddy plugins are compiled into the binary using xcaddy. This means you need Go installed to add plugins.
  • Less ecosystem documentation. nginx has 20 years of Stack Overflow answers, blog posts, and tutorials. Caddy’s documentation is good but the community knowledge base is smaller.

Realistic time to first HTTPS site: 5–15 minutes from a fresh VPS. This is genuinely faster than any alternative.


Who should use this (and who shouldn’t)

Use Caddy if:

  • You’re self-hosting web applications and want HTTPS without thinking about it.
  • You’re setting up a reverse proxy for Docker containers or small services.
  • You value configuration simplicity over raw performance at extreme scale.
  • You’re building a SaaS that needs On-Demand TLS for custom domains.
  • You’re running a homelab and want automatic HTTPS for internal and external services.

Skip it (use nginx) if:

  • You need maximum throughput at 50,000+ requests/second.
  • You’re running on a 512MB VPS where every megabyte of RAM matters.
  • Your team already has deep nginx expertise and established configuration patterns.
  • You need the vast nginx module ecosystem (e.g., OpenResty/Lua scripting, njs).

Skip it (use Traefik) if:

  • You’re running a Kubernetes cluster and want automatic service discovery from ingress resources.
  • You need built-in Docker label-based routing for a container-heavy architecture.

Skip it (use a CDN) if:

  • You need global edge caching, DDoS protection, and WAF. Caddy is a web server, not a CDN. Use Cloudflare in front of Caddy for that.

Alternatives worth considering

  • nginx — the incumbent. Fastest reverse proxy at extreme scale, smallest memory footprint, largest ecosystem. Manual TLS configuration. Powers ~40% of top 10,000 websites.
  • Traefik — modern reverse proxy built for containers. Auto-discovery from Docker/Kubernetes. More complex than Caddy for non-container use cases.
  • Apache HTTP Server — the original. Still relevant for PHP/LAMP stacks. Configuration is verbose but well-documented after 30 years.
  • HAProxy — purpose-built load balancer. Better for pure load balancing than Caddy, but doesn’t serve static files or handle TLS certificates.
  • Envoy — service mesh proxy. Overkill for simple reverse proxying, excellent for microservice architectures.

For a self-hoster deploying 1–20 web applications behind a reverse proxy: Caddy is the most productive choice. You’ll spend minutes on setup instead of hours, and your certificates will never expire unexpectedly.


Bottom line

Caddy solved the problem everyone complained about but accepted as inevitable: manually managing TLS certificates. In 2025, there is no good reason for a self-hosted web application to have an expired certificate, a misconfigured TLS chain, or an HTTP-only endpoint — and Caddy makes all three things essentially impossible by default.

The performance gap vs. nginx exists but is irrelevant for 99% of self-hosted deployments. If you’re serving fewer than 10,000 requests per second (and almost everyone is), Caddy is as fast as you need while being dramatically simpler to configure and operate. The memory overhead (50–100MB vs. nginx’s 5–20MB) is the cost of not writing C and not debugging Certbot failures.

Caddy is the rare tool that makes the correct choice also the easiest choice. HTTPS by default, zero configuration, single binary. That’s the pitch, and it delivers.

If you’d rather not manage web servers at all, upready.dev deploys self-hosted infrastructure including Caddy reverse proxying for clients who want the benefits without the terminal time.

Sources

This review synthesizes 5 independent third-party articles along with primary sources from the project itself. Inline references throughout the review map to the numbered list below.

  1. [1] koder.ai — “Nginx vs Caddy: which web server should you use in 2025?” — comparison (link)
  2. [2] blog.tjll.net — “35 Million Hot Dogs: Benchmarking Caddy vs. Nginx” — comparison (link)
  3. [3] blog.logrocket.com — “Comparing the best web servers: Caddy, Apache, and Nginx” — comparison (link)
  4. [4] digitalocean.com — “How To Host a Website with Caddy on Ubuntu 22.04” — deployment-guide (link)
  5. [5] caddyserver.com — “Caddyfile Concepts - Caddy Documentation” — deployment-guide (link)
  6. [6] GitHub repository — official source code, README, releases, and issue tracker (https://github.com/caddyserver/caddy)
  7. [7] Official website — Caddy project homepage and docs (https://caddyserver.com)

References [1]–[7] above were used to cross-check claims about features, pricing, deployment, and limitations in this review.

Features

Integrations & APIs

  • Plugin / Extension System