Caddy is essentially a configuration management system that can run various apps like an HTTP server, TLS certificate manager, PKI facilities, and more. It can be extended with plugins known as config modules.
</p>
<p>
Caddy sports a flexible and powerful HTTP reverse proxy, on-line configuration API, and a robust, production-ready static file server, and serves all sites over HTTPS by default with automagic TLS certificates.
</p>
<h3class="green">Overall program technical specifications</h3>
The language choice is crucial for a web server. Language impacts development speed and ease, performance, testing, deployment complexity, ecosystem reliability, dependencies, tooling, error handling and reliability, and much, much more. Go offers strong advantages in all these areas, allowing for rapid development, robust production performance, and high scalability.
Most servers (NGINX, Apache, HAProxy, etc.) and their dependencies are written in C, which are vulnerable to catastrophic memory safety bugs (such as buffer overflows) like Heartbleed. Go programs like Caddy are impervious to a whole class of security vulnerabilities.
Caddy compiles directly to native CPU instructions. There is no interpreter required; and many instructions are architecture-optimized. Static binaries are also <ahref="https://www.phoronix.com/news/Glibc-LD-Nasty-Root-Bug">more secure</a> because there is no dynamic linking.
Caddy is statically compiled. Dynamically-linked applications can easily break in production and <ahref="https://www.qualys.com/2023/10/03/cve-2023-4911/looney-tunables-local-privilege-escalation-glibc-ld-so.txt">may be less secure</a> as shared executable resources are loaded from various places around the system. Generally, Caddy binaries do not necessarily require external libraries — not even libc.
On consumer hardware, standard Caddy builds compile in just a few seconds. This is crucial for rapid iteration, plugin development, and low-cost deployments.
Caddy's regular expression language is <ahref="https://swtch.com/~rsc/regexp/regexp1.html">based on the Thompson NFA and has numerous performance improvements over PCRE</a> used by other web servers. It guarantees the runtime cost increases linearly instead of exponentially. This is ideal when evaluating untrusted input.
Go's runtime optimizes scheduled CPU time in smarter ways than the operating system can using lightweight user-space threads called goroutines. Caddy utilizes all CPU cores and easily handles hundreds of thousands of requests per second.
Caddy can be extended by compile-time plugins, which compile as native code, in a way that cannot be broken during deployments or by system upgrades. With no IPC or RPC calls, Caddy extensions perform equally well with native code.
Top-level configuration structures are called app modules, or Caddy apps. They provide the bulk of Caddy's functionality. Anyone can write app modules, and Caddy comes with several standard apps built-in.
Assets and state, including certificates and OCSP staples, are stored in configurable storage backends. In fact, multiple instances of Caddy configured with the same storage are considered part of a cluster and can coordinate automatically.
Caddy's CLI is not only useful—it's <i>helpful</i>. While most server CLIs merely run the process and reload config, Caddy's CLI goes the extra lightyear to help make administering your modern web server a breeze.
</p>
<p>
Plugins can register their own subcommands to extend Caddy's CLI.
</p>
<divclass="feature-list">
<divclass="feature-row">
<h4>Command help</h4>
<divclass="benefits">
If you misspell a command or flag, miss an argument, or don't know the subcommand, help text is automatically printed. You can also access overall command help or subcommand help with <code>caddy help</code> or <code>-h</code>.
</div>
<divclass="detail">
Built-in, automatic (<code>man</code> pages can also be generated)
Several subcommands use administration API endpoints for use with the CLI to help you perform common tasks like loading config from files or stopping the server.
</div>
<ulclass="detail">
<li>Adapt config to JSON</li>
<li>Start the server, optionally with config</li>
<li>Gracefully reload configuration</li>
<li>Stop the server</li>
</ul>
</div>
<divclass="feature-row">
<h4>Binary utilities</h4>
<divclass="benefits">
Since custom builds of Caddy are so common, several commands exist to help you manage and get detailed information about your build.
</div>
<ulclass="detail">
<li>Detailed build metadata</li>
<li>List installed config modules</li>
<li>List dependencies</li>
<li>Add and remove plugin packages</li>
<li>Print the version</li>
<li>Upgrade the Caddy binary</li>
</ul>
</div>
<divclass="feature-row">
<h4>Configuration utilities</h4>
<divclass="benefits">
If you choose to use configuration files, Caddy's CLI helps you manage them.
</div>
<ulclass="detail">
<li>Format Caddyfile</li>
<li>Validate configuration</li>
<li>List dependencies</li>
<li>Add and remove plugin packages</li>
<li>Print the version</li>
</ul>
</div>
<divclass="feature-row">
<h4>Module utilities</h4>
<divclass="benefits">
Modules may register their own subcommands to provide common functionality that can be utilized without a config document.
</div>
<ulclass="detail">
<li>Static file server</li>
<li>HTTP reverse proxy</li>
<li>Static HTTP responses (templateable)</li>
<li>Storage import/export (backup/restore)</li>
<li>Hash password for use with HTTP basic auth</li>
<li>Export file browse template</li>
</ul>
</div>
<divclass="feature-row">
<h4>Integration utilities</h4>
<divclass="benefits">
Several subcommands can help you integrate Caddy into your shell environment.
</div>
<ulclass="detail">
<li>Generate shell completion script</li>
<li>Print the environment</li>
<li>Generate <code>man</code> pages</li>
<li>Install Caddy-managed root CA into trust stores</li>
<li>Remove Caddy-managed root CA from trust stores</li>
</ul>
</div>
<divclass="feature-row">
<h4>System signals</h4>
<divclass="benefits">
Caddy has support for common operating system signals/interrupts, with subtle differences in behavior for each one.
Whether Caddy exits successfully or with an error, the <ahref="/docs/command-line#exit-codes">exit code</a> can give a hint to your process supervisor or script how to handle that.
We've designed Caddy so that its configuration not only provides access to features, but <i>it IS a feature</i> in and of itself.
</p>
<p>
No more quibbling over which config file format is the best: use whatever you want! Caddy's <ahref="/docs/config-adapters">config adapters</a> allow you to use whatever config format you prefer.
</p>
<divclass="feature-list">
<divclass="feature-row">
<h4>Native config format</h4>
<divclass="benefits">
Caddy's native configuration format is ubiquitous: it has tooling in nearly every operating system, platform, programming language, and API ecosystem. Almost all other formats can be translated down into JSON, which balances human readability and programmability. You'll find it a powerful ally of your web server.
</div>
<divclass="detail">
JSON
</div>
</div>
<divclass="feature-row">
<h4>Config adapters</h4>
<divclass="benefits">
You can always write your config in another format and with config adapters, Caddy will implicitly translate it into JSON for you so you can work with what you like.
</div>
<ulclass="detail">
<li>Caddyfile</li>
<liclass="nonstandard">JSON 5</li>
<liclass="nonstandard">JSON-C</li>
<liclass="nonstandard">NGINX Conf</li>
<liclass="nonstandard">YAML</li>
<liclass="nonstandard">CUE</li>
<liclass="nonstandard">TOML</li>
<liclass="nonstandard">HCL</li>
<liclass="nonstandard">Dhall</li>
<liclass="nonstandard">MySQL</li>
</ul>
</div>
<divclass="feature-row">
<h4>Human-friendly config</h4>
<divclass="benefits">
The Caddyfile is most users' favorite way to write their web server config by hand because its syntax is forgiving while also being designed with a structure that makes it easy to read and write. It is translated to JSON automatically.
</div>
<divclass="detail">
Caddyfile
</div>
</div>
<divclass="feature-row">
<h4>Export</h4>
<divclass="benefits">
Caddy's administration API allows you to have runtime access to the current configuration in JSON format with a simple GET request.
</div>
</div>
<divclass="feature-row">
<h4>Config API</h4>
<divclass="benefits">
Caddy receives its configuration through an API endpoint, which can accept JSON or any other format it has a config adapter for.
Our flagship feature, powered by <ahref="https://github.com/caddyserver/certmagic">CertMagic</a>. Caddy is the first and only major server that enables HTTPS by default, and automatically procures and renews certificates for all your sites.
Fully-native, integrated auto-HTTPS is far superior to any solution that requires external tooling or cron jobs. Caddy's certificate maintenance is the best in the industry because it is more robust, reliable, and scalable than any other solution. Caddy simplifies your infrastructure instead of complexifying it.
Sure, you can try deploying 100,000 sites with Certbot and a cron job—but if that doesn't fall over by itself, the web server will. Only Caddy is designed to massively scale TLS certificates both horizontally and vertically.
Never manually generate a CSR again. Never click a link in an email to download a certificate. Never (mis)configure your web server to use them. Never miss reminders to renew your certificates, one-by-one, every few months before they expire. You won't even have to think about certificates or TLS.
Serving domains that aren't yours? Or have lots of them? No problem! With just a few lines of config, On-Demand TLS gets certificates dynamically during TLS handshakes, scaling your deployments to tens of thousands of certs. This functionality is a Caddy exclusive.
</div>
</div>
<divclass="feature-row">
<h4>Certificate issuers</h4>
<divclass="benefits">
Get certificates from any issuing authority in a way compatible with them. Certificate issuers take a CSR and return a certificate resource. Most sites will simply use ACME to get certificates. But Caddy can also issue its own self-signed certificates for internal use, testing, or development. Caddy's issuer sources are pluggable, so Caddy can automate certificates from any issuer modules.
</div>
<ulclass="detail">
<li>ACME</li>
<li>Internal (self-signed)</li>
<liclass="nonstandard">Microsoft Active Directory Certificate Services</li>
</ul>
</div>
<divclass="feature-row">
<h4>Certificate managers</h4>
<divclass="benefits">
Unlike issuers, which take a CSR and return a certificate that Caddy has to manage, certificate managers are modules that can return always-valid certificates on-demand; that is, they are managing the certificates for us. Caddy can get interface with HTTP endpoints or Tailscale to get certificates in this manner, with other ways available through plugins.
</div>
<ulclass="detail">
<li>HTTP</li>
<li>Tailscale</li>
</ul>
</div>
<divclass="feature-row">
<h4>Cluster coordination</h4>
<divclass="benefits">
Across all Caddy instances configured with the same storage, Caddy automatically coordinates and shares resources across the cluster. This includes certificate operations and the certificates themselves, OCSP staples, and session ticket keys. This results in reduced latency for your clients and higher scalability.
</div>
<ulclass="detail">
<li>Obtaining & renewing certificates</li>
<li>Loading existing certificates</li>
<li>OCSP staples</li>
<li>Session ticket keys (STEKs)</li>
</ul>
</div>
<divclass="feature-row">
<h4>Redirect HTTP to HTTPS</h4>
<divclass="benefits">
By default, HTTP requests will be redirected to HTTPS.
</div>
</div>
<divclass="feature-row">
<h4>OCSP</h4>
<divclass="benefits">
OCSP indicates when certificates are revoked. Servers should staple OCSP responses to certificates to provide clients with better security and privacy. Caddy is the first and only server to do this automatically and by default. It also caches responses to weather OCSP responder outages, and shares them across its cluster. This can all be disabled if needed.
TLS connections are pointless if an attacker steals the key to encrypt session tickets. Caddy has been <ahref="https://jhalderm.com/pub/papers/forward-secrecy-imc16.pdf">academically cited</a> as the only server to rotate these keys regularly to limit attack windows.
</div>
<divclass="detail">
Automatic STEK rotation
</div>
</div>
<divclass="feature-row">
<h4>Key types</h4>
<divclass="benefits">
You can customize the type of key used for your certificates.
<p>Most ACME clients assume 90-day certificates, or don't expect certificates shorter than 7 days. Caddy can successfully manage certificates with lifetimes on the order of hours and minutes.</p>
<p>Instead of hard-coding a certain age before renewing, Caddy computes the age relative to the lifespan of each certificate, called a Renewal Window Ratio. By default, Caddy renews certificates after 2/3 of their usable lifetime. This ratio works for most validity periods, but can be adjusted.</p>
If Caddy can't get a certificate, errors are logged and Caddy will backoff exponentially and retry as long as needed until it succeeds (typically up to 30 days but could be longer). Caddy makes every reasonable effort to keep your certificate renewed.
Caddy conforms to best practices and doesn't blast CAs with requests for certificates; instead, each order is carefully timed to avoid overwhelming CA servers.
Caddy's ACME client is best-in-class, with higher reliability and more production experience than any other integrated ACME client available today. Caddy has been using ACME since before the public availability of Let's Encrypt, and Caddy works with any ACME-compatible CA.
</p>
<divclass="feature-list">
<divclass="feature-row">
<h4>Compatibility</h4>
<divclass="benefits">
Some ACME clients are only tested with Let's Encrypt. Caddy is guaranteed compatible with all ACME-capable CAs.
</div>
<divclass="detail">
All RFC 8555-compliant certificate authorities, such as:
<ul>
<li>Let's Encrypt</li>
<li>ZeroSSL</li>
<li>Google Trust Services</li>
<li>BuyPass</li>
<li>DigiCert</li>
<li>GlobalSign</li>
<li>SSL.com</li>
<li>Smallstep</li>
</ul>
</div>
</div>
<divclass="feature-row">
<h4>Test endpoints</h4>
<divclass="benefits">
By default, Caddy will fall back to a CA's test or staging endpoint (if there is one) after a failed attempt at getting a certificate to avoid hitting CA-enforced production rate limits. This could also be an ACME server you set up solely for the purpose of validating DNS configurations.
</div>
<divclass="detail">
Let's Encrypt (others configurable)
</div>
</div>
<divclass="feature-row">
<h4>External account binding</h4>
<divclass="benefits">
Optionally configure External Account Binding (EAB) to enable Caddy to work with CAs that require you to have a separate account with them.
</div>
</div>
<divclass="feature-row">
<h4>Challenge types</h4>
<divclass="benefits">
Caddy supports all major ACME challenge types for Web PKI and can also be extended to support others.
</div>
<ulclass="detail">
<li>HTTP-01</li>
<li>TLS-ALPN-01</li>
<li>DNS-01</li>
</ul>
</div>
<divclass="feature-row">
<h4>Alternate challenge ports</h4>
<divclass="benefits">
While certain ACME challenges must use the standardized ports 80 and 443, Caddy supports listening for these on alternate ports if you are forwarding them through a router.
</div>
<ulclass="detail">
<li>HTTP (default 80)</li>
<li>TLS-ALPN (default 443)</li>
</ul>
</div>
<divclass="feature-row">
<h4>DNS challenge integrations</h4>
<divclass="benefits">
Solve the DNS challenge with integrations for dozens of DNS providers. <b>This list is incomplete;</b><ahref="https://github.com/caddy-dns">see the full list of DNS providers</a>.
Caddy's flagship feature is enabling HTTPS automatically and by default. You can control how it works or disable aspects: HTTP redirects, certificate management, certain hostnames, etc.
Each HTTP server can listen on one or more sockets and network interfaces. For ports, you can specify specific host interface or all interfaces with just a port. All varieties of unix sockets are also supported.
</div>
<ulclass="detail">
<li>TCP</li>
<li>UDP</li>
<li>Unix sockets</li>
</ul>
</div>
<divclass="feature-row">
<h4>Listener wrappers</h4>
<divclass="benefits">
Listeners can be wrapped by modules that operate at the connection-accept level.
</div>
<ulclass="detail">
<li>Redirect HTTP on HTTPS port</li>
<li>PROXY protocol</li>
<liclass="nonstandard">Tailscale</li>
</ul>
</div>
<divclass="feature-row">
<h4>Timeouts</h4>
<divclass="benefits">
Setting timeouts is an important defensive measure for production environments, but must be tuned carefully to accommodate legitimate slow clients with large downloads or uploads.
</div>
<ulclass="detail">
<li>Read timeout</li>
<li>Read HTTP header timeout</li>
<li>Write timeout</li>
<li>Idle timeout</li>
<li>TCP keepalive interval</li>
</ul>
</div>
<divclass="feature-row">
<h4>Full duplex communication</h4>
<divclass="benefits">
Concurrent reading and writing of HTTP/1 is not supported by all clients, but can be enabled for certain clients and applications that require it.
Caddy gives you full control over handling errors to give you clients the best/desired experience.
</div>
<divclass="detail">
Custom error routes
</div>
</div>
<divclass="feature-row">
<h4>TLS termination</h4>
<divclass="benefits">
Terminate TLS (formerly "SSL") with sensible defaults that you can customize to give you fine-grained control over TLS handshakes. You can assign policies to clients based on various factors such as ServerName (SNI) or remote IP.
</div>
<ulclass="detail">
<li>TLS 1.2</li>
<li>TLS 1.3</li>
<li>Client authentication (TLS mutual auth)</li>
<li>Client auth modes: request, require, verify if given, require and verify</li>
<li>Cipher suites</li>
<li>Curves</li>
<li>ALPN</li>
<li>Limit protocol versions</li>
<li>Default SNI</li>
<li>Fallback SNI</li>
</ul>
</div>
<divclass="feature-row">
<h4>Cross-site security</h4>
<divclass="benefits">
Caddy often serves multiple sites on the same socket, so Caddy automatically enables protections to keep your sites safe if any of them have TLS client auth enabled.
</div>
<divclass="detail">
Verification that TLS ServerName and HTTP Host header match
Enable zero-allocation, structured access logs for the ultimate understanding of client requests and responses. Customize using Caddy's built-in logging configuration or the use of third-party modules.
Caddy has the most flexible general-purpose reverse proxy in the world, featuring advanced request and response handling, dynamic routing, health checking, load balancing, circuit breaking, and more.
</p>
<p>
What makes Caddy's proxy unique is its design. Only the client-facing side of the proxy needs to be HTTP; the transport underlying the roundtrip with the backend can be fulfilled with any protocol!
</p>
<p>
Moreover, our proxy can be programmed with highly dynamic upstreams. That is, the available upstreams can change during in-flight requests! If no backends are available, Caddy can hold onto the request until one is.
</p>
<h3class="blue">High-level proxy features</h3>
<divclass="feature-list">
<divclass="feature-row">
<h4>Transports</h4>
<divclass="benefits">
Transports are how Caddy gets the response from the backend. Caddy's proxy can be a front for protocols other than HTTP by using alternate transport modules. This allows Caddy to generate HTTP responses from backends that don't even speak HTTP!
</div>
<ulclass="detail">
<li>HTTP</li>
<li>FastCGI</li>
<liclass="nonstandard">NTLM</li>
</ul>
</div>
<divclass="feature-row">
<h4>Load balancing</h4>
<divclass="benefits">
Selecting upstreams is a crucial function of any modern reverse proxy. Caddy has a variety of built-in load balancing policies to choose from to suit any production services. Some policies are extremely fast and lightweight; others provide upstream affinity based on properties of the client or request; others strive for even distribution by counting connections or using randomness and weights.
</div>
<ulclass="detail">
<li>Random</li>
<li>Random Choose-N</li>
<li>Least connections</li>
<li>Round robin</li>
<li>Weighted round robin</li>
<li>First available</li>
<li>Remote IP hash</li>
<li>Client IP hash</li>
<li>URI hash</li>
<li>Query hash</li>
<li>Header hash</li>
<li>Cookie hash</li>
</ul>
</div>
<divclass="feature-row">
<h4>Circuit breaking</h4>
<divclass="benefits">
A circuit breaker module can temporarily mark a backend as down before it actually goes down, to keep it up.
</div>
<divclass="detail nonstandard">
Latency-based
</div>
</div>
<divclass="feature-row">
<h4>Health checking</h4>
<divclass="benefits">
Health checks detect when upstreams are unavailable. Passive health checks infer status from actual requests. Active health checks work in the background, out-of-band of client requests.
</div>
<ulclass="detail">
<li>Active</li>
<li>Passive</li>
</ul>
</div>
<divclass="feature-row">
<h4>Observability</h4>
<divclass="benefits">
The admin API exposes an endpoint to retrieve the traffic count and health status of the proxy upstreams.
</div>
</div>
<divclass="feature-row">
<h4>Upstream sources</h4>
<divclass="benefits">
Caddy can get the list of upstreams in various ways. The most common is to write them into the configuration (static). Other ways are dynamic, by which a list of upstreams are returned for each request (these utilize configurable caching to enhance performance).
Requests can be retried until a backend is available to successfully handle the request. During this time, the list of upstreams may even be updated while the request is still pending!
In order to use proxy-related headers like X-Forwarded-For, you can specify a list of IP ranges of proxies you trust. By default Caddy doesn't trust the clients.
The proxy can read the entire body before flushing it. This uses more memory but can be required by some backend applications or clients in some cases.
</div>
<ulclass="detail">
<li>Requests</li>
<li>Responses</li>
</ul>
</div>
<divclass="feature-row">
<h4>Request rewriting</h4>
<divclass="benefits">
Rewriting is a different concern from proxying and is normally handled separately, but sometimes you need to rewrite requests using information from the proxy like the chosen upstream. Caddy's proxy lets you do this.
</div>
</div>
<divclass="feature-row">
<h4>Response interception</h4>
<divclass="benefits">
By default, Caddy's proxy simply writes responses to the client. However, you can intercept the upstream's response and handle it in other ways. This includes matching only certain responses and invoking a custom handler chain you specify.
Active health checks assume a backend is down by default until that is confirmed otherwise by a health check.
</p>
<divclass="feature-list">
<divclass="feature-row">
<h4>HTTP request parameters</h4>
<divclass="benefits">
Active health checks are performed against an HTTP endpoint on the upstream. You can customize the parameters for these HTTP requests to work for you.
</div>
<ulclass="detail">
<li>Path & query string</li>
<li>Port</li>
<li>Headers</li>
</ul>
</div>
<divclass="feature-row">
<h4>Timing</h4>
<divclass="benefits">
You can customize the interval at which active health checks are performed.
</div>
</div>
<divclass="feature-row">
<h4>Success criteria</h4>
<divclass="benefits">
Each active health check can be customized with a set of criteria to determine healthy or unhealthy status.
</div>
<ulclass="detail">
<li>Response timeout</li>
<li>HTTP status code</li>
<li>Regular expression match on body</li>
</ul>
</div>
<divclass="feature-row">
<h4>Failure safety</h4>
<divclass="benefits">
Backends that are experiencing bugs and difficulties may sometimes respond with unexpectedly large response bodies. Caddy lets you limit this to preserve proxy resources.
</div>
<divclass="detail">
Limit response size
</div>
</div>
</div>
<h3class="purple">Passive health checks</h3>
<p>
Passive health checks assume a backend is up by default until failure criteria are met in the course of proxying requests.
</p>
<divclass="feature-list">
<divclass="feature-row">
<h4>Failure criteria</h4>
<divclass="benefits">
All passive health checks count connection failures. In addition, you can set more criteria needed to deem a backend as healthy during a request.
</div>
<ulclass="detail">
<li>Concurrent request limit exceeded</li>
<li>HTTP Status</li>
<li>Latency</li>
</ul>
</div>
<divclass="feature-row">
<h4>Failure memory</h4>
<divclass="benefits">
You can customize how long to remember failures and how many failures need to be in memory to consider a backend to be down.
FastCGI is typically used to serve PHP applications via php-fpm. FastCGI responders may require additional information about the script being run such as script name, path relative to root, etc., and Caddy's FastCGI transport takes care of all of that and makes it configurable.
</p>
<divclass="feature-list">
<divclass="feature-row">
<h4>Highly efficient</h4>
<divclass="benefits">
Caddy's FastCGI client implementation has been optimized to rival the performance of memory-unsafe clients written in C, sometimes even surpassing their performance.
</div>
</div>
<divclass="feature-row">
<h4>Path splitting</h4>
<divclass="benefits">
The path can be split, usually at the extension, to compute the proper PATH_INFO variable.
</div>
</div>
<divclass="feature-row">
<h4>Resolve root symlink</h4>
<divclass="benefits">
Optionally require paths declared to symlinks to be updated if the symlink changes without php-fpm being restarted.
</div>
</div>
<divclass="feature-row">
<h4>Environment variables</h4>
<divclass="benefits">
Read from the parent environment, and also set custom environment variables for your CGI script.
</div>
</div>
<divclass="feature-row">
<h4>Timeouts</h4>
<divclass="benefits">
Set timeouts to conserve resources.
</div>
<ulclass="detail">
<li>Dial (connect)</li>
<li>Read</li>
<li>Write</li>
</ul>
</div>
<divclass="feature-row">
<h4>Capture stderr</h4>
<divclass="benefits">
Caddy can capture the output to stderr from the upstream and log them for visibility.
Caddy's file server is the preferred way of serving static files for your website.
</p>
<p>
The way it works is simple: specify a root directory from which to serve the files, then request paths are automatically inferred as file paths relative to that root and the file is sent to the client.