Big Caddyfile docs update

This commit is contained in:
Francis Lavoie 2024-02-15 19:03:58 -05:00
parent 3ec3033602
commit 1f6c20639b
No known key found for this signature in database
GPG key ID: 0F66EE1687682239
34 changed files with 1732 additions and 512 deletions

View file

@ -140,19 +140,25 @@ or, if there is only one matcher in the set, you can put it on the same line:
@name ...
```
Then you can use the matcher like so: `@name`
For example:
Then you can use the matcher like so, by specifying it as the first argument to a directive:
```caddy-d
@websockets {
header Connection *Upgrade*
header Upgrade websocket
}
reverse_proxy @websockets localhost:6001
directive @name
```
This proxies only the requests that have a header field named "Connection" containing the word "Upgrade", and another field named "Upgrade" with a value of "websocket".
For example, this proxies websocket requests to `localhost:6001`, and other requests to `localhost:8080`. It matches requests that have a header field named `Connection` _containing_ `Upgrade`, **and** another field named `Upgrade` with exactly `websocket`:
```caddy
example.com {
@websockets {
header Connection *Upgrade*
header Upgrade websocket
}
reverse_proxy @websockets localhost:6001
reverse_proxy localhost:8080
}
```
If the matcher set consists of only one matcher, a one-liner syntax also works:
@ -161,19 +167,19 @@ If the matcher set consists of only one matcher, a one-liner syntax also works:
reverse_proxy @post localhost:6001
```
As a special case, the [`expression` matcher](#expression) may be used without specifying its name as long as a single quoted argument (the CEL expression itself) follows the matcher name:
As a special case, the [`expression` matcher](#expression) may be used without specifying its name as long as one [quoted](/docs/caddyfile/concepts#tokens-and-quotes) argument (the CEL expression itself) follows the matcher name:
```caddy-d
@notFound `{err.status_code} == 404`
@not-found `{err.status_code} == 404`
```
Like directives, named matcher definitions must go inside the site blocks that use them.
Like directives, named matcher definitions must go inside the [site blocks](/docs/caddyfile/concepts#structure) that use them.
A named matcher definition constitutes a _matcher set_. Matchers in a set are AND'ed together; i.e. all must match. For example, if you have both a `header` and `path` matcher in the set, both must match.
A named matcher definition constitutes a _matcher set_. Matchers in a set are AND'ed together; i.e. all must match. For example, if you have both a [`header`](#header) and [`path`](#path) matcher in the set, both must match.
Multiple matchers of the same type may be unioned (e.g. multiple `path` matchers in the same set) using boolean algebra (AND/OR), as described in their respective sections below.
Multiple matchers of the same type may be merged (e.g. multiple [`path`](#path) matchers in the same set) using boolean algebra (AND/OR), as described in their respective sections below.
For more complex boolean matching logic, it's recommended to the [`expression` matcher](#expression) to write a CEL expression, which supports _and_ `&&`, _or_ `||`, and _parentheses_ `( )`.
For more complex boolean matching logic, it's recommended to the [`expression` matcher](#expression) to write a CEL expression, which supports **and** `&&`, **or** `||`, and **parentheses** `( )`.
@ -208,14 +214,24 @@ There can be multiple `client_ip` matchers per named matcher, and their ranges w
Match requests from private IPv4 addresses:
```caddy-d
client_ip 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8
@private-ipv4 client_ip 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8
```
This matcher is commonly paired with the [`not`](#not) matcher to invert the match. For example, to abort all connections from _public_ IPv4 and IPv6 addresses (which is the inverse of all private ranges):
```caddy
example.com {
@denied not client_ip private_ranges
abort @denied
respond "Hello, you must be from a private network!"
}
```
In a [CEL expression](#expression), it would look like this:
```caddy-d
@denied not client_ip private_ranges
abort @denied
@my-friends `client_ip('12.23.34.45', '23.34.45.56')`
```
@ -230,9 +246,9 @@ By any [CEL (Common Expression Language)](https://github.com/google/cel-spec) ex
Caddy [placeholders](/docs/conventions#placeholders) (or [Caddyfile shorthands](/docs/caddyfile/concepts#placeholders)) may be used in these CEL expressions, as they are preprocessed and converted to regular CEL function calls before being interpreted by the CEL environment.
Since v2.5.2, most other request matchers can also be used in expressions as functions, which allows for more flexibility for boolean logic than outside expressions. See the documentation for each matcher for the supported syntax within CEL expressions.
Most other request matchers can also be used in expressions as functions, which allows for more flexibility for boolean logic than outside expressions. See the documentation for each matcher for the supported syntax within CEL expressions.
For convenience, the matcher name may be omitted if defining a named matcher that consists solely of a CEL expression. This reads quite nicely:
For convenience, the matcher name may be omitted if defining a named matcher that consists solely of a CEL expression. The CEL expression must be [quoted](/docs/caddyfile/concepts#tokens-and-quotes) (backticks or heredocs recommended). This reads quite nicely:
```caddy-d
@mutable `{method}.startsWith("P")`
@ -245,19 +261,35 @@ In this case the CEL matcher is assumed.
Match requests whose methods start with `P`, e.g. `PUT` or `POST`:
```caddy-d
expression {method}.startsWith("P")
@methods expression {method}.startsWith("P")
```
Match requests where handler returned error status code `404`, would be used in conjunction with the [`handle_errors` directive](/docs/caddyfile/directives/handle_errors):
```caddy-d
expression {err.status_code} == 404
@404 expression {err.status_code} == 404
```
Match requests where the path matches one of two different regular expressions; this is only possible to write using an expression, because the [`path_regexp`](#path-regexp) matcher can normally only exist once per named matcher:
```caddy-d
expression path_regexp('^/user/(\w*)') || path_regexp('^/(\w*)')
@user expression path_regexp('^/user/(\w*)') || path_regexp('^/(\w*)')
```
Or the same, omitting the matcher name, and wrapping in [backticks](/docs/caddyfile/concepts#tokens-and-quotes) so it's parsed as a single token:
```caddy-d
@user `path_regexp('^/user/(\w*)') || path_regexp('^/(\w*)')`
```
You may use [heredoc syntax](/docs/caddyfile/concepts#heredocs) to write multi-line CEL expressions:
```caddy-d
@api <<CEL
{method} == "GET"
&& {path}.startsWith("/api/")
CEL
respond @api "Hello, API!"
```
@ -268,7 +300,7 @@ expression path_regexp('^/user/(\w*)') || path_regexp('^/(\w*)')
file {
root <path>
try_files <files...>
try_policy first_exist|smallest_size|largest_size|most_recent_modified
try_policy first_exist|smallest_size|largest_size|most_recently_modified
split_path <delims...>
}
file <files...>
@ -276,7 +308,7 @@ file <files...>
expression `file({
'root': '<path>',
'try_files': ['<files...>'],
'try_policy': 'first_exist|smallest_size|largest_size|most_recent_modified',
'try_policy': 'first_exist|smallest_size|largest_size|most_recently_modified',
'split_path': ['<delims...>']
})`
expression file('<files...>')
@ -302,7 +334,7 @@ By files.
- `largest_size` chooses the file with the largest size.
- `most_recent_modified` chooses the file that was most recently modified.
- `most_recently_modified` chooses the file that was most recently modified.
- `split_path` will cause the path to be split at the first delimiter in the list that is found in each filepath to try. For each split value, the left-hand side of the split including the delimiter itself will be the filepath that is tried. For example, `/remote.php/dav/` using a delimiter of `.php` would try the file `/remote.php`. Each delimiter must appear at the end of a URI path component in order to be used as a split delimiter. This is a niche setting and is mostly used when serving PHP sites.
@ -335,13 +367,13 @@ Upon matching, four new placeholders will be made available:
Match requests where the path is a file that exists:
```caddy-d
file
@file file
```
Match requests where the path followed by `.html` is a file that exists, or if not, where the path is a file that exists:
```caddy-d
file {
@html file {
try_files {path}.html {path}
}
```
@ -349,9 +381,16 @@ file {
Same as above, except using the one-line shortcut, and falling back to emitting a 404 error if a file is not found:
```caddy-d
file {path}.html {path} =404
@html-or-error file {path}.html {path} =404
```
Some more examples using [CEL expressions](#expression). Keep in mind that placeholders are preprocessed and converted to regular CEL function calls before being interpreted by the CEL environment, so concatenation is used here. Additionally, the long-form must be used if concatenating with placeholders due to current parsing limitations:
```caddy-d
@file `file()`
@first `file({'try_files': [{path}, {path} + '/', 'index.html']})`
@smallest `file({'try_policy': 'smallest_size', 'try_files': ['a.txt', 'b.txt']})`
```
---
@ -382,10 +421,11 @@ Note that header fields may be repeated and have different values. Backend appli
Match requests with the `Connection` header containing `Upgrade`:
```caddy-d
header Connection *Upgrade*
@upgrade header Connection *Upgrade*
```
Match requests with the `Foo` header containing `bar` OR `baz`:
```caddy-d
@foo {
header Foo bar
@ -394,11 +434,13 @@ Match requests with the `Foo` header containing `bar` OR `baz`:
```
Match requests that do not have the `Foo` header field at all:
```caddy-d
@not_foo header !Foo
```
Match WebSocket requests by checking for the `Connection` header containing `Upgrade` and the `Upgrade` header equalling `websocket`, using an [expression](#expression) matcher:
Using an [CEL expression](#expression), match WebSocket requests by checking for the `Connection` header containing `Upgrade` and the `Upgrade` header equalling `websocket`:
```caddy-d
@websockets `header({'Connection':'*Upgrade*','Upgrade':'websocket'})`
```
@ -425,7 +467,13 @@ Only one regular expression is supported per header field. Multiple different fi
Match requests where the Cookie header contains `login_` followed by a hex string, with a capture group that can be accessed with `{re.login.1}`.
```caddy-d
header_regexp login Cookie login_([a-f0-9]+)
@login header_regexp login Cookie login_([a-f0-9]+)
```
Or the same, using a [CEL expression](#expression):
```caddy-d
@login `header_regexp('login', 'Cookie', 'login_([a-f0-9]+)')`
```
@ -439,14 +487,30 @@ host <hosts...>
expression host('<hosts...>')
```
Matches request by the `Host` header field of the request. It is not common to use this in the Caddyfile, since most site blocks already indicate hosts in the address of the site. This matcher is mostly used in site blocks that don't define specific hostnames (like wildcard subdomains), but where hostname-specific logic is required.
Matches request by the `Host` header field of the request.
Since most site blocks already indicate hosts in the address of the site, this matcher is more commonly used in site blocks that use a wildcard hostname (see the [wildcard certificates pattern](/docs/caddyfile/patterns#wildcard-certificates)), but where hostname-specific logic is required.
Multiple `host` matchers will be OR'ed together.
#### Example:
Matching one subdomain:
```caddy-d
host sub.example.com
@sub host sub.example.com
```
Matching the apex domain and a subdomain:
```caddy-d
@site host example.com www.example.com
```
Multiple subdomains using a [CEL expression](#expression):
```caddy-d
@app `host('app1.example.com', 'app2.example.com')`
```
@ -469,13 +533,19 @@ Multiple `method` matchers will be OR'ed together.
Match requests with the `GET` method:
```caddy-d
method GET
@get method GET
```
Match requests with the `PUT` or `DELETE` methods:
```caddy-d
method PUT DELETE
@put-delete method PUT DELETE
```
Match read-only methods using a [CEL expression](#expression):
```caddy-d
@read `method('GET', 'HEAD', 'OPTIONS')`
```
@ -484,14 +554,14 @@ method PUT DELETE
### not
```caddy-d
not <any other matcher>
not <matcher>
```
or, to negate multiple matchers which get AND'ed, open a block:
```caddy-d
not {
<any other matchers...>
<matchers...>
}
```
@ -502,7 +572,9 @@ The results of the enclosed matchers will be negated.
Match requests with paths that do NOT begin with `/css/` OR `/js/`.
```caddy-d
not path /css/* /js/*
@not-assets {
not path /css/* /js/*
}
```
Match requests WITH NEITHER:
@ -512,8 +584,10 @@ Match requests WITH NEITHER:
i.e. must have none of these to match:
```caddy-d
not path /api/*
not method POST
@with-neither {
not path /api/*
not method POST
}
```
Match requests WITHOUT BOTH:
@ -523,12 +597,27 @@ Match requests WITHOUT BOTH:
i.e. must have neither or either of these to match:
```caddy-d
not {
path /api/*
method POST
@without-both {
not {
path /api/*
method POST
}
}
```
There's no [CEL expression](#expression) for this matcher, because you may use the `!` operator for negation instead. For example:
```caddy-d
@without-both `!path('/api*') && !method('POST')`
```
Which is the same as this, using parentheses:
```caddy-d
@without-both `!(path('/api*') || method('POST'))`
```
---
@ -557,6 +646,32 @@ The special wildcard escape `%*` can also be used instead of `*` to leave its ma
Multiple paths will be OR'ed together.
#### Examples:
Match multiple directories and their contents:
```caddy-d
@assets path /js/* /css/* /images/*
```
Match a specific file:
```caddy-d
@favicon path /favicon.ico
```
Match file extensions:
```caddy-d
@extensions path *.js *.css
```
With a [CEL expression](#expression):
```caddy-d
@assets `path('/js/*', '/css/*', '/images/*')`
```
---
@ -582,7 +697,13 @@ There can only be one `path_regexp` pattern per named matcher.
Match requests where the path ends a 6 character hex string followed by `.css` or `.js` as the file extension, with capture groups that can be accessed with `{re.static.1}` and `{re.static.2}` for each part enclosed in `( )`, respectively:
```caddy-d
path_regexp static \.([a-f0-9]{6})\.(css|js)$
@static path_regexp static \.([a-f0-9]{6})\.(css|js)$
```
Or the same, using a [CEL expression](#expression), also validating that the [`file`](#file) exists on disk:
```caddy-d
@static `path_regexp('static', '\.([a-f0-9]{6})\.(css|js)$') && file()`
```
@ -593,13 +714,27 @@ path_regexp static \.([a-f0-9]{6})\.(css|js)$
```caddy-d
protocol http|https|grpc|http/<version>[+]
expression protocol('http|https|grpc')
expression protocol('http|https|grpc|http/<version>[+]')
```
By request protocol. A broad protocol name such as `http`, `https`, or `grpc` can be used; or specific or minimum HTTP versions such as `http/1.1` or `http/2+`.
There can only be one `protocol` matcher per named matcher.
#### Example:
Match requests using HTTP/2:
```caddy-d
@http2 protocol http/2+
```
With a [CEL expression](#expression):
```caddy-d
@http2 `protocol('http/2+')`
```
---
@ -619,12 +754,25 @@ There can be multiple `query` matchers per named matcher, and pairs with the sam
Illegal query strings (bad syntax, unescaped semicolons, etc.) will fail to parse and thus will not match.
**NOTE:** Query string parameters are arrays, not singular values. This is because repeated keys are valid in query strings, and each one may have a different value. This matcher will match for a key if any one of its configured values is assigned in the query string. Backend applications using query strings MUST take into consideration that query string values are arrays and can have multiple values.
#### Example:
Match requests with a `sort` query parameter with the value `asc`:
Match a `q` query parameter with any value:
```caddy-d
query sort=asc
@search query q=*
```
Match a `sort` query parameter with the value `asc` or `desc`:
```caddy-d
@sorted query sort=asc sort=desc
```
Matching both `q` and `sort`, with a [CEL expression](#expression):
```caddy-d
@search-sort `query({'sort': ['asc', 'desc'], 'q': '*'})`
```
@ -652,14 +800,24 @@ There can be multiple `remote_ip` matchers per named matcher, and their ranges w
Match requests from private IPv4 addresses:
```caddy-d
remote_ip 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8
@private-ipv4 remote_ip 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8
```
This matcher is commonly paired with the [`not`](#not) matcher to invert the match. For example, to abort all connections from _public_ IPv4 and IPv6 addresses (which is the inverse of all private ranges):
```caddy
example.com {
@denied not remote_ip private_ranges
abort @denied
respond "Hello, you must be from a private network!"
}
```
In a [CEL expression](#expression), it would look like this:
```caddy-d
@denied not remote_ip private_ranges
abort @denied
@my-friends `remote_ip('12.23.34.45', '23.34.45.56')`
```