Initial commit

This commit is contained in:
Matthew Holt 2020-01-24 12:47:52 -07:00
commit 03b6fddeb0
No known key found for this signature in database
GPG key ID: 2A349DD577D586A5
77 changed files with 7599 additions and 0 deletions

View file

@ -0,0 +1,354 @@
---
title: Caddyfile Concepts
---
# Caddyfile Concepts
This document will help you learn about the HTTP Caddyfile in detail.
1. [Structure](#structure)
2. [Addresses](#addresses)
3. [Matchers](#matchers)
4. [Placeholders](#placeholders)
5. [Snippets](#snippets)
6. [Comments](#comments)
7. [Environment variables](#environment-variables)
8. [Global options](#global-options)
## Structure
The Caddyfile's structure can be described visually:
![Caddyfile structure](/resources/images/caddyfile-visual.png)
Key points:
- An optional **global options block** can be the very first thing in the file.
- Otherwise, the first line of the Caddyfile is **always** the address(es) of the site to serve.
- All directives **must** go in a site block. There is no global scope or inheritence across site blocks.
- If there is **only one site block**, its curly braces `{ }` are optional.
A Caddyfile consists of at least one or more site blocks, which always starts with one or more [addresses](#addresses) for the site. Any directives appearing before the address will be confusing to the parser.
### Blocks
Opening and closing a **block** is done with curly braces:
```
... {
...
}
```
- The open curly brace `{` must be at the end of its line.
- The close curly brace `}` must be on its own line.
When there is only one site block, the curly braces (and indentation) are optional. This is for convenience to quickly define a single site, for example, this:
```
localhost
reverse_proxy /api/* localhost:9001
file_server
```
is equivalent to:
```
localhost {
reverse_proxy /api/* localhost:9001
file_server
}
```
when you have only a single site block; it's a matter of preference.
To configure multiple sites with the same Caddyfile, you **must** use curly braces around each one to separate their configurations:
```
example1.com {
root * /www/example.com
file_server
}
example2.com {
reverse_proxy localhost:9000
}
```
### Directives
**Directives** are keywords which customize how the site is served. For example, a complete file server config might look like this:
```
localhost
file_server
```
Or a reverse proxy:
```
localhost
reverse_proxy localhost:9000
```
In these examples, `file_server` and `reverse_proxy` are directives. Directives are the first word on a line in a site block.
In the second example, `localhost:9000` is an **argument** because it appears on the same line after the directive.
**Subdirectives** can appear in directive blocks:
```
localhost
reverse_proxy localhost:9000 localhost:9001 {
lb_policy first
}
```
Here, `lb_policy` is a subdirective to `reverse_proxy` (it sets the load balancing policy to use between backends).
## Addresses
An address always appears at the top of the site block, and is usually the first thing in the Caddyfile.
These are examples of valid addresses:
<aside class="tip">
<a href="/docs/automatic-https">Automatic HTTPS</a> is enabled if your site's address contains a real-looking domain name. This behavior is purely implicit, however, so it never overrides any explicit configuration. For example, if the site's address is <code>http://example.com</code>, auto-HTTPS will not activate because the scheme is http.
</aside>
- `localhost`
- `example.com`
- `:443`
- `http://example.com`
- `localhost:8080`
- `127.0.0.1`
- `[::1]:2015`
- `example.com/foo`
From the address, Caddy can potentially infer the scheme, host, port, and path prefix of your site. The default port is 2015 unless [automatic HTTPS](/docs/automatic-https#activation) is activated, which changes it to the HTTPS port.
If you specify a hostname, only requests with a matching Host header will be honored. In other words, if the site address is `localhost`, then Caddy will not match requests to `127.0.0.1`.
If multiple sites share the same definition, you can list all of them:
```
localhost:8080, example.com, www.site.com
```
or
```
localhost:8080,
example.com,
www.site.com
```
Notice how the commas indicate the continuation of addresses.
An address must be unique; you cannot specify the same address more than once.
## Matchers
By default, a directive that injects an HTTP handler applies to all requests (unless otherwise documented).
**Request matchers** can be used to classify requests by a given criteria. This concept originates in the [underlying JSON](/docs/json/apps/http/servers/routes/match/) structure, and it's important to know how to use them in the Caddyfile. With matchers, you can specify exactly which requests a directive applies to.
To limit a directive's scope, use a **matcher token** immediately after the directive. It can be one of these forms:
1. **`*`** to match all requests (wildcard; default).
2. **`/path`** start with a forward slash to match a request path.
3. **`@name`** to specify a _named matcher_.
Matcher tokens are usually optional. If a matcher token is omitted, it is the same as a wildcard matcher (`*`).
### Wildcard matcher
The wildcard matcher `*` matches all requests, and is only needed if a matcher token is required. For example, if the first argument you want to give a directive also happens to be a path, it would look exactly like a path matcher! So you can use a wildcard matcher to disambiguate, for example:
```
root * /home/www/mysite
```
Otherwise, this matcher is not often used. It is convenient to omit it when possible; just a matter of preference.
### Path matcher
Because matching by path is so common, a single path matcher can be inlined, like so:
```
redir /old-article.html /new-article.html
```
Path matcher tokens must start with a forward slash `/`.
Note that [path matching](/docs/json/apps/http/servers/routes/match/path/) is an exact match by default; you must append a `*` for a fast prefix match.
### Named matcher
Defining a matcher with a unique name gives you more flexibility:
```
@name {
...
}
```
Then you can use the matcher like so: `@name`
For example:
```
@websockets {
header_regexp Connection Upgrade
header Upgrade websocket
}
reverse_proxy @websockets localhost:6001
```
This example only proxies requests that have a header field named "Connection" containing the word "Upgrade", and another header named "Upgrade" with a value of "websocket".
The following matcher modules are built-in:
```
@name {
file {
root <paths>
try_files <files>
try_policy first_exist|smallest_size|largest_size|most_recent_modified
}
header <field> <value>
header_regexp <field> <regexp>
host <hosts...>
method <methods...>
not {
<any other matchers>
}
path <paths...>
path_regexp [<name>] <regexp>
protocol http|https|grpc
query <key>=<val>...
remote_ip <ranges...>
}
```
### Matcher examples
This directive applies to all HTTP requests:
```
reverse_proxy localhost:9000
```
As does this:
```
reverse_proxy * localhost:9000
```
But this directive applies only to requests having a path starting with `/api/`:
```
reverse_proxy /api/* localhost:9000
```
To match on anything other than a path, define a **named matcher** and refer to it using `@name`:
```
@post {
method POST
}
reverse_proxy @post localhost:9000
```
## Placeholders
You can use any [Caddy placeholders](/docs/conventions#placeholders) in the Caddyfile, but for convenience you can also use some equivalent shorthand ones:
| Shorthand | Replaces |
|--------------|---------------------------------|
| `{dir}` | `{http.request.uri.path.dir}` |
| `{file}` | `{http.request.uri.path.file}` |
| `{host}` | `{http.request.host}` |
| `{hostport}` | `{http.request.hostport}` |
| `{method}` | `{http.request.method}` |
| `{path}` | `{http.request.uri.path}` |
| `{query}` | `{http.request.uri.query}` |
| `{scheme}` | `{http.request.scheme}` |
| `{uri}` | `{http.request.uri}` |
## Snippets
You can define special blocks called snippets by giving them a name surrounded in parentheses:
```
(redirect) {
@http {
scheme http
}
redir @http https://{host}{uri}
}
```
And then you can reuse this anywhere you need:
```
import redirect
```
The `import` directive can also be used to include other files in its place. As a special case, it can appear almost anywhere within the Caddyfile.
## Comments
Comments start with `#` and proceed until the end of the line:
```
# Comments can start a line
directive # or go at the end
```
## Environment variables
If your configuration relies on environment variables, you can use them in the Caddyfile:
```
{$SITE_ADDRESS}
```
Environment variables in this form are substituted before parsing begins, so they can expand to empty values, partial tokens, complete tokens, or even multiple tokens and lines.
If you want to defer the substitution of an environment variable until runtime, you can use the [standard `{env.*}` placeholders](/docs/conventions#placeholders).
## Global options
A Caddyfile may optionally start with a special block that has no keys, called a [global options block](/docs/caddyfile/options):
```
{
...
}
```
If present, it must be the very first block in the config.
It is used to set options that apply globally, or not to any one site in particular. Inside, only global options can be set; you cannot use regular site directives in them.
[Learn more](/docs/caddyfile/options) about the global options block.

View file

@ -0,0 +1,93 @@
---
title: Caddyfile Directives
---
# Caddyfile Directives
The following directives come standard with Caddy, and can be used in the HTTP Caddyfile:
Directive | Description
----------|------------
**[basicauth](/docs/caddyfile/directives/basicauth)** | Enforces HTTP Basic Authentication
**[bind](/docs/caddyfile/directives/bind)** | Customize the server's socket address
**[encode](/docs/caddyfile/directives/encode)** | Encodes (usually compresses) responses
**[file_server](/docs/caddyfile/directives/file_server)** | Serve files from disk
**[handle](/docs/caddyfile/directives/handle)** | A mutually-exclusive group of directives
**[header](/docs/caddyfile/directives/header)** | Sets or removes response headers
**[php_fastcgi](/docs/caddyfile/directives/php_fastcgi)** | Serve PHP sites over FastCGI
**[redir](/docs/caddyfile/directives/redir)** | Issues an HTTP redirect to the client
**[request_header](/docs/caddyfile/directives/request_header)** | Manipulates request headers
**[respond](/docs/caddyfile/directives/respond)** | Writes a hard-coded response to the client
**[reverse_proxy](/docs/caddyfile/directives/reverse_proxy)** | A powerful and extensible reverse proxy
**[rewrite](/docs/caddyfile/directives/rewrite)** | Rewrites the request internally
**[root](/docs/caddyfile/directives/root)** | Set the path to the site root
**[route](/docs/caddyfile/directives/route)** | A group of directives treated literally as single unit
**[strip_prefix](/docs/caddyfile/directives/strip_prefix)** | Rewrite that strips path prefix
**[strip_suffix](/docs/caddyfile/directives/strip_suffix)** | Rewrite that strips path suffix
**[templates](/docs/caddyfile/directives/templates)** | Execute templates on the response
**[tls](/docs/caddyfile/directives/tls)** | Customize TLS settings
**[try_files](/docs/caddyfile/directives/try_files)** | Rewrite that depends on file existence
**[uri_replace](/docs/caddyfile/directives/uri_replace)** | Rewrite that replaces substrings in URI
## Syntax
The syntax of each directive will look something like this:
```
directive [<matcher>] <args...> {
subdirective [<args...>]
}
```
The `<carets>` indicate tokens to be substituted by actual values.
The`[brackets]` indicate optional parameters.
The ellipses `...` indicates a continuation, i.e. one or more parameters or lines.
Subdirectives are always optional unless documented otherwise, even though they don't appear in `[brackets]`.
### Matchers
Most directives accept [matcher tokens](/docs/caddyfile/concepts#matchers), and they are usually optional. You will often see this in a directive's syntax description:
```
[<matcher>]
```
When you see this in the syntax of a directive, it means a matcher token. Because this is the same with most directives, it will not be described on every page; this reduces duplication. Instead, refer to the centralized [matcher documentation](/docs/caddyfile/concepts#matchers).
## Directive order
Many directives manipulate the HTTP handler chain. The order in which those directives are evaluated matters, so a default ordering is hard-coded into Caddy:
```
root
redir
rewrite
strip_prefix
strip_suffix
uri_replace
try_files
basicauth
headers
request_header
encode
templates
handle
route
respond
reverse_proxy
php_fastcgi
file_server
```
You can override or customize this ordering by using the [`order` global option](/docs/caddyfile/options) or the [`route` directive](/docs/caddyfile/directives/route).

View file

@ -0,0 +1,40 @@
---
title: basicauth (Caddyfile directive)
---
# basicauth
Enables HTTP Basic Authentication, which can be used to protect directories and files with a username and hashed password.
**Note that basic auth is not secure over plain HTTP.** Use discretion when deciding what to protect with HTTP Basic Authentication.
When a user requests a resource that is protected, the browser will prompt the user for a username and password if they have not already supplied one. If the proper credentials are present in the Authorization header, the server will grant access to the resource. If the header is missing or the credentials are incorrect, the server will respond with HTTP 401 Unauthorized.
Caddy configuration does not accept plaintext passwords; you MUST hash them before putting them into the configuration. The [`caddy hash-password`](/docs/command-line#caddy-hash-password) command can help with this.
## Syntax
```
basicauth [<matcher>] [<hash_algorithm>] {
<username> <hashed_password_base64> [<salt_base64>]
...
}
```
- **&lt;hash_algorithm&gt;** is the name of the password hashing algorithm (or KDF) used for the hashes in this configuration. Can be `bcrypt` (default) or `scrypt`.
- **&lt;username&gt;** is a username or user ID.
- **&lt;hashed_password_base64&gt;** is the base-64 encoding of the hashed password.
- **&lt;salt_base64&gt;** is the base-64 encoding of the password salt, if an external site is required.
## Examples
Protect all resources in /secret so only Bob can access them with the password "hiccup":
```
basicauth /secret/* {
Bob JDJhJDEwJEVCNmdaNEg2Ti5iejRMYkF3MFZhZ3VtV3E1SzBWZEZ5Q3VWc0tzOEJwZE9TaFlZdEVkZDhX
}
```

View file

@ -0,0 +1,33 @@
---
title: bind (Caddyfile directive)
---
# bind
bind overrides the interface to which the server's socket should bind. Normally, the listener binds to the empty (wildcard) interface. However, you may force the listener to bind to another hostname or IP instead. (This directive accepts only a host, not a port.)
Note that binding sites inconsistently may result in unintended consequences. For example, if two sites on the same port resolve to 127.0.0.1 and only one of those sites is configured with `bind 127.0.0.1`, then only one site will be accessible since the other will bind to the port without a specific host; the OS will choose the more specific matching socket. (Virtual hosts are not shared across different listeners.)
## Syntax
```
bind <hosts...>
```
- **&lt;hosts...&gt;** is the list of host interfaces to bind which to bind the listener.
## Examples
To make a socket accessible only on the current machine, bind to the loopback interface (localhost):
```
bind 127.0.0.1
```
To include IPv6:
```
bind 127.0.0.1 ::1
```

View file

@ -0,0 +1,38 @@
---
title: encode (Caddyfile directive)
---
# encode
Encodes responses using the configured encoding(s). A typical use for encoding is compression.
## Syntax
```
encode [<matcher>] <formats...> {
gzip [<level>]
zstd
brotli [<quality>]
}
```
- **&lt;formats...&gt;** is the list of encoding formats to enable.
- **gzip** enables Gzip compression, optionally at the specified level.
- **zstd** enables Zstandard compression.
- **brotli** enables on-the-fly Brotli compression, but be aware that Brotli compression is not designed to be fast and the current Go implementation is not efficient. Use only for testing and development. _We might remove this option in the future. Do not use in production. Not subject to compatibility promises._ To use brotli compression, pre-compress your assets and serve those instead.
## Examples
Enable Gzip compression:
```
encode gzip
```
Enable Zstandard and Gzip compression:
```
encode zstd gzip
```

View file

@ -0,0 +1,45 @@
---
title: file_server (Caddyfile directive)
---
# file_server
A static file server. It works by appending the request's URI path to the [site's root path](/docs/caddyfile/directives/root).
## Syntax
```
file_server [<matcher>] [browse] {
root <path>
hide <files...>
index <files...>
browse [<template_file>]
}
```
- **browse** enables file listings for requests to directories that do not have an index file.
- **root** sets the path to the site root for just this file server instance, overriding any other. Default: `{http.vars.root}` or the current working directory.
- **hide** is a list of files to hide; if requested, the file server will pretend they do not exist. The active configuration file will be added by default.
- **<template_file>** is an optional custom template file to use for directory listings.
## Examples
A static file server out of the current directory:
```
file_server
```
With file listings enabled:
```
file_server browse
```
Only serve static files out of the `/static` folder:
```
file_server /static/*
```

View file

@ -0,0 +1,37 @@
---
title: handle (Caddyfile directive)
---
# handle
Evaluates a group of directives mutually exclusively from other `handle` blocks at the same level of nesting.
The `handle` directive is kind of similar to the `location` directive from nginx config: the first matching `handle` block will be evaluated. Handle blocks can be nested if needed. Only HTTP handler directives can be used inside handle blocks.
## Syntax
```
handle [<matcher>] {
<directives...>
}
```
- **<directives...>** is a list of HTTP handler directives or directive blocks, one per line, just like would be used outside of a handle block.
## Utility
If you prefer crafting HTTP handler logic in a more inheritence-based way like nginx location blocks, you may prefer the use of `handle` blocks rather than defining mutually-exclusive matchers for your directives. If inheritence is a desired characteristic of your HTTP handler configurations, then the `handle` directive may suit you well.
## Examples
Handle requests in `/foo/` by the static file server, and send all other requests to the reverse proxy:
```
handle /foo/* {
file_server
}
handle {
reverse_proxy 127.0.0.1:8080
}
```

View file

@ -0,0 +1,64 @@
---
title: header (Caddyfile directive)
---
# header
Manipulates HTTP header fields on the response. It can set, add, and delete header values, or perform replacements using regular expressions.
## Syntax
```
header [<matcher>] [[+|-]<field> [<value>|<find>] [<replace>]] {
<field> <find> <replace>
[+]<field> <value>
-<field>
}
```
- **&lt;field&gt;** is the name of the header field. By default, will overwrite any existing field of the same name. Prefix with `+` to add the field instead of replace, or prefix with `-` to remove the field.
- **&lt;value&gt;** is the header field value, if adding or setting a field.
- **&lt;find&gt;** is the substring or regular expression to search for.
- **&lt;replace&gt;** is the replacement value; required if performing a search-and-replace.
For multiple header manipulations, you can open a block and specify one manipulation per line in the same way.
## Examples
Set a custom header field on all requests:
```
header Custom-Header "My value"
```
Strip the "Hidden" header field:
```
header -Hidden
```
Replace `http://` with `https://` in any Location header:
```
header Location http:// https://
```
Set security headers on all pages: (**WARNING:** only use if you understand the implications!)
```
header {
# enable HSTS
Strict-Transport-Security max-age=31536000;
# disable clients from sniffing the media type
X-Content-Type-Options nosniff
# clickjacking protection
X-Frame-Options DENY
# keep referrer data off of HTTP connections
Referrer-Policy no-referrer-when-downgrade
}
```

View file

@ -0,0 +1,69 @@
---
title: php_fastcgi (Caddyfile directive)
---
# php_fastcgi
An opinionated directive that proxies requests to a PHP FastCGI server such as php-fpm.
Caddy's [reverse_proxy](/docs/caddyfile/directives/reverse_proxy) is capable of serving any FastCGI application, but this directive is tailored specifically for PHP apps. This directive is actually just a convenient way to use a longer, more common configuration (below).
It expects that any `index.php` at the site root acts as a router. If that is not desirable, either perform your own URI rewrite or use something like the [expanded form](#expanded-form) below and customize it to your needs.
## Syntax
```
php_fastcgi [<matcher>] <php-fpm_gateway>
```
- **<php-fpm_gateway>** is the address of the FastCGI server.
Since this directive is an opinionated wrapper over a reverse proxy, you can open a block and use any of reverse_proxy's subdirectives to customize it.
## Expanded form
The `php_fastcgi` directive is the same as the following configuration:
```
# Add trailing slash for directory requests
@canonicalPath {
file {
try_files {path}/index.php
}
not {
path */
}
}
redir @canonicalPath {path}/ 308
# If the requested file does not exist, try index files
try_files {path} {path}/index.php index.php
# Proxy PHP files to the FastCGI responder
@phpFiles {
path *.php
}
reverse_proxy @phpFiles <php-fpm_gateway> {
transport fastcgi {
split .php
}
}
```
Most modern PHP apps work well with this preset. If yours does not, feel free to borrow from this and customize it as needed instead of using the `php_fastcgi` shortcut.
## Examples
Proxy all PHP requests to a FastCGI responder listening at 127.0.0.1:9000:
```
php_fastcgi 127.0.0.1:9000
```
Same, but only for requests under `/blog/`:
```
php_fastcgi /blog/* 127.0.0.1:9000
```

View file

@ -0,0 +1,45 @@
---
title: redir (Caddyfile directive)
---
# redir
Issues an HTTP redirect to the client.
This directive implies that a matched request is to be rejected. It is ordered very early in the handler chain (before [`rewrite`](/docs/caddyfile/directives/rewrite)).
## Syntax
```
redir [<matcher>] <to> [<code>]
```
- **&lt;to&gt;** is the target location. Becomes the response's Location header.
- **&lt;code&gt;** is the HTTP status code to use for the redirect. Can be:
- A positive integer in the 3xx range
- `temporary` for a temporary redirect (302; default)
- `permanent` for a permanent redirect (301)
- `html` to use an HTML document to perform the redirect (useful for redirecting browsers but not API clients)
## Examples
Redirect all requests to `https://example.com`:
```
redir https://example.com
```
Same, but preserve the existing URI:
```
redir https://example.com{uri}
```
Same, but permanent:
```
redir https://example.com{uri} permanent
```

View file

@ -0,0 +1,28 @@
---
title: request_header (Caddyfile directive)
---
# request_header
Manipulates HTTP header fields on the request. It can set, add, and delete header values, or perform replacements using regular expressions.
## Syntax
```
request_header [<matcher>] [[+|-]<field> [<value>|<find>] [<replace>]]
```
- **&lt;field&gt;** is the name of the header field. By default, will overwrite any existing field of the same name. Prefix with `+` to add the field instead of replace, or prefix with `-` to remove the field.
- **&lt;value&gt;** is the header field value, if adding or setting a field.
- **&lt;find&gt;** is the substring or regular expression to search for.
- **&lt;replace&gt;** is the replacement value; required if performing a search-and-replace.
## Examples
Remove the Referer header from the request:
```
request_header -Referer
```

View file

@ -0,0 +1,47 @@
---
title: respond (Caddyfile directive)
---
# respond
Writes a hard-coded/static response to the client.
## Syntax
```
respond [<matcher>] <status>|<body> [<status>] {
body <text>
close
}
```
- **&lt;status&gt;** is the HTTP status code to write. Default 200.
- **&lt;body&gt;** is the response body to write.
- **body** is an alternate way to provide a body; convenient if it is multiple lines.
- **close** will close the client's connection to the server after writing the response.
To clarify, the first non-matcher argument can be either a 3-digit status code or a response body string. If it is a body, the next argument can be the status code.
## Examples
Write a 200 status with an empty body to all health checks:
```
respond /health-check 200
```
Write a simple response body to all requests:
```
respond "Hello, world!"
```
Write an error response and close the connection:
```
respond /secret/* "Access denied" 403 {
close
}
```

View file

@ -0,0 +1,165 @@
---
title: reverse_proxy (Caddyfile directive)
---
# reverse_proxy
Proxies requests to one or more backends with configurable transport, load balancing, health checking, header manipulation, and buffering options.
## Syntax
```
reverse_proxy [<matcher>] [<upstreams...>] {
# backends
to <upstreams...>
...
# load balancing
lb_policy <name> [<options...>]
lb_try_duration <duration>
lb_try_interval <interval>
# active health checking
health_path <path>
health_port <port>
health_interval <interval>
health_timeout <duration>
health_status <status>
health_body <regexp>
# passive health checking
fail_duration <duration>
max_fails <num>
unhealthy_status <status>
unhealthy_latency <duration>
unhealthy_request_count <num>
# streaming
flush_interval <duration>
# header manipulation
header_up [+|-]<field> [<value|regexp> [<replacement>]]
header_down [+|-]<field> [<value|regexp> [<replacement>]]
# round trip
transport <name> {
...
}
}
```
- **&lt;upstreams...&gt;** is a list of upstreams (backends) to which to proxy.
- **to** is an alternate way to specify the list of upstreams, one (or more) per line.
**Load balancing** is used whenever more than one upstream is defined.
- **lb_policy** is the name of the load balancing policy, along with any options. Default: `random`. Can be:
- `first` - choose first available upstream
- `header` - map request header to sticky upstream
- `ip_hash` - map client IP to sticky upstream
- `least_conn` - choose upstream with fewest number of current requests
- `random` - randomly choose an upstream
- `random_choose <n>` - selects two or more upstreams randomly, then chooses one with least load (`n` is usually 2)
- `round_robin` - iterate each upstream in turn
- `uri_hash` - map URI to sticky upstream
- **lb_try_duration** is a [duration value](/docs/conventions#durations) that defines how long to try selecting available backends for each request if the next available host is down. By default, this retry is disabled. Clients will wait for up to this long while the load balancer tries to find an available upstream host.
- **lb_try_interval** is a [duration value](/docs/conventions#durations) that defines 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 `lb_try_duration` can cause the CPU to spin if all backends are down and latency is very low.
**Active health checks** perform health checking in the background on a timer:
- **health_path** is the URI path for active health checks.
- **health_port** is the port to use for active health checks, if different from the upstream's port.
- **health_interval** is a [duration value](/docs/conventions#durations) that defines how often to perform active health checks.
- **health_timeout** is a [duration value](/docs/conventions#durations) that defines how long to wait for a reply before marking the backend as down.
- **health_status** is the HTTP status code to expect from a healthy backend. Can be a 3-digit status code or a status code class ending in `xx`, for example: `200` (default) or `2xx`.
- **health_body** is a substring or regular expression to match on the response body of an active health check. If the backend does not return a matching body, it will be marked as down.
**Passive health checks** happen inline with actual proxied requests:
- **fail_duration** is a [duration value](/docs/conventions#durations) that defines how long to remember a failed request. A duration > 0 enables passive health checking.
- **max_fails** is the maximum number of failed requests within fail_timeout that are needed before considering a backend to be down; must be >= 1; default is 1.
- **unhealthy_status** counts a request as failed if the response comes back with one of these status codes. Can be a 3-digit status code or a status code class ending in `xx`, for example: `404` or `5xx`.
- **unhealthy_latency** is a [duration value](/docs/conventions#durations) that counts a request as failed if it takes this long to get a response.
- **unhealthy_request_count** is the permissible number of simultaneous requests to a backend before marking it as down.
The proxy **buffers responses** by default for wire efficiency:
- **flush_interval** is a [duration value](/docs/conventions#durations) that defines how often Caddy should flush the buffered response body to the client. Set to -1 to disable buffering.
It can also **manipulate headers** between itself and the backend:
- **header_up** Sets, adds, removes, or performs a replacement in a request header going upstream to the backend.
- **header_down** Sets, adds, removes, or performs a replacement in a response header coming downstream from the backend.
Caddy's proxy **transport** is pluggable:
- **transport** defines how to communicate with the backend. Default is `http`.
The `http` and `http_ntlm` transports can look like this:
```
transport http {
read_buffer <size>
write_buffer <size>
dial_timeout <duration>
tls
tls_client_auth <cert_file> <key_file>
tls_insecure_skip_verify
tls_timeout <duration>
tls_trusted_ca_certs <pem_files...>
keepalive [off|<duration>]
keepalive_idle_conns <max_count>
}
```
The `http_ntlm` transport is identical to the `http` transport, but the HTTP version is always 1.1, and Keep-Alive is always disabled.
- **read_buffer** is the size of the read buffer in bytes.
- **write_buffer** is the size of the write buffer in bytes.
- **dial_timeout** is how long to wait when connecting to the upstream socket.
- **tls** uses HTTPS with the backend.
- **tls_client_auth** specifies a certificate and key file to present for TLS client authentication with the backend.
- **tls_insecure_skip_verify** turns off security. _Do not use in production._
- **tls_timeout** is a [duration value](/docs/conventions#durations) that specifies how long to wait for the TLS handshake to complete.
- **tls_trusted_ca_certs** is a list of PEM files that specify CA public keys to trust when connecting to the backend.
- **keepalive** is either `off` or a [duration value](/docs/conventions#durations) that specifies how long to keep connections open.
- **keepalive_idle_conns** defines the maximum number of connections to keep alive.
The `fastcgi` transport can look like this:
```
transport fastcgi {
root <path>
split <at>
env <key> <value>
}
```
- **root** is the root of the site. Default: `{http.vars.root}` or current working directory.
- **split** is where to split the path to get PATH_INFO at the end of the URI.
- **env** sets custom environment variables.
## Examples
Reverse proxy all requests to a local backend:
```
reverse_proxy localhost:9005
```
Load-balance all requests between 3 backends:
```
reverse_proxy node1:80 node2:80 node3:80
```
Same, but only requests within `/api`, and with header affinity:
```
reverse_proxy /api/* node1:80 node2:80 node3:80 {
lb_policy header X-My-Header
}
```

View file

@ -0,0 +1,55 @@
---
title: rewrite (Caddyfile directive)
---
# rewrite
Rewrites the request internally. A rewrite changes some or all of the request URI.
The `rewrite` directive implies the intent to accept the request, but with modifications. It is mutually exclusive to other `rewrite` directives in the same block, so it is safe to define rewrites that would otherwise cascade into each other; only the first matching rewrite will be executed.
## Syntax
```
rewrite [<matcher>] <to>
```
- **<to>** is the URI to set on the request. Only designated parts will be replaced. The URI path is any substring that comes before `?`. If `?` is omitted, then the whole token is considered to be the path.
## Examples
Rewrite all requests to `foo.html`, leaving any query string unchanged:
```
rewrite * /foo.html
```
Replace the query string on API requests with `a=b`, leaving the path unchanged:
```
rewrite /api/* ?a=b
```
Preserve the existing query string and add a key-value pair:
```
rewrite /api/* ?{query}&a=b
```
Change both the path and query string, preserving the original query string while adding the original path as the `p` parameter:
```
rewrite * /index.php?{query}&p={path}
```
## Similar directives
There are other directives that perform rewrites, but imply a different intent or do the rewrite without a complete replacement of the URI:
- [`strip_prefix`](/docs/caddyfile/directives/strip_prefix) strips a prefix from the request path.
- [`strip_suffix`](/docs/caddyfile/directives/strip_suffix) strips a suffix from the request path.
- [`uri_replace`](/docs/caddyfile/directives/uri_replace) performs a substring replacement on the request path.
- [`try_files`](/docs/caddyfile/directives/try_files) rewrites the request based on the existence of files.

View file

@ -0,0 +1,44 @@
---
title: root (Caddyfile directive)
---
# root
Sets the root path of the site, used by various matchers and directives that access the file system. If unset, the default site root is the current working directory.
Specifically, this directive sets the `{http.vars.root}` placeholder.
## Syntax
```
root [<matcher>] <path>
```
- **&lt;path&gt;** is the path to use for the site root.
Note that a matcher token is usually required since the first argument is a path, which could look like a path matcher.
## Examples
Set the site root to `/home/user/public_html` for all requests:
```
root * /home/user/public_html
```
(A [wildcard matcher](/docs/caddyfile/concepts#wildcard-matcher) is required in this case because the first argument is ambiguous with a [path matcher](/docs/caddyfile/concepts#path-matcher).)
Set the site root to `public_html` (relative to current working directory) for all requests:
```
root public_html
```
(No matcher token is required here because our site root is a relative path, so it does not start with a forward slash and thus is not ambiguous.)
Set the site root only for requests in `/foo`:
```
root /foo/* /home/user/public_html/foo
```

View file

@ -0,0 +1,76 @@
---
title: route (Caddyfile directive)
---
# route
Evaluates a group of directives literally and as a single unit.
Directives contained in a route block will not be reordered internally. Only HTTP handler directives (directives which add handlers or middleware to the chain) can be used in a route block.
This directive is a special case in that its subdirectives are also regular directives.
## Syntax
```
route [<matcher>] {
<directives...>
}
```
- **<directives...>** is a list of directives or directive blocks, one per line, just like outside of a route block; except these directives will not be reordered. Only HTTP handler directives can be used.
## Utility
The `route` directive is helpful in certain advanced use cases or edge cases to take absolute control over parts of the HTTP handler chain.
Because the order of HTTP middleware evaluation is significant, the Caddyfile will normally reorder directives after parsing to make the Caddyfile easier to use; you don't have to worry about what order you type things.
While the built-in order is compatible with most sites, sometimes you need to take manual control over the order, either for the whole site or just a part of it. That's what the `route` directive is for.
To illustrate, consider the case of two terminating handlers: `redir` and `file_server`. Both write the response to the client and do not call the next handler in the chain, so only one of these will be executed for a certain request. Which comes first? Normally, `redir` is executed before `file_server` because usually you would want to issue a redirect only in specific cases and serve files in the general case.
However, there may be occasions where the second directive (`redir`) has a more specific matcher than the second (`file_server`). In other words, you want to redirect in the general case, and serve only a specific file.
So you might try a Caddyfile like this (but this will not work as expected!):
```
example.com
file_server /specific.html
redir https://anothersite.com{uri}
```
The problem is that, internally, `redir` comes before `file_server`, but in this case the matcher for `redir` is a superset of the matcher for `file_server` (`*` is a superset of `/specific.html`).
Fortunately, the solution is easy: just wrap those two directives in a `route` block:
```
example.com
route {
file_server /specific.html
redir https://anothersite.com{uri}
}
```
<aside class="tip">
Another way to do this is to make the two matchers mutually exclusive, but this can quickly become complex if there are more than one or two conditions. With the <code>route</code> directive, the mutual exclusivity of the two handlers is implicit because they are both terminal handlers.
</aside>
And now `file_server` will be chained in before `redir` because the order is taken literally.
## Examples
Strip `api/` prefix from request path just before proxying all API requests to a backend:
```
route /api/* {
strip_prefix api/
reverse_proxy localhost:9000
}
```

View file

@ -0,0 +1,31 @@
---
title: strip_prefix (Caddyfile directive)
---
# strip_prefix
Strips a given prefix from the request URI's path. If a matched request does not have the given path prefix, this directive is a no-op.
## Syntax
```
strip_prefix [<matcher>] <prefix>
```
- **&lt;prefix&gt;** is the prefix to strip from the request path. This value may omit the leading forward slash `/` and it will be assumed.
## Examples
Strip `api/` from the beginning of all request paths:
```
strip_prefix api/
```
An alternate way to describe the same thing, using a matcher:
```
strip_prefix /api/* /api
```

View file

@ -0,0 +1,25 @@
---
title: strip_suffix (Caddyfile directive)
---
# strip_suffix
Strips a given suffix from the request URI's path. If a matched request does not have the given path suffix, this directive is a no-op.
## Syntax
```
strip_suffix [<matcher>] <suffix>
```
- **&lt;suffix&gt;** is the suffix to strip from the request path.
## Examples
Strip `.html` from the end of all request paths:
```
strip_suffix .html
```

View file

@ -0,0 +1,32 @@
---
title: templates (Caddyfile directive)
---
# templates
Executes the response body as a [template](/docs/json/apps/http/servers/errors/routes/handle/templates/) document. Templates provide functional primitives for making simple dynamic pages. Features include HTTP subrequests, HTML file includes, Markdown rendering, JSON parsing, basic data structures, randomness, time, and more.
## Syntax
```
templates [<matcher>] {
mime <types...>
between <open_delim> <close_delim>
root <path>
}
```
- **mime** are the MIME types the templates middleware will act on; any responses that do not have a qualifying Content-Type will not be evaluated as templates. Default: `text/html text/plain`.
- **between** are the opening and closing delimiters for template actions. Default: `{{printf "{{ }}"}}`. You can change them if they interfere with the rest of your document.
- **root** is the site root, when using functions that access the file system.
## Examples
Enable templates on all requests:
```
templates
```

View file

@ -0,0 +1,68 @@
---
title: tls (Caddyfile directive)
---
# tls
Configures TLS for the site.
**Caddy's default TLS settings are secure. Only change these settings if you have a good reason and understand the implications.** The most common use of this directive will be to specify an ACME account email address, change the ACME CA endpoint, or to provide your own certificates.
Compatibility note: Due to its sensitive nature as a security protocol, deliberate adjustments to TLS defaults may be made in new minor or patch releases. Old or broken TLS versions, ciphers, features, etc. may be removed at any time. If your deployment is extremely sensitive to changes, you should explicitly specify those values which must remain constant, and be vigilant about upgrades. In almost every case, we recommend using the default settings.
## Syntax
```
tls <email>|[<cert_file> <key_file>] {
protocols <min> [<max>]
ciphers <cipher_suites...>
curves <curves...>
alpn <values...>
load <paths...>
ca <ca_dir_url>
}
```
- **&lt;email&gt;** is the email address to use for the ACME account managing the site's certificates.
- **&lt;cert_file&gt;** and **&lt;key_file&gt;** are the paths to the certificate and private key PEM files. Specifying just one is invalid; specifying both will disable automatic HTTPS.
- **protocols** specifies the minimum and maximum protocol versions. Default min: `tls1.2`. Default max: `tls1.3`
- **ciphers** specifies the list of cipher suites in descending preference order. Note that cipher suites are not customizable with TLS 1.3. Supported values are:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384
- TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_128_CBC_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_RSA_WITH_3DES_EDE_CBC_SHA
- **curves** specifies the list of EC curves to support. Supported values are:
- x25519
- p256
- p384
- p521
- **alpn** is the list of values to advertise in the ALPN extension of the TLS handshake.
- **load** specifies a list of folders from which to load PEM files that are certificate+key bundles.
- **ca** changes the ACME CA endpoint. This is most often used to use [Let's Encrypt's staging endpoint](https://letsencrypt.org/docs/staging-environment/) or an internal ACME server. (To change this value for the whole Caddyfile, use the `acme_ca` [global option](/docs/caddyfile/options) instead.)
## Examples
Use a custom certificate and key:
```
tls cert.pem key.pem
```

View file

@ -0,0 +1,51 @@
---
title: try_files (Caddyfile directive)
---
# try_files
Rewrites the request URI path to the first of the listed files which exists in the site root. If no files match, no rewrite is performed.
## Syntax
```
try_files <files...>
```
- **<files...>** is the list of files to try. The URI will be rewritten to the first one that exists. To match directories, append a trailing forward slash `/` to the path. All file paths are relative to the site [root](/docs/caddyfile/directives/root). Each argument may also contain a query string, in which case the query string will also be changed if it matches that particular file.
## Expanded form
The `try_files` directive is basically a shortcut for:
```
@try_files {
file {
try_files <files...>
}
}
rewrite @try_files {http.matchers.file.relative}
```
## Examples
If the request does not match any static files, rewrite to an index/router file:
```
try_files {path} /index.php
```
Same, but adding the original path to the query string:
```
try_files {path} /index.php?{query}&p={path}
```
Same, but also match directories:
```
try_files {path} {path}/ /index.php?{query}&p={path}
```

View file

@ -0,0 +1,27 @@
---
title: uri_replace (Caddyfile directive)
---
# uri_replace
Performs a substring or regular expression replacement in the request URI.
## Syntax
```
uri_replace [<matcher>] <find> <replace> [<limit>]
```
- **&lt;find&gt;** is the substring or regular expression to search for.
- **&lt;replace&gt;** is the replacement value.
- **&lt;limit&gt;** is an optional limit to the number of replacements.
## Examples
Replace "/docs/" with "/v1/docs/" in any request URI:
```
uri_replace * /docs/ /v1/docs/
```

View file

@ -0,0 +1,43 @@
---
title: Global options (Caddyfile)
---
# Global options
The Caddyfile has a way for you to specify options that apply globally. Some options act as default values, while others customize the behavior of the Caddyfile [adapter](/docs/config-adapters).
The very top of your Caddyfile can be a **global options block**. This is a block that has no keys:
```
{
...
}
```
There can only be one at most, and it must be the first block of the Caddyfile.
Possible options are:
```
{
http_port <port>
https_port <port>
order <dir1> first|last|[before|after <dir2>]
storage <module_name> {
<options...>
}
experimental_http3
acme_ca <directory_url>
email <yours>
admin <addr>
}
```
- **http_port** is the port for the server to use for HTTP. For internal use only; does not change the HTTP port for clients. Default: 80
- **https_port** is the port for the server to use for HTTPS. For internal use only; does not change the HTTPS port for clients. Default: 443
- **order** sets or changes the standard order of HTTP handler directive(s). Can set directives to be `first` or `last`, or `before` or `after` another directive.
- **storage** configures Caddy's storage mechanism. Default: `file_system`
- **experimental_http3** enables experimental draft HTTP/3 support. Note that HTTP/3 is not a finished spec and client support is extremely limited. This option will go away in the future. _This option is not subject to compatibility promises._
- **acme_ca** specifies the URL to the ACME CA's directory. It is strongly recommended to set this to Let's Encrypt's [staging endpoint](https://letsencrypt.org/docs/staging-environment/) for testing or development. Default: Let's Encrypt's production endpoint.
- **email** is your email address. Mainly used when creating an ACME account with your CA, and is highly recommended in case there are problems with your certificates.
- **admin** customizes the admin API endpoint.

View file

@ -0,0 +1,203 @@
---
title: Caddyfile Spec
---
TODO: this page is unfinished
<style>
</style>
# Caddyfile Specification
This page describes the syntax of the Caddyfile. If it is your first time writing a Caddyfile, try the <a href="/v1/tutorial/caddyfile">Caddyfile primer</a> tutorial instead. This page is not beginner-friendly; it is technical and kind of boring.
Although this article is verbose, the Caddyfile is designed to be easily readable and writable by humans. You will find that it is easy to remember, not cumbersome, and flows off the fingers.
The term "Caddyfile" often refers to a file, but more generally means a blob of Caddy configuration text. A Caddyfile can be used to configure any Caddy server type: HTTP, DNS, etc. The basic structure and syntax of the Caddyfile is the same for all server types, but semantics change. Because of this variability, this document treats the Caddyfile only as the generic configuration syntax as it applies to all server types. Caddyfile documentation for specific types may be found within their respective docs. For instance, the HTTP server <a href="/v1/docs/http-caddyfile">documents the semantics of its Caddyfile</a>.
#### Topics
1. [File format & encoding](#)
2. [Lexical syntax](#)
3. [Structure](#)
4. [Labels](#)
5. [Directives](#)
6. [Environment variables](#)
7. [Import](#)
8. [Reusable snippets](#)
9. [Examples](#)
## File Format &amp; Encoding
The Caddyfile is plain Unicode text encoded with UTF-8. Each code point is distinct; specifically, lowercase and uppercase characters are different. A leading byte order mark (0xFEFF), if present, will be ignored.
## Lexical Syntax
A <b>token</b> is a sequence of whitespace-delimited characters in the Caddyfile. A token that starts with quotes <code>"</code> is read literally (including whitespace) until the next instance of quotes <code>"</code> that is not escaped. Quote literals may be escaped with a backslash like so: <code>\"</code>. Only quotes are escapable. <!-- Those stupid --> &ldquo;Smart quotes&rdquo; are not valid as quotes.
<b>Lines</b> are delimited with the <code>\n</code> (newline) character only. Carriage return <code>\r</code> is discarded unless quoted. Blank, unquoted lines are allowed and ignored.
<b>Comments</b> are discarded by the lexer. Comments begin with an unquoted hash <code>#</code> and continue to the end of the line. Comments may start a line or appear in the middle of a line as part of an unquoted token. For the purposes of this document, commented and blank lines are no longer considered.
Tokens are then evaluated by the parser for structure.
## Structure
A Caddyfile has no global scope or inheritence between separate blocks. The most global unit of the Caddyfile is an <b>entry</b>. An entry consists of a list of labels and a definition associated with those labels. A <b>label</b> is a string identifier, and a <b>definition</b> is a body (one or more lines) of tokens grouped together in a <i>block</i>:
<code class="block"><span class="cf-label-bg">list of labels</span>
<span class="cf-block-bg">definition (block)</span></code>
A Caddyfile with <i>only one</i> entry may consist simply of the label line(s) followed by the definition on the next line(s), as shown above. However, a Caddyfile with <i>more than one</i> entry <b>must</b> enclose each definition in curly braces <code>{ }</code>. The opening curly brace <code>{</code> must be at the end of the label line, and the closing curly brace <code>}</code> must be the only token on its line:
<code class="block"><span class="cf-label-bg">list of labels</span> <span class="cf-bigbrace">{</span>
<span class="cf-block-bg indent">definition (block)</span>
<span class="cf-bigbrace">}</span>
<span class="cf-label-bg">list of labels</span> <span class="cf-bigbrace">{</span>
<span class="cf-block-bg indent">definition (block)</span>
<span class="cf-bigbrace">}</span></code>
<p>
Consistent tab indentation is encouraged within blocks enclosed by curly braces.
</p>
<p>
<b>The first line of a Caddyfile is always a label line.</b> Comment lines, empty lines, and <a href="/v1/docs/import">import</a> lines are the exceptions.
</p>
<h3 id="labels">Labels</h3>
<p>
Labels are the only tokens that appear outside of blocks (with one exception being the <a href="/v1/docs/import">import</a> directive). A label line may have just one label:
</p>
<code class="block"><span class="cf-addr">label</span></code>
<p>
or several labels, separated by spaces:
</p>
<code class="block"><span class="cf-addr">label1 label2</span> ...</code>
<p>
If many labels are to head a block, the labels may be suffixed with a comma. A comma-suffixed label may be followed by a newline, in which case the next line will be considered part of the same line:
</p>
<code class="block"><span class="cf-addr">label1</span>,
<span class="cf-addr">label2</span></code>
<p>
Mixing of these patterns is valid (but discouraged), as long as the last label of the line has a comma if the next line is to continue the list of labels:
</p>
<code class="block"><span class="cf-addr">label1 label2</span>,
<span class="cf-addr">label3</span>, <span class="cf-addr">label4</span>,
<span class="cf-addr">label5</span></code>
<p>
A definition with multiple labels is replicated across each label as if they had been defined separately but with the same definition.
</p>
<h3 id="directives">Directives</h3>
<p>
The body of the definition follows label lines. The first token of each line in a definition body is a <b>directive</b>. Every token <i>after</i> the directive on the same line is an <b>argument</b>. Arguments are optional:
</p>
<code class="block"><span class="cf-dir">directive1</span>
<span class="cf-dir">directive2</span> <span class="cf-arg">arg1 arg2</span>
<span class="cf-dir">directive3</span> <span class="cf-arg">arg3</span></code>
<p>
Commas are not acceptable delimiters for arguments; they will be treated as part of the argument value. Arguments are delimited solely by same-line whitespace.
</p>
<p>
Directives may span multiple lines by opening a block. Blocks are enclosed by curly braces <code>{ }</code>. The opening curly brace <code>{</code> must be at the end of the directive's first line, and the closing curly brace <code>}</code> must be the only token on its line:
</p>
<code class="block"><span class="cf-dir">directive</span> {
...
}</code>
<p>
Within a directive block, the first token of each line may be considered a <b>subdirective</b> or <b>property</b>, depending on how it is used (other terms may be applied). And as before, they can have arguments:
</p>
<code class="block"><span class="cf-dir">directive</span> <span class="cf-arg">arg1</span> {
<span class="cf-subdir">subdir</span> arg2 arg3
...
}</code>
<p>
Subdirectives cannot open new blocks. In other words, nested directive blocks are not supported. If a directive block is empty, the curly braces should be omitted entirely.
</p>
<h3 id="env">Environment Variables</h3>
<p>
Any token (label, directive, argument, etc.) may contain or consist solely of an environment variable, which takes the Unix form or Windows form, enclosed in curly braces <code>{ }</code> without extra whitespace:
</p>
<code class="block"><span class="cf-addr">label_{$ENV_VAR_1}</span>
<span class="cf-dir">directive</span> <span class="cf-arg">{%ENV_VAR_2%}</span></code>
<p>
Either form works on any OS. A single environment variable does not expand out into multiple tokens, arguments, or values.
</p>
<h3 id="import">Import</h3>
<p>
The <a href="/v1/docs/import">import</a> directive is a special case, because it can appear outside a definition block. The consequence of this is that no label can take on the value of "import".
</p>
<p>
Where an import line is, that line will be replaced with the contents of the imported file, unmodified. See the <a href="/v1/docs/import">import docs</a> for more information.
</p>
<h3 id="snippets">Reusable Snippets</h3>
<p>
You can define snippets to be reused later in your Caddyfile by defining a block with a single-token label surrounded by parentheses:
</p>
<code class="block"><span class="cf-addr">(mysnippet)</span> {
...
}</code>
<p>
Then you can invoke the snippet with the <code>import</code> directive:
</p>
<p>
<code class="block"><span class="cf-dir">import</span> <span class="cf-arg">mysnippet</span></code>
<h3 id="examples">Examples</h3>
<p>
A very simple Caddyfile with only one entry:
<code class="block"><span class="cf-addr">label1</span>
<span class="cf-dir">directive1</span> <span class="cf-arg">argument1</span>
<span class="cf-dir">directive2</span></code>
</p>
<p>
Appending the prior example with another entry introduces the need for curly braces:
<code class="block"><span class="cf-addr">label1</span> {
<span class="cf-dir">directive1</span> <span class="cf-arg">arg1</span>
<span class="cf-dir">directive2</span>
}
<span class="cf-addr">label2</span>, <span class="cf-addr">label3</span> {
<span class="cf-dir">directive3</span> <span class="cf-arg">arg2</span>
<span class="cf-dir">directive4</span> <span class="cf-arg">arg3</span> <span class="cf-arg">arg4</span>
}
</code>
</p>
<p>
Some people prefer to always use braces even if there's just one entry; this is fine, but unnecessary:
<code class="block"><span class="cf-addr">label1</span> {
<span class="cf-dir">directive1</span> <span class="cf-arg">arg1</span>
<span class="cf-dir">directive2</span>
}</code>
</p>
<p>
Example in which a directive opens a block:
<code class="block"><span class="cf-addr">label1</span>
<span class="cf-dir">directive</span> <span class="cf-arg">arg1</span> {
<span class="cf-subdir">subdir</span> arg2 arg3
}
<span class="cf-dir">directive</span> <span class="cf-arg">arg4</span></code>
</p>
<p>
Similarly, but in an indented definition body, and with a comment:
<code class="block"><span class="cf-addr">label1</span> {
<span class="cf-dir">directive1</span> <span class="cf-arg">arg1</span>
<span class="cf-dir">directive2</span> <span class="cf-arg">arg2</span> {
<span class="cf-subdir">subdir1</span> arg3 arg4
<span class="cf-subdir">subdir2</span>
<span class="cf-comment"># nested blocks not supported</span>
}
<span class="cf-dir">directive3</span>
}</code>
</p>