From 7a3deeb4fc7bea8d7416d58dd2b672a057df793d Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Wed, 22 Jan 2020 10:51:40 -0700 Subject: [PATCH] Move docs out of here --- v2:-Documentation.md | 2521 +----------------------------------------- 1 file changed, 2 insertions(+), 2519 deletions(-) diff --git a/v2:-Documentation.md b/v2:-Documentation.md index ac962dd..d66786a 100644 --- a/v2:-Documentation.md +++ b/v2:-Documentation.md @@ -1,2522 +1,5 @@ -### THESE DOCS ARE MOVING. +### THESE DOCS HAVE MOVED, YAY! 🙌 ### Please visit our NEW documentation site: https://caddyserver.com/docs/ -**The new site is still a work-in-progress. Please be patient if you encounter errors. Thank you for understanding.** - -The new site does not yet have v2 Caddyfile documentation, as the v2 Caddyfile is rapidly changing in preparation for a stable release. The Caddyfile will probably be the last thing to be finalized before the release candidates. - ---------------- ---------------- ---------------- - -**OBSOLETE DOCS** - -This page describes how to use Caddy 2, which is a work-in-progress on the [v2 branch](https://github.com/caddyserver/caddy/tree/v2). See its [README](https://github.com/caddyserver/caddy/tree/v2#readme) to know how to download and build Caddy 2 for now. - -# Contents - -- [Command-line interface](#command-line-interface) - - [help](#help) - - [start](#start) - - [run](#run) - - [reload](#reload) - - [stop](#stop) - - [version](#version) - - [list-modules](#list-modules) - - [environ](#environ) - - [adapt](#adapt) - - [validate](#validate) - - [file-server](#file-server) - - [reverse-proxy](#reverse-proxy) -- [Admin endpoint](#admin-endpoint) - - [POST /load](#post-load) - - [POST /stop](#post-stop) - - [GET /config/[scope]](#get-configscope) - - [POST /config/[scope]](#post-configscope) - - [PUT /config/[scope]](#put-configscope) - - [PATCH /config/[scope]](#patch-configscope) - - [DELETE /config/[scope]](#delete-configscope) - - [Using IDs in JSON](#using-ids-in-json) -- [Caddy modules](#caddy-modules) -- [Config intro](#config-intro) - - [Making one from scratch](#making-one-from-scratch) - - [Duration values](#duration-values) - - [Placeholders (variables)](#placeholders-variables) - - [Config adapters](#config-adapters) - - [Caddyfile adapter](#caddyfile-adapter) - - [Matcher tokens](#matcher-tokens) - - [Shorthand placeholders](#shorthand-placeholders) - - [Global config](#global-config) - - [Caddyfile directives](#caddyfile-directives) - - [root](#root) - - [matcher](#matcher) - - [file_server](#file_server) - - [basicauth](#basicauth) - - [encode](#encode) - - [headers](#headers) - - [request_header](#request_header) - - [php_fastcgi](#php_fastcgi) - - [reverse_proxy](#reverse_proxy) - - [redir](#redir) - - [rewrite](#rewrite) - - [templates](#templates) - - [respond](#respond) - - [tls](#tls-directive) - - [try_files](#try_files) -- [Config structure](#config-structure) - - [admin](#admin) - - [logging](#logging) - - [writers](#caddyloggingwriters) - - [encoders](#caddyloggingencoders) - - [storage](#storage) - - [caddy.storage.file_system](#caddystoragefile_system) - - [apps](#apps) - - [http](#http) - - [http/servers](#httpservers) - - [http/servers/listen](#httpserverslisten) - - [http/servers/routes](#httpserversroutes) - - [HTTP Placeholders](#http-placeholders) - - [http/servers/routes/match](#httpserversroutesmatch) - - [http.matchers.host](#httpmatchershost) - - [http.matchers.path](#httpmatcherspath) - - [http.matchers.path_regexp](#httpmatcherspath_regexp) - - [http.matchers.method](#httpmatchersmethod) - - [http.matchers.query](#httpmatchersquery) - - [http.matchers.header](#httpmatchersheader) - - [http.matchers.header_regexp](#httpmatchersheader_regexp) - - [http.matchers.protocol](#httpmatchersprotocol) - - [http.matchers.not](#httpmatchersnot) - - [http.matchers.remote_ip](#httpmatchersremote_ip) - - [http.matchers.starlark_expr](#httpmatchersstarlark_expr) - - [http.matchers.file](#httpmatchersfile) - - [http/servers/handle](#httpservershandle) - - Middleware (non-terminating handlers): - - [http.handlers.cache](#httphandlerscache) - - [http.handlers.headers](#httphandlersheaders) - - [http.handlers.rewrite](#httphandlersrewrite) - - [http.handlers.markdown](#httphandlersmarkdown) - - [http.handlers.authentication](#httphandlersauthentication) - - [http.handlers.request_body](#httphandlersrequest_body) - - [http.handlers.encode](#httphandlersencode) - - [http.handlers.templates](#httphandlerstemplates) - - [http.handlers.vars](#httphandlersvars) - - Terminating handlers: - - [http.handlers.static_response](#httphandlersstatic_response) - - [http.handlers.file_server](#httphandlersfile_server) - - [http.handlers.reverse_proxy](#httphandlersreverse_proxy) - - [http.handlers.subroute](#httphandlerssubroute) - - [http.handlers.error](#httphandlerserror) - - [http/servers/errors](#httpserverserrors) - - [http/servers/tls_connection_policies](#httpserverstls_connection_policies) - - [tls.certificate_selection.custom](#tlscertificate_selectioncustom) - - [http/servers/automatic_https](#httpserversautomatic_https) - - [tls](#tls) - - [tls/certificates](#tlscertificates) - - [tls/automation](#tlsautomation) - - [tls/automation/policies](#tlsautomationpolicies) - - [tls.management.acme](#tlsmanagementacme) - - [tls/session_tickets](#tlssession_tickets) - - [tls.stek.standard](#tlsstekstandard) - - [tls.stek.distributed](#tlsstekdistributed) - - -# Command-line interface - -## help - -``` -$ caddy help [] -``` - -Prints CLI help text, optionally for a specific subcommand. - -## start - -``` -$ caddy start - [--config ] - [--adapter ] -``` - -Starts the Caddy process, optionally bootstrapped with an initial config file. Blocks until server is successfully running (or fails to run), then returns. On Windows, the child process will remain attached to the terminal, so closing the window will forcefully stop Caddy. See [`caddy run`](#run) for more details. - -Once started, you can use [`caddy stop`](#stop) to exit the background process. - -## run - -``` -$ caddy run - [--config ] - [--adapter ] - [--environ] -``` - -Same as `start`, but blocks indefinitely; i.e. runs Caddy in "daemon" mode. On Windows, this is recommended over `caddy start` when running Caddy manually since it will be more obvious that Caddy is still running and bound to the terminal window. - -If a config file is specified, it will be applied immediately after the process is running. If the config file is not in Caddy's native JSON format, you can specify an adapter with `--adapter` to adapt the given config file to Caddy's native format. The config adapter must be a registered module. Any warnings will be printed to the log, but beware that any adaptation without errors will immediately be used. If you want to review the results of the adaptation first, use the [`caddy adapt`](#adapt) subcommand. - -As a special case, if the current working directory has a file called "Caddyfile" and the `caddyfile` config adapter is plugged in (default), then that file will be loaded and used to configure Caddy, even without any command line flags. - -If `--environ` is specified, the environment as seen by the Caddy process will be printed before starting. This is the same as the `environ` command but does not quit after printing. - -## stop - -``` -$ caddy stop [--address ] -``` - -Gracefully stops the running Caddy process (other than the process for the stop command) and causes it to exit. - -It first tries to use the admin API (at its default address, or you can customize it with the `--address` flag) to perform a graceful shutdown. In other words, it simply performs a request to the [/stop endpoint](#post-stop). If that fails for any reason, it will look for any other process named the same as the current binary (i.e. `os.Args[0]`) and signal it to stop gracefully. On Windows, such a stop is forceful and Caddy will not have an opportunity to clean up any active locks. - -If you want to stop the current configuration but do not want to exit the process, use the admin API: [`DELETE /config/`](#delete-configscope). - - -## reload - -``` -$ caddy reload - --config - [--adapter ] - [--address ] -``` - -Gives the running Caddy instance a new configuration. This has the same effect as POSTing a document to the [/load](#post-load) endpoint, but is convenient for simple workflows revolving around config files. Since the admin endpoint is configurable, the endpoint configuration is loaded from the `--address` flag if specified; otherwise it is loaded from the given config file; otherwise the default is assumed. - -## version - -``` -$ caddy version -``` - -Prints the version. - -## list-modules - -``` -$ caddy list-modules - [--versions] -``` - -Prints the Caddy modules that are installed, optionally with version information from their associated Go modules. NOTE: Due to [a bug in the Go standard library](https://github.com/golang/go/issues/29228), version information is only available if Caddy is built as a dependency and not as the main module. See our README for build instructions that preserve module version info. - -## environ - -``` -$ caddy environ -``` - -Prints the environment as seen by caddy. Can be useful when debugging init systems or process manager units like systemd. - -## adapt - -``` -$ caddy adapt - --config - [--adapter ] - [--pretty] - [--validate] -``` - -Adapts a configuration to Caddy's native JSON config structure and writes the output to stdout, along with any warnings to stderr. The default `--adapter` value is "caddyfile". If `--pretty` is specified, the output will be formatted with indentation for human readability. If `--validate` is specified, the adapted configuration will be loaded and provisioned to check for validity (but it will not actually start running the config). - -Note that a config which is successfully adapted may still fail validation. For an example of this, try this Caddyfile: - -``` -localhost - -tls cert_notexist.pem key_notexist.pem -``` - -Try adapting it: - -``` -$ caddy adapt --config Caddyfile --adapter caddyfile -``` - -It succeeds without error; then try: - -``` -$ caddy adapt --config Caddyfile --adapter caddyfile --validate -``` - -Even though that Caddyfile can be adapted to JSON without errors, the actual certificate and/or key files do not exist, so validation fails because that error arises during the provisioning phase. Thus, validation is a stronger error check than adaptation is. - -### Example - -To adapt a Caddyfile to JSON that you can read and tweak manually: - -```bash -$ caddy adapt --config /path/to/Caddyfile --adapter caddyfile --pretty -``` - -## validate - -``` -$ caddy validate - --config - [--adapter ] -``` - -Validates a configuration file. This command deserializes the config, then loads and provisions all of its modules as if to start the config, but the config is not actually started. This exposes errors in a configuration that arise during loading or provisioning phases and is a stronger error check than merely serializing a config as JSON. - - -## file-server - -``` -$ caddy file-server - [--domain ] - [--path ] - [--listen ] - [--browse] -``` - -Spins up a quick but production-ready static file server. By default, the current directory will be the root of the site, but you can use `--path` to override that. `--listen` accepts a listener address; the default is `:2015`. If `--domain` is specified, then the files will only be served from that domain name, and Caddy will attempt to serve it over HTTPS if it qualifies for a certificate, so make sure your DNS is configured properly. If `--browse` is used, requests to directories without an index file will show a file listing. - -This command disables the admin API, making it easier to run multiple instances on a local development machine. - - -## reverse-proxy - -``` -$ caddy reverse-proxy - --from - --to -``` - -Spins up a quick but production-ready reverse proxy from `--from` address to the `--to` address. The addresses can be `host:port` format or a URL. - -This command disables the admin API, making it easier to run multiple instances on a local development machine. - -### Example - -To proxy a local port to a remote site: - -``` -$ caddy reverse-proxy --from localhost:2015 --to https://example.com -``` - - -# Admin endpoint - -Caddy is configured through an administration endpoint which is an HTTP listener with a REST API. You can [configure this admin endpoint](#admin) as part of the config structure. - -Default address: `localhost:2019` - -## POST /load - -Sets Caddy's configuration. It blocks until the reload completes or fails. Configuration changes are lightweight, efficient, and incur zero downtime. - -This endpoint supports different config formats using config adapters. The request's Content-Type header indicates the config format used in the request body. Usually, this should be `application/json` which represents Caddy's native config format. For another config format, specify the appropriate Content-Type so that the value after the forward slash `/` is the name of the config adapter to use. For example, when submitting a Caddyfile, use a value like `text/caddyfile`; or for JSON 5, use a value such as `application/json5`; etc. - -### Example - -```bash -$ curl -X POST "http://localhost:2019/load" \ - -H "Content-Type: application/json" \ - -d @caddy.json -``` - -**Note:** curl's `-d` flag removes newlines, so if your config format is sensitive to line breaks (e.g. the Caddyfile), use `--data-binary` instead: - -```bash -$ curl -X POST "http://localhost:2019/load" \ - -H "Content-Type: text/caddyfile" \ - --data-binary @Caddyfile -``` - -## POST /stop - -Gracefully shuts down the server and exits the process. To only stop the running configuration without exiting the process, use [`DELETE /config/`](#delete-configscope). - -### Example - -```bash -$ curl -X POST "http://localhost:2019/stop" -``` - -## GET /config/[scope] - -Exports Caddy's current configuration. Returns a JSON body. Any path appended to this endpoint will traverse the configuration and return only that scope. - -### Examples - -```bash -$ curl "http://localhost:2019/config/" -{"apps":{"http":{"servers":{"myserver":{"listen":[":443"],"routes":[{"match":[{"host":["example.com"]}],"handle":[{"handler":"file_server"}]}]}}}}} -``` - -```bash -$ curl "http://localhost:2019/config/apps/http/servers/myserver/listen" -[":443"] -``` - - -## POST /config/[scope] - -Changes Caddy's configuration at the named scope to the JSON body of the request. If the named scope is an array, POST appends; if an object, it creates or replaces. - -As a special case, many items can be added to an array if: - -1. the path ends in `/...` -2. the second-to-last element of the path refers to an array -3. the payload is an array - -In this case, the elements in the payload's array will be expanded, and each one will be appended to the destination array. - -### Examples - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -d '":8080"' \ - "http://localhost:2019/config/apps/http/servers/myserver/listen" -``` - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -d '[":8080", ":5133"]' \ - "http://localhost:2019/config/apps/http/servers/myserver/listen/..." -``` - - -## PUT /config/[scope] - -Changes Caddy's configuration at the named scope to the JSON body of the request. If the named scope is an array, PUT inserts; if an object, it strictly creates a new value. - -### Example - -```bash -$ curl -X PUT \ - -H "Content-Type: application/json" \ - -d '":2080"' \ - "http://localhost:2019/config/apps/http/servers/myserver/listen" -``` - - -## PATCH /config/[scope] - -Changes Caddy's configuration at the named scope to the JSON body of the request. PATCH strictly replaces an existing value or array element. - -### Example - -```bash -$ curl -X PUT \ - -H "Content-Type: application/json" \ - -d '":2080"' \ - "http://localhost:2019/config/apps/http/servers/myserver/listen" -``` - - -## DELETE /config/[scope] - -Changes Caddy's configuration at the named scope to the JSON body of the request. DELETE deletes the value at the named scope. - -### Examples - -To unload the entire current configuration: - -```bash -$ curl -X DELETE "http://localhost:2019/config/" -``` - -To stop only one of your HTTP servers: - -```bash -$ curl -X DELETE "http://localhost:2019/config/apps/http/servers/myserver" -``` - - -## Using IDs in JSON - -You can embed IDs in your JSON document for easier direct access to those parts of the JSON. Simply add a field called `"@id"` to an object and give it a unique name. For example, if you had a reverse proxy handler that you wanted to access frequently: - -```javascript -{ - "@id": "my_proxy", - "handler": "reverse_proxy", - // ... -} -``` - -To use it, simply make a request to the `/id/` API endpoint in the same way you would to the `/config/` endpoint, but the ID takes the request directly into that scope of the config. For example, this request adds an upstream to a reverse proxy: - -``` -POST /config/apps/http/servers/myserver/routes/1/handle/0/upstreams "10.0.0.5:7000" -``` - -It would be shortened to: - -``` -POST /id/my_proxy/upstreams "10.0.0.5:7000" -``` - -which is much easier to remember and write by hand. - - -# Caddy modules - -Caddy modules are distinct from [Go modules](https://github.com/golang/go/wiki/Modules), although technically speaking, Caddy modules can be implemented by Go modules. When we talk about modules here, we mean Caddy modules. - -Caddy modules are the evolution of "plugins" in Caddy 1, and although modules are much-improved over plugins, the idea is similar. Various parts of Caddy's functionality can be swapped out or extended by use of modules which are statically compiled in at build-time. - -Each Caddy module has a name, scope/namespace, and ID: - -- A name looks like `a.b.c.module_id` -- The namespace would be `a.b.c` -- The module ID is `module_id` which must be unique in its namespace - -When the context makes it obvious what the namespace is, we generally refer to the module ID as the name, or use the terms interchangably; and in conversation the namespace can be omitted. - -_Host modules_ (or _parent modules_) are modules which load/initialize other modules. - -_Guest modules_ (or _child modules_) are modules which get loaded or initialized. All modules are at least guest modules. - - -# Config intro - -At its core, Caddy 2 is configured with JSON via an API. There are no config files, but Caddy's command line interface can wrap the task of loading a config from a file and feeding it to the API for you. There are also alternatives to writing JSON by hand; see [Config Adapters](#config-adapters) for more on that. - -This section covers just a few things you will find helpful as you craft a Caddy config. - -## Making one from scratch - -We have a [separate page](https://github.com/caddyserver/caddy/wiki/v2:-Config-from-Scratch) which walks you through an example of building up a config of a working static file server with automatic HTTPS from scratch. - - -## Duration values - -Any properties which expect a duration value are given as a string in the same format as [Go's time.Duration type](https://golang.org/pkg/time/#ParseDuration): - -> A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - -Valid examples: `"30s"`, `"15m"`, `"1h25m30s"`, and `"30us"`. - -## Placeholders (variables) - -You can inject dynamic values into Caddy 2's configuration by using placeholders (aka variables). Placeholders can be used in properties which accept placeholder values; not all properties execute placeholders. Only string values can use placeholders. - -Placeholders are enclosed in `{ }` and namespaced to avoid collisions. Different placeholders are available in different contexts. - -All contexts support the global placeholders: - -``` -{system.hostname} - The system's hostname -{system.os} - The system's OS -{system.arch} - The system's architecture -{system.slash} - The system's filepath separator -{time.now.common_log} - The current timestamp in Common Log Format -{env.VARIABLE_NAME} - Replace VARIABLE_NAME with any env variable -``` - -## Config adapters - -Caddy's native config language is JSON, but writing JSON by hand can be tedious and error-prone. That's why Caddy supports being configured with other means through _config adapters_. They make it possible to use config in a more comfortable or convenient format by outputting Caddy JSON for you. For example, a config adapter may turn your NGINX config into Caddy JSON. - -Config adapters do their best to translate your input to Caddy JSON with the highest fidelity and correctness, but some features/behaviors don't translate well or are not yet programmed. Because this conversion process is not guaranteed to be complete and correct all the time, we don't call them "converters" or "translators". They are "adapters" since they will at least give you a good starting point to finish crafting your final JSON config. That said, the Caddyfile format is specifically designed for Caddy, so any and all of the Caddyfile's features should translate to Caddy JSON correctly and completely. The Caddyfile adapter is a special case in this sense. - -Config adapters can output the resulting JSON, warnings, and errors. JSON results if no errors occur. Errors occur when something is wrong with the input (for example, syntax errors). Warnings are emitted when something is wrong with the adaptation but which is not necessarily fatal (for example, feature not supported). Caution is advised if using configs adapted with warnings. - -You can use config adapters simply by specifying the `--config` and `--adapter` flags with the [`caddy adapt`](#adapt), [`caddy start`](#start), and [`caddy run`](#run) commands. - -Config adapters are an exciting and unique feature. We hope you will help contribute to the config adapters! - -### Caddyfile adapter - -The Caddyfile is the #1 choice for most users to configure Caddy because it is extremely quick to learn, easy to comprehend, and very productive for developers. [The Caddyfile syntax is documented on the Caddy website.](https://caddyserver.com/docs/caddyfile) - -The Caddyfile is not as expressive as Caddy's native JSON, so it cannot describe all possible Caddy configurations. However, it is designed to be suitable for upwards of ~95% of use cases. Some odd web apps or other edge cases may necessitate using the Caddy JSON directly, but you can still use a config adapter such as the Caddyfile as a starting point. Caddy's config is the most flexible on the planet, even if the Caddyfile can't express all of the possibilities. - -The Caddyfile is geared toward _everyone_, not just beginners. Rather than skill level, the decision about whether to use the Caddyfile should be more about what your technical and business requirements are, or if nothing else, what you personally prefer. - -The Caddyfile can support different "server types" or syntaxes. The default is the HTTP server type, which we describe here. You may be familiar with others, such as the Corefile from [CoreDNS](https://coredns.io), which is a different flavor of the same Caddyfile syntax. - -The v2 Caddyfile is not backwards-compatible with v1; as such, you cannot bring your v1 Caddyfile and expect it to work in v2 without changes (although some will be compatible by chance). - -At a high level, major changes from v1 include: - -- Some directives have changed, along with their syntax/structure. -- The static file server is no longer enabled by default. (There was no way to turn it off in v1, which could be problematic in some situations.) There is a `file_server` directive to enable the static file server. -- Request matching is much more powerful and not limited to just path prefixes anymore. -- Directives need not be centrally registered on a list in the Caddy code base anymore. This means you can write a handler module for Caddy and publish it and use it right away, without needing to submit a PR to the Caddy code base to add your directive to the list and wait for the next Caddy release. - - -#### Matcher tokens - -Request matching is one of the most important parts of configuring a web server. For directives that inject handlers into the middleware chain, you can specify which requests that handler applies to with _matchers_. - -A matcher token comes immediately after the directive token and can be one of these forms: - -1. `*` to match all requests (wildcard). -2. `/path` starting with a forward slash to match path prefix. -3. `=/path` for an exact path match. -3. `match:name` to specify a matcher by name. - -If a matcher token is omitted, it is the same as a wildcard matcher. The wildcard matcher is only needed if a matcher token is required; for example, if the argument you want to give a directive is itself a path, it would be ambiguous with a path matcher, so you use a wildcard token: `root * /home/www/mysite` - -Path matching is the most common, so it is inlined for convenience: `redir /old-article.html /new-article.html` - -Specifying a matcher by name gives you more flexibility. To define a matcher by name, use the `matcher` directive: - -```plain -matcher name { - ... -} -``` - -See the [Caddyfile directives](#caddyfile-directives) below for more details about matchers. - -#### Shorthand placeholders - -The Caddyfile is supposed to be easy to write, so it also provides shorter placeholder variable names for you to use. Instead of `{http.request.uri.path}` for example, you could just write `{path}`. Again, this loses some of the flexibility of the full JSON config because these shorthand variables are not properly namespaced. They are optional, however, so you are welcome to use the full name. - -| Shorthand | Replaces | -|------------|---------------------------------| -| {uri} | {http.request.uri} | -| {path} | {http.request.uri.path} | -| {host} | {http.request.host} | -| {hostport} | {http.request.hostport} | -| {method} | {http.request.method} | -| {scheme} | {http.request.scheme} | -| {file} | {http.request.uri.path.file} | -| {dir} | {http.request.uri.path.dir} | -| {query} | {http.request.uri.query_string} | - - -#### Global config - -The Caddyfile has a special place for specific settings that apply to the whole process rather than specifically per-site. This allows us to replace an arbitrary and growing number of CLI flags and environment variables, which constituted a large portion of hidden configuration in version 1. - -Simply create a server block with no keys to specify global options. The following options are allowed: - -``` -{ - http_port - https_port - handler_order appearance| { - - } - storage { - - } - experimental_http3 -} -``` - -Note that this feature is not a "defaults" block which all other sites inherit. The Caddyfile does not have inheritence. To share repeated directives across many site definitions, use snippets. - - -#### Caddyfile directives - -##### root - -Specifies the site root, usable by other directives that need a root path. - -``` -root [] -``` - -##### matcher - -Creates a matcher. Multiple matchers are AND'ed. - -``` -matcher { - host - path - path_regexp [] - method - query - header - header_regexp - protocol http|https|grpc - remote_ip - file { - root - try_files - try_policy first_exist|smallest_size|largest_size|most_recent_modified - } -} -``` - -##### file_server - -Enables static file server, optionally with directory browsing. - -``` -file_server [] [browse] { - hide - index - browse [] - root -} -``` - -##### basicauth - -Configures HTTP Basic Authentication. - -``` -basicauth [] [] { - [] - ... -} -``` - -Passwords must be hashed. Available algorithms are `bcrypt` and scrypt. Default is bcrypt. Salt is required when using scrypt. - -##### encode - -Encodes HTTP responses. Used for compression. - -``` -encode [] { - gzip [] - zstd - brotli [] -} -``` - -##### headers - -Manipulates HTTP response headers. Can add, remove, set, or do substring replacements. - -``` -headers [] [[+|-] [] []] { - [+] [ []] - - -} -``` - -##### request_header - -Manipulates an HTTP request header. - -``` -request_header [] [[+|-] [] [replacement]] -``` - -##### php_fastcgi - -Proxies requests to one or more FastCGI backends specially configured for PHP apps. The most basic usage has this syntax: - -``` -php_fastcgi php-fpm:9000 -``` - -That single line is sufficient and works for _most_ PHP scripts (replace `php-fpm:9000` with your php-fpm listener). - -If you have a Unix socket, use an address in the form `unix//path/to/socket`. - -This directive actually has the same syntax and options as [reverse_proxy](#reverse_proxy), but is shorthand for a configuration equivalent to this example (**PLEASE do not needlessly copy and paste this example**, because the directive above does the same thing and is recommended unless your specific needs are different): - -``` -# canonicalize URI trailing slash when index file present -matcher indexFiles { - not { - path */ - } - file { - try_files {path}/index.php - } -} -redir match:indexFiles {path}/ - -# internally rewrite directory URIs to index.php files -try_files {path} {path}/index.php index.php - -# proxy any requests for PHP files to backend via FastCGI -matcher phpFiles { - path *.php -} -reverse_proxy match:phpFiles php-fpm:9000 { - transport fastcgi { - split .php - } -} -``` - - -##### reverse_proxy - -Proxies requests to one or more backends with configurable transport options. - -``` -reverse_proxy [] [] { - # backends - to - - # load balancing - lb_policy [] - lb_try_duration - lb_try_interval - - # active health checking - health_path - health_port - health_interval - health_timeout - health_status - health_body - - # passive health checking - max_fails - fail_duration - max_conns - unhealthy_status - unhealthy_latency - - # streaming - flush_interval - - # header manipulation - header_up [+|-] [ []] - header_down [+|-] [ []] - - # round trip - transport { - ... - } -``` - -HTTP transport options: - -``` -transport http { - read_buffer - write_buffer - dial_timeout - tls # use HTTPS instead of HTTP - tls_client_auth - tls_insecure_skip_verify - tls_timeout - keepalive [off|] - keepalive_idle_conns -} -``` - -FastCGI transport options: - -``` -transport fastcgi { - root - split - env -} -``` - -For proxying to PHP via FastCGI (php-fpm) specifically, see the [php_fastcgi](#php_fastcgi) directive. - -##### redir - -Issue an HTTP redirect. - -``` -redir [] to [|permanent|temporary] -``` - -##### rewrite - -Rewrite the request URI. - -``` -rewrite [] to -``` - -##### templates - -Execute the HTTP response body as a [template](https://github.com/caddyserver/caddy/wiki/v2:-Templates). - -``` -templates [] { - mime - between - root -} -``` - -##### respond - -Respond with a hard-coded HTTP response. - -``` -respond [] { - body - close -} -``` - -##### tls (directive) - -Configure TLS for the site in which the directive appears. (Still WIP) - -``` -tls [off| ] { - load - protocols [] - ciphers - curves - alpn -} -``` - -##### try_files - -Rewrites a request based on the existence of the listed files on disk. Because this is a fairly common rewrite, this directive simply combines a `rewrite` handler with a `file` matcher for convenience in writing. - -``` -try_files -``` - - -# Config structure - -Caddy configuration is a JSON document. - -Generally, object keys are optional, as most of the "required" settings have sane defaults. If something is actually explicitly required for a successful config load, the docs will say so. - -At the top level, you'll find properties needed for Caddy's basic functionality: - -```json -{ - "admin": {}, - "logging": {}, - "storage": {}, - "apps": {} -} -``` - -## admin - -Configures the administration endpoint, also known as the Caddy API. - -```json -{ - "disabled": false, - "listen": "localhost:2019", - "enforce_origin": false, - "origins": [] -} -``` - -- `disabled`: If true, the admin endpoint will be completely disabled. Note that this makes any runtime changes to the config impossible, since the interface to do so is through the admin endpoint. -- `listen`: the address to which the admin endpoint's listener should bind itself. Can be [any single network address](#httpserverslisten) that can be parsed by Caddy. -- `enforce_origin`: If true, CORS headers will be emitted and requests to the admin API will be rejected if their Host and Origin headers do not match the expected value(s). If `origins` is not set, the `listen` address is the only value allowed by default. Use `origins` to customize which origins/hosts are allowed. -- `origins`: The list of allowed origins for API requests. Only used if `enforce_origin` is `true`. If not set, the listener address will be the default value. If set but empty, no origins will be allowed. - - - -## logging - -Configures Caddy logs. By default, all logs at INFO level and higher are written to standard error ("stderr" writer) in a human-readable format ("console" encoder). The default log is called "default" and you can customize it. You can also define additional logs. - -By default, all logs accept all log entries, but you can filter by level and module/logger names. A logger's name is the same as the module's name, but a module may append to logger names for more specificity. For example, you can filter only logs emitted by HTTP handlers using the name `"http.handlers"`, because all HTTP handler module names start with that. - -There is also a "sink" where all unstructured logs emitted from Go's standard library logger are written. These logs are common in dependencies that are not designed specifically for use in Caddy. Because they are global and unstructured, the sink lacks most advanced features and customizations. - -Caddy logs (except the sink) are mostly zero-allocation, so they are very high-performing in terms of memory and CPU time. Enabling sampling can further increase throughput on extremely high-load servers. - -```json -{ - "sink": { - "writer": {} - }, - "logs": { - "default": { - "writer": {}, - "encoder": {}, - "level": "info", - "sampling": { - "interval": "1s", - "first": 100, - "thereafter": 100 - }, - "include": [], - "exclude": [] - } - } -} -``` - -- `sink`: Configures log emissions made by Go's global `log` package logger. This is typically where third-party libraries and dependencies which do not support Caddy's logging facilities will emit their logs. -- `sink.writer`: The logging writer for the sink logs. -- `logs`: User-defined logs. All logs defined in this object, including "default", have the same structure and features, so the documentation explains that structure using `logs.default`. -- `logs.default`: As a special case, the default Caddy logs. All logs will be emitted to this logger by default. -- `logs.default.writer`: The log writer module. -- `logs.default.encoder`: The log encoder module. -- `logs.default.level`: The lowest level entries to add to the log. -- `logs.default.sampling`: Configures log entry sampling, useful for improving performance on extremely high pressure servers. -- `logs.default.sampling.interval`: The window over which to conduct sampling. -- `logs.default.sampling.first`: Log this many entries within a given level and message for each interval. -- `logs.default.sampling.thereafter`: If more entries with the same level and message are seen during the same interval, keep one in this many entries until the end of the interval. -- `logs.default.include`: Allow modules within this namespace to emit logs here. Mutually exclusive with `exclude`. -- `logs.default.exclude`: Deny modules within this namespace from emitting logs here. Mutually exclusive with `include`. - -If both `include` and `exclude` are populated, longer namespaces have priority. If neither are populated, all logs are emitted. - -### caddy.logging.writers - -Writers are where logs get written. Because these are modular, you can write your logs to anything, anywhere! - -#### caddy.logging.writers.stdout - -Emits logs to standard output. - -```json -{ - "output": "stdout" -} -``` - -#### caddy.logging.writers.stderr - -Emits logs to standard error. This is the default writer. - -```json -{ - "output": "stderr" -} -``` - -#### caddy.logging.writers.discard - -Discards all writes. This effectively disables the log, and is only useful if you want to completely turn off the default log. - -```json -{ - "output": "discard" -} -``` - -#### caddy.logging.writers.file - -Writes logs to a local file, optionally with automatic log rolling. Log rolling is enabled by default just in case, but can be disabled if you have an external service rotating logs. Most use cases will only need to specify a filename, since other defaults are reasonable. - -```json -{ - "output": "file", - "filename": "", - "roll": true, - "roll_gzip": true, - "roll_local_time": false, - "roll_size_mb": 100, - "roll_keep": 10, - "roll_keep_days": 90 -} -``` - -- `filename`: The name of the log file. -- `roll`: Enables log rolling (default). -- `roll_gzip`: Enables compression of rolled logs (default). -- `roll_local_time`: Whether to use local times in rotated log filenames. -- `roll_size_mb`: Size of a log file in MB at which it will be rotated. -- `roll_keep`: Keep this many rolled log files. -- `roll_keep_days`: How many days to keep rolled files. - - -### caddy.logging.encoders - -Encoders determine how log entries are encoded (formatted). - -In addition to the properties specific to each encoder, these properties are available for all encoders (and have the following defaults): - -```json -{ - "message_key": "msg", - "level_key": "level", - "time_key": "ts", - "name_key": "logger", - "caller_key": "caller", - "stacktrace_key": "stacktrace", - "line_ending": "\n", - "time_format": "wall_milli", - "duration_format": "seconds", - "level_format": "color" -} -``` - -- `message_key`: The key for the message field. -- `level_key`: The key for the level field. -- `time_key`: The key for the timestamp field. -- `name_key`: The key for the name of the logger field. -- `caller_key`: The key for the caller field. -- `stacktrace_key`: The key for the stacktrace field. -- `line_ending`: The line ending to use. -- `time_format`: The format to use for timestamps. Can be: "unix_seconds_float", "unix_milli_float", "unix_nano", "iso8601", "rfc3339", "rfc3339_nano", "wall", "wall_milli", "wall_nano", or [any time format value accepted by Go's time package](https://golang.org/pkg/time/#pkg-constants). -- `duration_format`: The format to use for duration values. Can be "seconds", "nano", or "string". -- `level_format`: The format to use for the log level. Can be "lower", "upper", or "color" (useful with console encoder). - -#### caddy.logging.encoders.console - -Formats log enties for human readability on the console. This is the default encoder. - -```json -{ - "format": "console" -} -``` - -#### caddy.logging.encoders.filter - -This encoder merely filters fields in logs. It wraps an underlying encoder which does the actual processing. You must define the wrapped encoder. - -```json -{ - "format": "filter", - "fields": { - "name": {} - }, - "wrap": {} -} -``` - -- `fields`: A map of fields to the filter to apply to that field. Nested fields (fields which are contained within others, as is common when logging objects) can be denoted with `>`, so for example, `request>remote_addr` refers to the "remote_addr" field within the "request" object. -- `wrap`: The underlying encoder to use. - -##### caddy.logging.encoders.filter.delete - -This filter deletes the field from the log entry. - -```json -{ - "filter": "delete" -} -``` - -##### caddy.logging.encoders.filter.ip_mask - -This filter masks IP addresses. - -```json -{ - "filter": "ip_mask", - "ipv4_cidr": 0, - "ipv6_cidr": 0 -} -``` - -- `ipv4_cidr`: The CIDR prefix (number of bits) to mask on IPv4 addresses. -- `ipv6_cidr`: The CIDR prefix (number of bits) to mask on IPv6 addresses. - -#### caddy.logging.encoders.json - -JSON formatted logs. There is one JSON document per line/entry. - -```json -{ - "format": "json" -} -``` - -#### caddy.logging.encoders.logfmt - -Formats each structured log entry as [logfmt](https://www.brandur.org/logfmt). Note that this format does not support complex types, so objects and maps cannot be encoded. - -```json -{ - "format": "logfmt" -} -``` - - -#### caddy.logging.encoders.string - -An encoder that will write an entry that consists exclusively of a single field in the log. This is useful if that particular field is already formatted the way you want your logs formatted. - -```json -{ - "format": "string", - "field": "", - "fallback": {} -} -``` - -- `field`: The name of the field to use its value as the log entry. -- `fallback`: An encoder to use if the specified field does not exist or cannot be used. Note that this can lead to mixed encodings in your log file, but depending on your requirements, may be better than eliding log entries entirely. - - -## storage - -Configures Caddy's default storage module. A storage module defines how and where Caddy stores assets (such as TLS certificates). - -Default: The local file system (`caddy.storage.file_system`). If `XDG_DATA_HOME` is set, then `$XDG_DATA_HOME/caddy` is the folder. Otherwise, `$HOME/.local/share/caddy` is the folder. - -### caddy.storage.file_system - -```json -{ - "module": "file_system", - "root": "/var/caddy_storage" -} -``` - -- `module`: The ID of the storage module. -- `root`: The base path in which things should be stored. - - -## apps - -Each app to initialize should be keyed by its name (i.e. module ID). - -Example which initializes the `tls` and `http` apps: - -```json -{ - "apps": { - "tls": { ... }, - "http": { ... } - } -} -``` - -### http - -The `http` app implements an HTTP server with automatic HTTPS: - -```json -{ - "http_port": 80, - "https_port": 443, - "grace_period": "", - "servers": {} -} -``` - -- `http_port`: The port to use for HTTP (optional; used for automatic HTTPS). -- `https_port`: The port to use for HTTPS (optional; used for automatic HTTPS). -- `grace_period`: How long to allow servers to shut down gracefully before forcing them to stop. Duration values follow Go's `time.Duration` format, e.g. `"10s"` or `"1m30s"`. -- `servers`: Server configurations, keyed by unique names you choose. A server is a set of listeners and routes which make sense to group together. At this time, servers cannot have overlapping listeners. - - -#### http/servers - -A map of server ID (of your choice) to its configuration object. Each server is an object with the following structure: - -```json -{ - "listen": [], - "read_timeout": "", - "read_header_timeout": "", - "write_timeout": "", - "idle_timeout": "", - "max_header_bytes": 0, - "routes": [], - "errors": {}, - "tls_connection_policies": [], - "automatic_https": {}, - "max_rehandles": 3, - "strict_sni_host": false, - "experimental_http3": false, - "logs": { - "logger_names": {} - }, -} -``` - -- `listen`: The array of listener addresses to bind to. -- `read_timeout`: How long to allow reading an HTTP request. -- `read_header_timeout`: How long to allow reading an HTTP request header. -- `write_timeout`: How long to allow writing an HTTP response. -- `idle_timeout`: How long to keep idle connections open. -- `max_header_bytes`: How many bytes to allow an HTTP request header to be read. -- `routes`: The list of routes. -- `errors`: Configures how to handle errors during HTTP requests. -- `tls_connection_policies`: List of TLS connection policies. -- `automatic_https`: Customize or disable automatic HTTPS. -- `max_rehandles`: How many rehandles to allow; prevents infinite looping. -- `strict_sni_host`: If true, enforce that an HTTP Host header matches the connection's ServerName (SNI) value from the TLS handshake. Important when using TLS client authentication. -- `experimental_http3`: If true, IETF-draft-compliant HTTP/3 ("QUIC") will be enabled. It creates a UDP listener. This feature is experimental and is not subject to compatibility promises. -- `logs`: Enables and configures HTTP access logging. An empty object uses default settings. Access logs document HTTP requests as they come in; they use the namespace `http.log.access`. Error logs record HTTP handler errors and use the namespace `http.log.error`. -- `logs.logger_names`: Map of request host to custom logger name. For example, if you wanted all requests for `example.com` to be emitted to a logger with a unique name, you can do `"example.com": "example"` and then all access logs related to requests for `example.com` will use a logger named `http.log.access.example` (and same for error logs, but with `.error.` in the name instead). - -#### http/servers/listen - -Listener addresses have the following form: - - network/address - -The network name is anything that [Go's `net` package](https://golang.org/pkg/net) recognizes, and is optional. The default network is `tcp`. If a network is specified, a single forward slash `/` is used to separate the network and the address. - -The address portion may be any of these forms: - -- `host` -- `host:port` -- `:port` -- `/path/to/socket` - -The host may be any hostname, resolvable domain name, or IP address. The port may be a single value (`:8080`) or a range (`:8080-8085`). A port range will be multiplied into singular addresses. (Not all config parameters accept multiple ports.) - -Valid examples: - - :8080 - 127.0.0.1:8080 - localhost:8080 - localhost:8080-8085 - tcp/localhost:8080 - tcp/localhost:8080-8085 - udp/localhost:9005 - unix//path/to/socket - -#### http/servers/routes - -Routes are not your typical notion of routes (i.e. "GET /foo/bar" -> someFunc). Routes in Caddy 2 are much more powerful and dynamic. They are given in an ordered list, and each route has two parts: - -1. match (optional) -2. handle - -You can think of "match-handle" like "if-then" if that helps (but Caddy config is not really imperative or procedural). - -For each request, route matchers are evaluated in the order they are given in the list. Each route that matches the request is compiled into the _composite route_, which ends up becoming the HTTP handler for the request. All matchers in the routes list are evaluated before the request is sent down the handler chain. - -In Caddy 1, HTTP handlers were chained in a hard-coded order you had no control over. Unlike Caddy 1, handlers in Caddy 2 are chained in the order you specify in the routes. So, the order of routes matters. - -In some cases, a request can be _rehandled_, meaning that it is virtually processed through the top-level handler again. This is useful if changes were made to a request (such as rewriting part of it) and you want to process it as if it originally came in like that. Other web servers call this an internal redirect. Upon rehandling, a new composite route will be compiled and the request will be processed again. - -The structure for a route is: - -```json -{ - "group": "", - "match": [], - "handle": [], - "terminal": false -} -``` - -- `group`: If this route belongs to a group, specify its name here. Groups are used for mutual exclusion. Only the first matching route from a group is compiled into the composite route. (Think like radio buttons on an HTML form.) Groups can be used to implement "else" and "else-if" logic with matchers. -- `match`: The "if" statement of the route. This specifies an ordered list of matcher sets. -- `handle`: The "then" statement of the route. This specifies an ordered list of handlers to chain together. Handlers are chained from first to last, so requests flow from the first handler to the last. -- `terminal`: If true, no additional routes will be considered. - - -##### HTTP Placeholders - -Within an HTTP route, you can use additional placeholders: - -``` -{http.request.hostport} - The Host header of the request (including port, if given) -{http.request.host} - Same as hostport but with port stripped -{http.request.host.labels.N} - N is the number; i.e. for "foo.example.com": - 0 = "com" - 1 = "example" - 2 = "foo" -{http.request.port} - The port of the request. -{http.request.scheme} - The scheme of the request (http/https usually) -{http.request.uri} - The full request URI -{http.request.uri.path} - The path component of the request URI -{http.request.uri.path.file} - The filename in the path, excluding directory -{http.request.uri.path.dir} - The directory, excluding leaf filename -{http.request.uri.query.PARAM} - A specific query string parameter given by PARAM (not all caps) -{http.request.header.FIELD-NAME} - Request header field name (not all caps) -{http.request.cookie.COOKIE_NAME} - Request cookie name (not all caps) -{http.response.header.FIELD-NAME} - Response header field name (not all caps) -``` - -If you are using regexp matchers, capture groups (both named and numeric) are available as well: - - {http.regexp.REGEXP_NAME.CAPTURE_GROUP} - -Replacing: - -- REGEXP_NAME with the lower-cased name you gave the regular expression. -- CAPTURE_GROUP with the name or index number (starting at 1) of the capture group in the regular expression. - -This will allow you to access capture groups from anywhere in your HTTP route. - - -#### http/servers/routes/match - -Each route takes a list of matcher sets. A matcher set is comprised of matchers of various types. A matcher may be comprised of multiple values. - -Example: - -```json -[ - { - "host": ["example.com"] - }, - { - "host": ["example.com", "sub.example.com"], - "path": ["/foo/bar"] - } -] -``` - -Here you can see there are 2 matcher sets. The first one has one matcher (`host`), and the second one has two (`host` and `path`). - -The boolean logic of request matching goes like this: - -- Matcher sets are OR'ed (first matching matcher set is sufficient). -- Matchers within a set are AND'ed (all matchers in the set must match). -- Values within a specific matcher are OR'ed. - -This design enables moderately complex logic such as: - -``` -IF (Host = "example.com") - OR (Host = "sub.example.com" AND Path = "/foo/bar") -``` - -The expressions in parentheses are matcher sets. This expression has 2 matcher sets. This expression uses two matchers: Host and Path, which are AND'ed together within their set. - -Even more advanced logic can be expressed through the Starlark expression matcher at virtually no loss in performance. - -A route may omit matchers entirely to match all requests. - -All matchers within the same route list are evaluated before the requst is handled and do not modify the request, so all the matchers will see the same version of the request. - -##### http.matchers.host - -Matches requests by Host header. - -```json -"host": [] -``` - -Host values can contain wildcards to substitute for one label of the domain name. Host matching is case-insensitive. - -##### http.matchers.path - -Matches requests by request path. - -```json -"path": [] -``` - -By default, paths are treated as prefixes: a request matches if its path starts with the given path. There are two special exceptions to this: - -- A path may start with `*`, then it is treated as a suffix match. -- A path may start with `=`, then the path must match exactly what follows. - -Paths may contain globular patterns. Path matching is case-insensitive. If case sensitivity is required, use a path_regexp matcher. There are two special cases: - -##### http.matchers.path_regexp - -Matches requests by request path using a regular expression. - -```json -"path_regexp": { - "name": "", - "pattern": "", -} -``` - -- `name`: A name for the regular expression so you can access its capture groups in placeholders. Optional. -- `pattern`: The regular expression in [Go's regexp syntax](https://golang.org/pkg/regexp/). - - -##### http.matchers.method - -Matches requests by the request method. - -```json -"method": [] -``` - -Methods should be upper-cased. - -##### http.matchers.query - -Matches requests by query string parameters. - -```json -"query": { - "param": ["values"] -} -``` - -The object keys should be query string parameters, with the values to match in an array, as strings. - - -##### http.matchers.header - -Matches requests by request headers. - -```json -"header": { - "Field": ["values"] -} -``` - -The object keys should be header field names, with the values to match in an array. If the values array is present but empty, it will accept any value and match merely on the presence of the header field. This matcher supports wildcards at the beginning and end of values: `*foo` matches all values ending with "foo", `foo*` matches values starting with "foo", and `*foo*` matches all values that contain "foo". These common wildcard matches are much faster than their regular expression equivalents. - -##### http.matchers.header_regexp - -Matches requests by request headers using a regular expression. - -```json -"header_regexp": { - "Field": { - "name": "", - "pattern": "" - } -} -``` - -The object keys should be header fields, then: - -- `name`: A name for the regular expression so you can access its capture groups in placeholders. Optional. -- `pattern`: The regular expression in [Go's regexp syntax](https://golang.org/pkg/regexp/). - -##### http.matchers.protocol - -Matches requests by the protocol being used. - -```json -"protocol": "" -``` - -Possible values are `http`, `https`, or `grpc`. - -##### http.matchers.not - -Matches requests by negating a matcher set. - -```json -"not": {} -``` - -Its value should be a matcher set. The result of the matcher set will be negated. - -##### http.matchers.remote_ip - -Matches requests by the client IP address. - -```json -"remote_ip": { - "ranges": [] -} -``` - -- `ranges`: A list of IP addresses or CIDR ranges to match. - -##### http.matchers.starlark_expr - -Matches requests by evaluating a Starlark expression. This provides a great deal of flexibility with regards to boolean logic, and is a fine fit for advanced matching needs. - -```json -"starlark_expr": "" -``` - -The value should be a Starlark expression. (TODO: examples and docs) - - -##### http.matchers.file - -Matches requests based on files on disk. - -```json -"file": { - "root": "", - "try_files": [], - "try_policy": [] -} -``` - -- `root`: The base path with which relative paths will be rooted. Default is `{http.vars.root}` if set, or current working directory. -- `try_files`: A list of root-relative file paths to "try" matching (similar to nginx's try_files). A file will be selected based on try_policy. Directory convention is observed: paths ending in a forward slash (`/`) _must_ be a directory in order to match; paths ending without a forward slash _must not_ be a directory for a match. For example: `/my/path/` matches only directories and `/my/path` matches only files. To match both, include both patterns. -- `try_policy`: When trying files listed in `try_files`, use this policy to choose one. - - `first_exist` (default): Choose the first file that exists. - - `smallest_size`: Choose the file with the smallest size. - - `largest_size`: Choose the file with the largest size. - - `most_recent_modified`: Choose the file that was most recently modified. - -If a file is matched, two new placeholders will be made available: - -- `{http.matchers.file.relative}`: The root-relative path of the file. This is often useful when rewriting requests. -- `{http.matchers.file.absolute}`: The absolute path of the file. - - - -#### http/servers/handle - -Handlers are modules which handle HTTP requests. They are chained together in a middleware fashion: requests flow from the first handler to the last (top of the config to the bottom), with the possibility that any handler could abort the chain and/or return an error. Responses flow back up the chain as they are written out to the client. - -Not all handlers call the next handler in the chain. For example, the `file_server` handler always serves a file from disk or returns an error. Thus, configuring handlers after `file_server` in your route is illogical, since they would never be executed. You will want to put handlers which originate the response at the very end of your route(s). The documentation for a module should state whether it invokes the next handler, but sometimes it is common sense. - -Some handlers manipulate the response. Remember that **requests flow down, and responses flow up**. For example, if you wanted to use both `templates` and `encode` handlers, you would need to put `templates` _after_ `encode` in your route, because responses flow up. Thus, `templates` will be able to parse and execute the plain-text response as a template, and then return it up to the `encode` handler which will then compress it into a binary format. - -If `templates` came before `encode`, then `encode` would write a compressed, binary-encoded response to `templates` which would not be able to parse the response properly. - -The correct order, then, is this: - -``` -[ - { - "handler": "encode" - }, - { - "handler": "templates" - }, - { - "handler": "file_server" - } -] -``` - -The request flows ⬇️ **DOWN** (`encode` -> `templates` -> `file_server`). - -1. First, `encode` will choose how to encode the response and wrap the response. -2. Then, `templates` will wrap the response with a buffer. -3. Finally, `file_server` will originate the content from a file. - -The response flows ⬆️ **UP** (`file_server` -> `templates` -> `encode`): - -1. First, `file_server` will write the file to the response. -2. That write will be buffered and then executed by `templates`. -3. Lastly, the write from templates will flow into `encode` which will compress the stream. - -If you think of routes in this way, it will be easy and even fun to solve the puzzle of writing correct routes. - - -##### http.handlers.cache - -A distributed HTTP cache. - -**NOTE: This module is a work-in-progress. It is not finished and is NOT ready for production use. [We need your help to finish it! Please volunteer in this issue.](https://github.com/caddyserver/caddy/issues/2820)** - -Caches only GET and HEAD requests. Honors the `Cache-Control: no-cache` header. - -Still TODO: - -- Eviction policies and API -- Use single cache per-process -- Preserve cache through config reloads -- More control over what gets cached - -```json -{ - "handler": "cache", - "self": "", - "peers": [], - "max_size": 536870912 -} -``` - -- `self`: The network address of this cache instance; required. -- `peers`: A list of network addresses of cache instances in the group. -- `max_size`: Maximum size of the cache, in bytes. Default is 512 MB. - - - -##### http.handlers.headers - -Modifies request or response headers. - -Changes to headers are applied immediately, except for the response headers when `deferred` is true or when `required` is set. In those cases, the changes are applied when the headers are written to the response. Note that deferred changes do not take effect if an error occurs later in the middleware chain. - -Properties in this module accept placeholders. - -Response header operations can be conditioned upon response status code and/or other header values. - -```json -{ - "handler": "headers", - "request": { - "set": { - "Field": ["overwrites"] - }, - "add": { - "Field": ["appends"] - }, - "delete": ["Goodbye-Field"], - "replace": { - "Field": [ - { - "search": "old", - "search_regexp": "old(e)?", - "replace": "new" - } - ] - } - }, - "response": { - "set": { - "Field": ["overwrites"] - }, - "add": { - "Field": ["appends"] - }, - "delete": ["Goodbye-Field"], - "replace": { - "Field": [ - { - "search": "old", - "search_regexp": "old(e)?", - "replace": "new" - } - ] - }, - "deferred": true, - "require": { - "status_code": [2, 301], - "headers": { - "Foo": ["bar"] - } - } - } -} -``` - -- `request`: Request headers to set, add, delete, or perform substring replacements. -- `response`: Response headers to set, add, delete, or perform substring replacements. -- `*.replace`: Performs replacements of header values. Either the `search` or `search_regexp` parameters can be specified, but not both. `search` is a simple and fast substring replacement, while `search_regexp` is a regular expression replacement. Matched values are replaced with the value of `replace`. If the field name is `*`, the replacements will happen on every accessible header field. -- `response.deferred`: If true, changes will be applied when the response headers are written instead of as the request is being processed (immediately). Not necessary if `require` is set. -- `response.require`: Defer response header operations until they are written, and only if these criteria are met. -- `response.require.status_code`: Apply response header changes if the status code matches one of these values. Can be a single digit to apply to all statuses in that class (i.e. `2` means all `2xx` status codes) or a full status code (e.g. `404`). -- `response.require.headers`: Apply response header changes if the given response headers have the given value(s). - - -##### http.handlers.rewrite - -Changes the request's URI or method. May also optionally issue a redirect for convenience if the URI is changed. - -Properties in this module accept placeholders. - -```json -{ - "handler": "rewrite", - "method": "FOO", - "uri": "/new/path?param=val", - "strip_path_prefix": "", - "strip_path_suffix": "", - "rehandle": false, - "http_redirect": 307 -} -``` - -- `method`: Changes the request's HTTP verb. -- `uri`: Changes the request's URI. -- `strip_path_prefix`: Strips the given prefix from the beginning of the URI path. -- `strip_path_suffix`: Strips the given suffix from the end of the URI path. -- `rehandle`: If true, the request will sent for rehandling after rewriting. -- `http_redirect`: If set to a 3xx HTTP status code and if the URI was rewritten (changed), the handler will issue a simple HTTP redirect to the new URI using the given status code. - -The `rehandle` and `http_redirect` properties are mutually exclusive (you cannot both rehandle and issue a redirect). - -These rewrite properties are applied to a request in this order: `method`, `uri`, `strip_path_prefix`, `strip_path_suffix`. - - -##### http.handlers.markdown - -Currently, does almost nothing: very plain/simple markdown rendering using Blackfriday. Will be configurable. But unlike Caddy 1, this already allows rendering *any* response body as Markdown, whether it be from a proxied upstream or a static file server. This needs a lot more testing and development. - -```json -{ - "handler": "markdown" -} -``` - - - -##### http.handlers.authentication - -An authentication middleware. Rejects requests with HTTP 401 if the request is not authenticated. - -```json -{ - "handler": "authentication", - "providers": { - "http_basic": { - "hash": { - "algorithm": "bcrypt", - "N": 0, - "r": 0, - "p": 0, - "key_length": 0 - }, - "accounts": [ - { - "username": "foo", - "password": "hashed_and_base64_encoded", - "salt": "base64_encoded", - } - ], - "realm": "restricted" - } - } -} -``` - -- `providers`: A set of authentication providers. If none are specified, all requests will be unauthenticated. -- `providers.http_basic`: An authentication provider using HTTP Basic Authentication. -- `providers.http_basic.hash`: The algorithm with which the passwords are hashed. Can be `bcrypt` or `scrypt`. Default is `bcrypt`. -- `providers.http_basic.hash.N`: scrypt's N parameter. If unset or 0, a safe default is used. -- `providers.http_basic.hash.r`: scrypt's r parameter. If unset or 0, a safe default is used. -- `providers.http_basic.hash.p`: scrypt's p parameter. If unset or 0, a safe default is used. -- `providers.http_basic.hash.key_length`: scrypt's key length parameter (in bytes). If unset or 0, a safe default is used. -- `providers.http_basic.accounts`: The list of accounts to authenticate. -- `providers.http_basic.accounts.username`: A user's username. -- `providers.http_basic.accounts.password`: The user's hashed password, base64-encoded. -- `providers.http_basic.accounts.salt`: The user's password salt, base64-encoded. -- `providers.http_basic.realm`: The name of the realm. Default is "restricted". - - -##### http.handlers.request_body - -Change or limit the request body. - - -```json -{ - "handler": "request_body", - "max_size": 0 -} -``` - -- `max_size`: The maximum number of bytes to allow reading from the body by a later handler. - - -##### http.handlers.encode - -Compresses responses on-the-fly. - -```json -{ - "handler": "encode", - "encodings": { - "gzip": {"level": 5}, - "zstd": {}, - "brotli": {"quality": 6} - }, - "prefer": "", - "minimum_length": 512 -} -``` - -- `encodings`: Selection of compression algorithms to choose from. The best one will be chosen based on the client's Accept-Encoding header. Available options are gzip, zstd, and brotli. Note that brotli is currently very slow and it is recommended to pre-compress static content instead. -- `prefer`: If the client has no strong preference, choose this encoding. TODO: Not yet implemented -- `minimum_length`: Only encode responses that are at least this many bytes long. - - -##### http.handlers.templates - -Interprets the response as a template body, then executes the template and writes the response to the client. [There are functions](https://github.com/caddyserver/caddy/wiki/v2:-Templates) to include other files, make sub-requests (virtual HTTP requests), render Markdown, manipulate headers, access the request fields, manipulate strings, do math, work with data structures, and more. - -```json -{ - "handler": "templates", - "include_root": "", - "mime_types": ["text/html", "text/plain", "text/markdown"], - "delimiters": ["{{", "}}"] -} -``` - -- `include_root`: The root path from which to load files. Required if template functions accessing the file system are used (such as .Include). Default is `{http.vars.root}` if set, or current working directory. -- `mime_types`: The MIME types for which to render templates. It is important to use this if the route matchers do not exclude images or other binary files. -- `delimiters`: The template action delimiters. - -See [all available template actions](https://github.com/caddyserver/caddy/wiki/v2:-Templates). - - -##### http.handlers.vars - -Sets variables associated with the request that can be used later with placeholders: `{http.vars.variable_name}` - -```json -{ - "handler": "vars", - "variable_name": "value" -} -``` - - -##### http.handlers.static_response - -Responds to the request with a static (hard-coded) response. Does not call the next handler in the chain. - -This is a great way to do HTTP redirects. - -```json -{ - "handler": "static_response", - "status_code": 307, - "headers": { - "Location": ["https://example.com/foo"] - }, - "body": "Response body", - "close": true -} -``` - -- `status_code`: The HTTP status code to respond with. Can be an integer or, if needing to use a placeholder, a string. -- `headers`: Header fields to set on the response. -- `body`: The response body. -- `close`: If true, the server will close the client's connection after writing the response. - - -##### http.handlers.file_server - -A powerful, flexible static file server. - -In general, the request URI's path will be joined to the file server's root to get the file path to serve. - -This module executes placeholders in most of its properties. It does not call the next handler in the chain. - -```json -{ - "handler": "file_server", - "root": "", - "hide": [], - "index_names": [], - "browse": { - "template_file": "" - }, - "canonical_uris": true, - "pass_thru": false -} -``` - -- `root`: The path to the root of the site. Default is `{http.vars.root}` if set, or current working directory. -- `hide`: A list of files or folders to hide; the file server will pretend as if they don't exist. Accepts globular patterns like "\*.hidden" or "/foo/*/bar". -- `index_names`: The names of files to try as index files if a folder is requested. -- `browse`: Enables browsing if a directory was requested. -- `browse.template_file`: Use this template file instead of the default browse template. -- `canonical_uris`: Use redirects to enforce trailing slash appended to URIs for directories, or to remove trailing slash from URIs for files. Default is true. -- `pass_thru`: If enabled, when a requested file is not found, invoke the next handler in the chain instead of returning a 404 error. By default, this is false (disabled). - - - -##### http.handlers.reverse_proxy - -A highly flexible and configurable multi-host reverse proxy with load balancing, health checks, and pluggable transport and security options. Does not call the next handler in the chain. - -```javascript -{ - "handler": "reverse_proxy", - "transport": { - "protocol": "http" - }, - "flush_interval": 0, - "circuit_breaker": {}, - "load_balancing": { - "selection_policy": { - "policy": "header", - "header_name": "Server-ID" - }, - "try_duration": "10s", - "try_interval": "250ms", - "retry_match": [] - }, - "health_checks": { - "active": { - "path": "/ok", - "port": 1234, - "interval": "10s", - "timeout": "2s", - "max_size": 1024, - "expect_status": 200, - "expect_body": ".*foobar.*" - "headers": {} - }, - "passive": { - "max_fails": 3, - "fail_duration": "1m", - "unhealthy_request_count": 100, - "unhealthy_status": [500, 502], - "unhealthy_latency": "5s" - } - }, - "headers": { - // same structure as 'http.handlers.headers' - } - "upstreams": [ - { - "dial": "localhost:7777" - }, - { - "dial": "localhost:7799", - "max_requests": 1000 - }, - ] -} -``` - -- `transport`: The module for round-tripping requests. See below for options. -- `flush_interval`: How frequently to flush buffered responses to the client. Accepts any duration value. Set to -1 to always flush immediately. -- `circuit_breaker`: The module for short-circuiting before backends become unhealthy. -- `load_balancing`: Configures load balancing among a group of hosts. -- `load_balancing.selection_policy`: The module to use for selecting a host from a pool. See below for options. -- `load_balancing.try_duration`: How long to try selecting available backends for each request if the next available host is down. By default, this retry is disabled. Clients may hang for this long while the load balancer tries to find an available upstream host. -- `load_balancing.try_interval`: How long to wait between selecting the next host from the pool. Default is 250ms. Only relevant when a request to an upstream host fails. Be aware that setting this to 0 with a non-zero `try_duration` can cause the CPU to spin if all backends are down and latency is very low. -- `load_balancing.retry_match`: A list of matcher sets that restricts with which requests retries are allowed. A request must match any of the given matcher sets in order to be retried if the connection to the upstream succeeded but the subsequent round-trip failed. If the connection to the upstream failed, a retry is always allowed. If unspecified, only GET requests will be allowed to be retried. Note that a retry is done with the next available host according to the load balancing policy. -- `health_checks`: Configures active and passive health checks. Active health checks run in the background on a timer, whereas passive health checks monitor proxied requests. To minimally enable active health checks, set either path or port (or both). To minimally enable passive health checks, specify at least an empty config object. -- `health_checks.active.path`: The URI path to use for health checks. -- `health_checks.active.port`: The port to use (if different from dial address) for health checks. -- `health_checks.active.interval`: How frequently to perform active health checks (default 30s). -- `health_checks.active.timeout`: How long to wait for a response from a backend before considering it unhealthy (default 10s). -- `health_checks.active.max_size`: The maximum response body to download from the backend during a health check. -- `health_checks.active.expect_status`: The HTTP status code to expect from a healthy backend. -- `health_checks.active.expect_body`: A regular expression against which to match the response body of a healthy backend. -- `health_checks.active.headers`: An object of headers (where the values are arrays of strings) to set on the request to the backend. -- `health_checks.passive.fail_duration`: How long to remember a failed request to a backend. A duration > 0 enables passive health checking. Default is 0. -- `health_checks.passive.max_fails`: The number of failed requests within the `fail_duration` window to consider a backend as "down". Must be >= 1; default is 1. Requires that `fail_duration` be > 0. -- `health_checks.passive.unhealthy_request_count`: Limits the number of simultaneous requests to a backend by marking the backend as "down" if it has this many concurrent requests or more. -- `health_checks.passive.unhealthy_status`: Count the request as failed if the response comes back with a status code. -- `health_checks.passive.unhealthy_latency`: Count the request as failed if the response takes at least this long to receive. -- `headers`: Mutates proxied request and response headers to and from the chosen upstream. Has the same structure as the [http.handlers.headers](#httphandlersheaders) module. Can use placeholders, including those set by this handler (see below). -- `upstreams`: A list of backends (upstream hosts) to add to the pool. If there are multiple backends, requests will be load-balanced between them using the configured load balancing policy. -- `upstreams.[n].dial`: The network address of the upstream in [Caddy's network address syntax](#httpserverslisten). Must represent precisely one socket (i.e. no port ranges). A valid network address either has a host and port, or is a unix socket address. Placeholders may be used to make the upstream dynamic, but be aware of the health check implications of this. -- `upstreams.[n].max_requests`: The maximum number of simultaneous requests to allow to this host. If set, overrides the global `health_checks.passive.unhealthy_request_count`. - -During proxying, this module sets the following placeholders (which can be used both within and after this handler): - -``` -{http.handlers.reverse_proxy.upstream.address} - The full address to the upstream as given in the config -{http.handlers.reverse_proxy.upstream.hostport} - The host:port of the upstream -{http.handlers.reverse_proxy.upstream.host} - The host of the upstream -{http.handlers.reverse_proxy.upstream.port} - The port of the upstream -{http.handlers.reverse_proxy.upstream.requests} - The approximate current number of requests to the upstream -{http.handlers.reverse_proxy.upstream.max_requests} - The maximum approximate number of requests allowed to the upstream -{http.handlers.reverse_proxy.upstream.fails} - The number of recent failed requests to the upstream -``` - -Transport modules: - -**HTTP**: The HTTP transport module is the default, and sane parameters are used if not explicitly configured. - -```json -{ - "protocol": "http", - "tls": { - "root_ca_pool": ["..."], - "client_certificate_file": "cert.pem", - "client_certificate_key_file": "key.pem", - "insecure_skip_verify": false, - "handshake_timeout": "2s", - "server_name": "" - }, - "keep_alive": { - "enabled": true, - "probe_interval": "500ms", - "max_idle_conns": 16, - "max_idle_conns_per_host": 4, - "idle_timeout": "2m" - }, - "compression": true, - "max_conns_per_host": 0, - "dial_timeout": "5s", - "fallback_delay": "250ms", - "response_header_timeout": "5s", - "max_response_header_size": 1024, - "expect_continue_timeout": "5s", - "read_buffer_size": 4096, - "write_buffer_size": 4096, - "versions": ["1.1", "2"] -} -``` - -- `tls`: Enables and configures TLS between the proxy and the backend. An empty object will use secure defaults. -- `tls.root_ca_pool`: A list of base64-encoded DER certificates to use as the root CA pool; these are the CA certificates that will be accepted by the proxy when connecting to a backend with TLS. -- `tls.client_certificate_file`: Path to a PEM certificate file to present to the backend. For use with TLS client authentication (mTLS, i.e. for the proxy to authenticate with the backend). -- `tls.client_certificate_key_file`: Path to the PEM private key file associated with the client certificate in `client_certificate_file`. -- `tls.insecure_skip_verify`: If true, disables certificate verification. This is insecure, dangerous, and cancels the benefits of TLS. Use only for testing/development. -- `tls.handshake_timeout`: Maximum time to establish TLS connection with the backend. -- `tls.server_name`: Custom SNI value to use in the TLS handshake; overrides implicit inferred value. -- `keep_alive`: TCP Keep-Alive configuration between the proxy and the backends. -- `keep_alive.enabled`: If false, TCP Keep-Alive will be disabled. Each request will establish a new connection. Default is true (Keep-Alive enabled). -- `keep_alive.probe_interval`: How often to probe for idleness. -- `keep_alive.max_idle_conns`: Maximum number of idle connections to keep alive across any host. -- `keep_alive.max_idle_conns_per_host`: Maximum number of idle connections to keep alive for a single host. -- `keep_alive.idle_timeout`: How long an idle connection should be kept alive without activity. -- `compression`: If false, compression to the backend will be disabled. Default true (enabled). -- `max_conns_per_host`: Maximum number of connections to allow per backend from this proxy. If this limit is reached, connections will block until an opening becomes available. -- `dial_timeout`: Maximum time allowed to dial connection to a backend. -- `fallback_delay`: Duration between dual stack fallback attempts. Not used by default. -- `response_header_timeout`: Maximum time to wait for response headers to be downloaded. -- `max_response_header_size`: Maximum size to allow for response headers. -- `expect_continue_timeout`: Maximum time to allow for HTTP 100 Continue responses. -- `read_buffer_size`: Size of the read buffer in bytes. -- `write_buffer_size`: Size of the write buffer in bytes. -- `versions`: Which HTTP versions to enable. Can be "1.1" or "2" (or both, which is default). - - -**NTLM**: This transport module is the same as `http` except it supports NTLM. It has the same structure and options as the `http` module, but it forces HTTP/1.1 and TCP Keep-Alive. When a request with an Authorization header of either "NTLM" or "Negotiate" values is received, this transport module pins the downstream connection to a new upstream connection, which preserves the context and state of the NTLM authentication. It is basically the same thing as [nginx's paid `ntlm` directive](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ntlm) (but is free in Caddy!). - - -```json -{ - "protocol": "http_ntlm" -} -``` - - -**FastCGI**: The FastCGI transport module is often used to proxy requests to PHP backends like php-fpm. - -```json -{ - "protocol": "fastcgi", - "root": "/var/www/mysite", - "split_path": ".php", - "env": {"key": "value"} -} -``` - -- `root`: Path to the root of the site, which is necessary when creating the environment variables for the request's FastCGI environment. Default is `{http.vars.root}` or current working directory. -- `split_path`: To create the FastCGI environment, the URI path will be split into two parts, with the first part ending with the first occurrence of this substring. The first part will be used as the actual resource (CGI script) name in DOCUMENT_URI, and the second piece will be set to PATH_INFO for the CGI script to use. -- `env`: Key-value pairs to add to the FastCGI environment. - -Load balancing policies: - -**round_robin**: Host is selected in turn. - -```json -{ - "policy": "round_robin" -} -``` - -**random**: Host is selected randomly. - -```json -{ - "policy": "random" -} -``` - -**random_choose**: A number of hosts (N) are randomly selected, then the host with the fewest concurrent connections is chosen from among those. N defaults to 2 and is the recommended value. Also referred to as _the power of two random choices_. - -```json -{ - "policy": "random_choose", - "choose": 2 -} -``` - -**least_conn**: Host with the fewest number of concurrent requests is selected. If tied for fewest, host is chosen randomly from among them. - -```json -{ - "policy": "least_conn" -} -``` - -**first**: First available host is selected. - -```json -{ - "policy": "first" -} -``` - -**ip_hash**: Host is selected by hashing the remote IP of the request. Each client IP will always get the same host, but specifically which host is arbitrary. - -```json -{ - "policy": "ip_hash" -} -``` - -**header**: Host is selected by hashing the value of a request header. Each request with a certain header value will get the same host, but specifically which host is arbitrary. - -```json -{ - "policy": "header", - "field": "Field-Name" -} -``` - -**uri_hash**: Host is selected by hashing the request URI. Each request with a certain URI will get the same host, but specifically which host is arbitrary. - -```json -{ - "policy": "uri_hash" -} -``` - - -##### http.handlers.subroute - -Creates a group of routes that are compiled and executed when this handler is invoked. This is useful if the evaluation of matchers needs to be deferred, like if they depend on placeholders created by other matchers or handlers that need to be evaluated first. - -This handler does not invoke the next handler in the chain. Instead, it compiles and executes the chain defined in `routes`. - -```json -{ - "handler": "subroute", - "routes": [] -} -``` - -- `routes`: The list of routes to compile and execute. - - -##### http.handlers.error - -This handler returns an error value, but does not write a response. This is useful when you want the server to act as if an error occurred; for example, to invoke your custom error handling logic. - -Since this handler does not write a response, the error information is for use by the server or other handlers to know how to handle the error. - -```json -{ - "handler": "error", - "status_code": 404, - "error": "" -} -``` - -- `status_code`: The recommended HTTP status code. Can be either an integer or a string if placeholders are needed. Optional. Default is 500. -- `error`: The error message. Optional. Default is no error message. - - - -#### http/servers/errors - -Specifies how to handle errors returned from the HTTP handlers. - -If a [handler](#httpservershandle) chain returns an error, the error along with its recommended status code are bubbled back to the HTTP server which executes a separate error route, specified using this property. The error routes work exactly like the normal routes. - -```json -{ - "routes": [] -} -``` -- `routes`: The routes to execute on error. Works just like normal HTTP routes. - -In an error route, extra placeholders are available: - -``` -{http.error.status_code} - The recommended HTTP status code -{http.error.status_text} - The status text associated with the recommended status code -{http.error.message} - The error message -{http.error.trace} - The origin of the error -{http.error.id} - A short, human-conveyable ID for the error -``` - - -#### http/servers/tls_connection_policies - -An ordered list of policies which specify how to complete TLS handshakes when establishing an HTTPS connection. The first matching policy will be used. - -Most users will not need this; it is an advanced configuration feature. - -```json -{ - "match": {}, - "alpn": [], - "cipher_suites": [], - "curves": [], - "protocol_min": [], - "protocol_max": [], - "certificate_selection": {}, - "client_authentication": { - "trusted_ca_certs": ["..."], - "trusted_leaf_certs": ["..."] - } -} -``` - -- `match`: Configures how to match this policy with a TLS ClientHello. If the policy matches, it will be used. -- `alpn`: Protocols to use for Application-Layer Protocol Negotiation (ALPN) during the handshake. -- `cipher_suites`: The list of cipher suites to support. -- `curves`: The list of elliptic curves to support. -- `protocol_min`: Minimum TLS protocol version to allow. Default is `tls1.2`. -- `protocol_max`: Maximum TLS protocol version to allow. Default is `tls1.3`. -- `certificate_selection`: Certificate selection module, which configures how to choose a certificate if more than one match the given ServerName (SNI) value. -- `client_authentication`: Enables and configures TLS client authentication. -- `client_authentication.trusted_ca_certs`: A list of base64 DER-encoded CA certificates against which to validate client certificates. Client certs which are not signed by any of these CAs will be rejected. -- `client_authentication.trusted_leaf_certs`: A list of base64 DER-encoded client leaf certs to accept. If this list is not empty, client certs which are not in this list will be rejected. - -##### tls.certificate_selection.custom - -Provides advanced certificate selection capabilities, when multiple certificates may satisfy a ClientHello's SNI value. - -All fields which are specified will be used to match certificates in the cache. If any specified field does not match the certificate, the certificate will not be chosen to complete the handshake. - -```json -{ - "policy": "custom", - "serial_number": "", - "subject_organization": "", - "public_key_algorithm": "", - "tag": "" -} -``` - -- `serial_number`: The certificate's serial number. -- `subject_organization`: The X.509 Subject.Organization field. -- `public_key_algorithm`: The kind of public key the certificate has. -- `tag`: A tag added to the certificate when it was loaded into the cache. Tags may be added in the load_files or load_pem certificate loaders. - - -#### http/servers/automatic_https - -Configures automatic HTTPS for this server. Automatic HTTPS consists of: - -- Provisioning certificates -- Renewing certificates -- Configuring TLS listeners -- Redirecting HTTP to HTTPS - -Generally you will not need to change these settings; they are for advanced use. - -```json -{ - "disable": false, - "disable_redirects": false, - "skip": [], - "skip_certificates": [] -} -``` - -- `disable`: If true, automatic HTTPS will be completely disabled. -- `disable_redirects`: If true, automatic HTTP->HTTPS redirects will be disabled, but automated certificate management will still be enabled. -- `skip`: A list of hosts (domain names) to not include in automatic HTTPS. -- `skip_certificates`: A list of hosts (domain names) to still enable automatic HTTPS for, except for managing certificates. - - -### tls - -Caddy's TLS app is an immensely powerful way to configure your server's security and privacy policies with regards to network connections. It enables you to load TLS certificates into the cache so they can be used to complete TLS handshakes. You can customize how certificates are managed or automated, and you can even configure how TLS session tickets are handled. - -Most users will not need to configure the TLS app at all, since HTTPS is automatic and on by default. - -The app is structured like this: - -```json -{ - "certificates": {}, - "automation": {}, - "session_tickets": {} -} -``` - -- `certificates`: Caches certificates in memory for quick use during TLS handshakes. Each key is the name of a certificate loader module. -- `automation`: Configures certificate automation. -- `session_tickets`: Configures session ticket ephemeral keys (STEKs) - - -#### tls/certificates - -Configures how certificates are loaded into memory. - -All loaded certificates get pooled into the same cache and may be used to complete TLS handshakes for the relevant server names (SNI). Certificates loaded manually (anything other than "automate") are not automatically managed and will have to be refreshed manually before they expire. - -There are several loader modules available. - -##### tls.certificates.load_files - -Loads certificates and their keys from files. Is a list of objects which specify how to load each cert+key pair. - -```json -"load_files": [ - { - "certificate": "", - "key": "", - "format": "pem", - "tags": [] - } -] -``` - -- `certificate`: The certificate file. -- `key`: The private key file. -- `format`: The format of the certificate and key. Values: pem -- `tags`: Optionally associate this certificate with tags ( as strings) to keep track of them. Useful for advanced certificate selection. - - -##### tls.certificates.load_folders - -Load all certificates and keys that can be found in the specified folders. Certificates and key pairs should be bundled in the same `.pem` files. This is a quick way to load a bunch of certificates at once. - -```json -"load_folders": ["/folder1", "folder2"] -``` - -- Simply specify the folder paths in the array. - -##### tls.certificates.automate - -A special case, this instructs the TLS app to automate certificates for the specified host/domain names. Certificates will be automated according to their matching automation policy. - -```json -"automate": ["example.com", "foo.example.com"] -``` - -- Specify the names to automate certificates for in the array. - - -##### tls.certificates.pem_loader - -Loads certificate and key pairs directly as presented in the config, without needing to access disk. This allows you to securely transmit private keys without having to persist them to storage; you can keep them entirely in memory. - -```json -[ - { - "certificate": "", - "key": "", - "tags": [] - } -] -``` -- `certificate`: The PEM encoding of the certificate. -- `key`: The PEM encoding of the private key. -- `tags`: Optionally associate this certificate with tags ( as strings) to keep track of them. Useful for advanced certificate selection. - - -#### tls/automation - -Configures TLS certificate automation. - -```json -{ - "policies": [], - "on_demand": { - "rate_limit": { - "interval": "", - "burst": 0 - }, - "ask": "" - }, - "renew_interval": "12h", - "ocsp_interval": "1h" -} -``` - -- `policies`: An ordered list of automation policies. -- `on_demand`: The configuration On-Demand TLS, when needed. On-Demand TLS defers certificate operations to the time they are needed, e.g. during a TLS handshake. Because it is possible to abuse this feature, usage controls are configurable. -- `on_demand.rate_limit`: Configures a rate limit for getting certificates with On-Demand TLS. -- `on_demand.rate_limit.interval`: A duration value. A certificate may be obtained `burst` times during this interval. -- `on_demand.rate_limit.burst`: How many times during an interval a certificate can be obtained. -- `on_demand.ask`: A URL which will be queried to check if Caddy should be allowed to try to get a certificate for a hostname. The name will be passed in a query string parameter like so: `?domain=example.com`. The endpoint must return a 200 OK if a certificate is allowed; anything else will cause it to be denied. Redirects are not followed. -- `renew_interval`: How often to scan loaded certificates for renewal. Default is 12 hours. Should be at least an order of magnitude shorter than certificate lifetimes. -- `ocsp_interval`: How often to scan active OCSP staples for staleness. Default is 1 hour. Should be at least an order of magnitude less than the lifetime of an OCSP response. - - -#### tls/automation/policies - -Automation policies are a very powerful way to describe how Caddy should manage certificates for certain names. - -The first matching policy will be used. Policies are matched by hostname (aka "domain name"). - -```json -{ - "hosts": [], - "management": {}, - "manage_sync": false -} -``` - -- `hosts`: The list of host names for which this policy should be applied. Omitting this field matches all hostnames. An empty list matches none. -- `management`: The module to use for management. -- `manage_sync`: If true, certificates will be initially obtained and renewed synchronously. This should only be used in interactive settings, because the first failure will cause an error that aborts startup. This makes it easier to troubleshoot problems when an administrator is present. Default is false. - -##### tls.management.acme - -This module uses ACME to manage TLS certificates. - -```json -{ - "module": "acme", - "ca": "https://acme-staging-v02.api.letsencrypt.org/directory", - "email": "", - "renew_ahead": "30d", - "key_type": "", - "acme_timeout": "", - "must_staple": false, - "challenges": { - "http": { - "disabled": false, - "alternate_port": 0 - }, - "tls-alpn": { - "disabled": false, - "alternate_port": 0 - }, - "dns": {} - }, - "on_demand": false, - "storage": {}, - "trusted_roots_pem_files": [] -} -``` -- `ca`: The ACME CA's directory endpoint. -- `email`: Your email address, so the CA can contact you if necessary. Not required but strongly recommended to provide one so you can be reached if there is a problem. -- `renew_ahead`: How long before a certificate's expiration to try renewing it. Default is 30 days. Should usually be about 1/3 of certificate lifetime, but long enough to give yourself time to troubleshoot problems before expiration. -- `key_type`: The type of key to generate for the certificate. Supported values: `rsa2048`, `rsa4096`, `p256`, `p384` -- `acme_timeout`: Duration to wait before timing out an ACME operation. -- `must_staple`: If true, the certificate will have MustStaple set. -- `challenges`: Configures the various ACME challenge types. -- `challenges.http`: Configures the ACME HTTP challenge type. -- `challenges.http.disabled`: Disables the HTTP challenge. -- `challenges.http.alternate_port`: Use this port for the HTTP challenge. Since the ACME spec requires port 80, you must use port forwarding to this alternate port. -- `challenges.tls-alpn`: Configures the ACME TLS-ALPN challenge type. -- `challenges.tls-alpn.disabled`: Disables the TLS-ALPN challenge. -- `challenges.tls-alpn.alternate_port`: Use this port for the TLS-ALPN challenge. Since the ACME spec requires port 443, you must use port forwarding to this alternate port. -- `challenges.dns`: Configures the ACME DNS challenge. Doing so disables the other challenge types. This challenge type must be configured using a DNS challenge module. -- `on_demand`: If true, certificates will be managed "on demand", that is, during TLS handshakes or when needed, as opposed to at startup. -- `storage`: Optionally configure a separate storage module associated with this manager, instead of using Caddy's global/default-configured storage. -- `trusted_roots_pem_files`: An array of CA certificates to accept when connecting to the ACME CA. - - - -#### tls/session_tickets - -Configures Caddy's TLS session tickets. By default, Caddy generates several keys and rotates them automatically on a regular basis, preserving forward secrecy in TLS 1.2. (Caddy is the only web server to do this by default.) You can customize this behavior. - -```json -{ - "disabled": false, - "max_keys": 4, - "key_source": {}, - "disable_rotation": false, - "rotation_interval": "12h" -} -``` - -- `disabled`: Disables session ticket keys. -- `max_keys`: How many keys to keep in memory. -- `key_source`: A STEK provider module that produces keys. -- `disable_rotation`: Disables STEK rotation. This is discouraged. -- `rotation_interval`: How often to rotate STEKs. - -##### tls.stek.standard - -Caddy's standard STEK provider module. It generates cyrptographically-secure keys in memory. There is nothing to configure, and it does not need to be specified in a config. - - -##### tls.stek.distributed - -A distributed STEK provider module. This allows Caddy to share STEKs among other instances in its cluster (those which use the same storage configuration), increasing performance and reducing connection latency when behind a load balancer. - -```json -{ - "provider": "distributed", - "storage": {} -} -``` - -- `storage`: The storage module to use. All instances in the cluster should use the same storage configuration. +The new site is still a work-in-progress. Please be patient if you encounter errors. Thank you for understanding. \ No newline at end of file