Big Caddyfile docs update (#374)

This commit is contained in:
Francis Lavoie 2024-02-20 06:49:30 -05:00 committed by GitHub
parent 3ec3033602
commit 22301d6a81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 1732 additions and 512 deletions

View file

@ -29,3 +29,42 @@ acme_server [<matcher>] {
- **lifetime** (Default: `12h`) is a [duration](/docs/conventions#durations) which specifies the validity period for issued certificates. This value must be less than the lifetime of the [intermediate certificate](/docs/caddyfile/options#intermediate-lifetime) used for signing. It is not recommended to change this unless absolutely necessary.
- **resolvers** are the addresses of DNS resolvers to use when looking up the TXT records for solving ACME DNS challenges. Accepts [network addresses](/docs/conventions#network-addresses) defaulting to UDP and port 53 unless specified. If the host is an IP address, it will be dialed directly to resolve the upstream server. If the hot is not an IP address, the addresses are resolved using the [name resolution convention](https://golang.org/pkg/net/#hdr-Name_Resolution) of the Go standard library. If multiple resolvers are specified, then one is chosen at random.
## Examples
To serve an ACME server with ID `home` on the domain `acme.example.com`, with the CA customized via the [`pki` global option](/docs/caddyfile/options#pki-options), and issuing its own certificate using the `internal` issuer:
```caddy
{
pki {
ca home {
name "My Home CA"
}
}
}
acme.example.com {
tls {
issuer internal {
ca home
}
}
acme_server {
ca home
}
}
```
If you have another Caddy server, it can use the above ACME server to issue its own certificates:
```caddy
{
acme_ca https://acme.example.com/acme/home/directory
acme_ca_root /path/to/home_ca_root.crt
}
example.com {
respond "Hello, world!"
}
```

View file

@ -37,11 +37,30 @@ basicauth [<matcher>] [<hash_algorithm> [<realm>]] {
## Examples
Protect all resources in /secret so only Bob can access them with the password "hiccup":
Require authentication for all requests to `example.com`:
```caddy-d
basicauth /secret/* {
Bob $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvG
```caddy
example.com {
basicauth {
# Username "Bob", password "hiccup"
Bob $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvG
}
respond "Welcome, {http.auth.user.id}" 200
}
```
Protect files in `/secret/` so only `Bob` can access them (and anyone can see other paths):
```caddy
example.com {
root * /srv
basicauth /secret/* {
# Username "Bob", password "hiccup"
Bob $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvG
}
file_server
}
```

View file

@ -4,7 +4,9 @@ title: bind (Caddyfile directive)
# 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.)
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. The port is determined by the [site address](/docs/caddyfile/concepts#addresses) (defaulting to `443`).
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.)
@ -24,18 +26,54 @@ bind <hosts...>
To make a socket accessible only on the current machine, bind to the loopback interface (localhost):
```caddy-d
bind 127.0.0.1
```caddy
example.com {
bind 127.0.0.1
}
```
To include IPv6:
```caddy-d
bind 127.0.0.1 [::1]
```caddy
example.com {
bind 127.0.0.1 [::1]
}
```
To bind to `10.0.0.1:8080`:
```caddy
example.com:8080 {
bind 10.0.0.1
}
```
To bind to a Unix domain socket at `/run/caddy`:
```caddy-d
bind unix//run/caddy
```caddy
example.com {
bind unix//run/caddy
}
```
To change the file permission to be writable by all users ([defaults](/docs/conventions#network-addresses) to `0200`, which is only writable by the owner):
```caddy
example.com {
bind unix//run/caddy|0222
}
```
To bind one domain to two different interfaces, with different responses:
```caddy
example.com {
bind 10.0.0.1
respond "One"
}
example.com {
bind 10.0.0.2
respond "Two"
}
```

View file

@ -55,10 +55,12 @@ encode [<matcher>] <formats...> {
}
```
## Response matcher
**Response matchers** can be used to filter (or classify) responses by specific criteria.
### status
```caddy-d
@ -69,10 +71,12 @@ By HTTP status code.
- **&lt;code...&gt;** is a list of HTTP status codes. Special cases are `2xx`, `3xx`, ... which match against all status codes in the range of 200-299, 300-399, ... respectively
### header
See the [header](/docs/caddyfile/matchers#header) request matcher for the supported syntax.
## Examples
Enable Gzip compression:
@ -86,3 +90,13 @@ Enable Zstandard and Gzip compression (with Zstandard implicitly preferred, sinc
```caddy-d
encode zstd gzip
```
And in a full site, compressing static files served by [`file_server`](file_server):
```caddy
example.com {
root * /srv
encode zstd gzip
file_server
}
```

View file

@ -23,6 +23,7 @@ error [<matcher>] <status>|<message> [<status>] {
To clarify, the first non-matcher argument can be either a 3-digit status code, or an error message string. If it is an error message, the next argument can be the status code.
## Examples
Trigger an error on certain request paths, and use [`handle_errors`](handle_errors) to write a response:

View file

@ -85,9 +85,11 @@ file_server /static/*
The `file_server` directive is usually paired with the [`root` directive](root) to set the root path from which to serve files:
```caddy-d
root * /home/user/public_html
file_server
```caddy
example.com {
root * /srv
file_server
}
```
<aside class="tip">

View file

@ -2,6 +2,29 @@
title: forward_auth (Caddyfile directive)
---
<script>
window.$(function() {
// Fix > in code blocks
window.$('pre.chroma .k:contains(">")')
.each(function() {
const e = window.$(this);
// Skip if ends with >
if (e.text().trim().endsWith('>')) return;
// Replace > with <span class="p">&gt;</span>
e.html(e.html().replace(/&gt;/g, '<span class="p">&gt;</span>'));
});
// Fix uri subdirective, gets parsed as matcher arg because of "uri" directive
window.$('.k:contains("uri") + .nd')
.each(function() {
window.$(this)
.removeClass('nd')
.addClass('s')
.text(window.$(this).text());
});
});
</script>
# forward_auth
An opinionated directive which proxies a clone of the request to an authentication gateway, which can decide whether handling should continue, or needs to be sent to a login page.

View file

@ -6,7 +6,11 @@ title: handle (Caddyfile directive)
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` directives at the same level of nesting will be tried in the order they're written in the `Caddyfile`, except if there is a single path matcher, which orders them by longest (most specific) path pattern first. Handle blocks can be nested if needed. Only HTTP handler directives can be used inside handle blocks.
In other words, when multiple `handle` directives appear in sequence, only the first _matching_ `handle` block will be evaluated. A handle with no matcher acts like a _fallback_ route.
The `handle` directives are sorted according to the [directive sorting algorithm](/docs/caddyfile/directives#sorting-algorithm) by their matchers. The [`handle_path`](handle_path) directive is a special case which sorts at the same priority as a `handle` with a path matcher.
Handle blocks can be nested if needed. Only HTTP handler directives can be used inside handle blocks.
## Syntax
@ -19,39 +23,67 @@ handle [<matcher>] {
- **<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 inheritance-based way like nginx location blocks, you may prefer the use of `handle` blocks rather than defining mutually-exclusive matchers for your directives. If inheritance is a desired characteristic of your HTTP handler configurations, then the `handle` directive may suit you well.
## Similar directives
There are other directives that can wrap HTTP handler directives, but each has its use depending on the behavior you want to convey:
- [`handle_path`](handle_path) does the same as `handle`, but it strips a prefix from the request before running its handlers.
- [`handle_errors`](handle_errors) is like `handle`, but is only invoked when Caddy encounters an error during request handling.
- [`route`](route) wraps other directives like `handle` does, but with two distinctions: 1) route blocks are not mutually exclusive to each other, and 2) directives within a route are not [re-ordered](/docs/caddyfile/directives#directive-order), giving you more control if needed.
- [`route`](route) wraps other directives like `handle` does, but with two distinctions:
1. route blocks are not mutually exclusive to each other,
2. directives within a route are not [re-ordered](/docs/caddyfile/directives#directive-order), giving you more control if needed.
## Examples
Handle requests in `/foo/` by the static file server, and send all other requests to the reverse proxy:
Handle requests in `/foo/` with the static file server, and other requests with the reverse proxy:
```caddy-d
handle /foo/* {
file_server
}
handle {
reverse_proxy 127.0.0.1:8080
```caddy
example.com {
handle /foo/* {
file_server
}
handle {
reverse_proxy 127.0.0.1:8080
}
}
```
You can mix `handle` and [`handle_path`](handle_path) directives in the same site, and they will still be mutually exclusive from each other:
You can mix `handle` and [`handle_path`](handle_path) in the same site, and they will still be mutually exclusive from each other:
```caddy-d
handle_path /foo/* {
# The path has the "/foo" prefix stripped
}
```caddy
example.com {
handle_path /foo/* {
# The path has the "/foo" prefix stripped
}
handle /bar/* {
# The path still retains "/bar"
handle /bar/* {
# The path still retains "/bar"
}
}
```
You can nest `handle` blocks to create more complex routing logic:
```caddy
example.com {
handle /foo* {
handle /foo/bar* {
# This block only matches paths under /foo/bar
}
handle {
# This block matches everything else under /foo/
}
}
handle {
# This block matches everything else (acts as a fallback)
}
}
```

View file

@ -97,12 +97,12 @@ To handle specific error codes differently, use an [`expression`](/docs/caddyfil
```caddy-d
handle_errors {
@404-410 expression `{err.status_code} in [404, 410]`
@404-410 `{err.status_code} in [404, 410]`
handle @404-410 {
respond "It's a 404 or 410 error!"
}
@5xx expression `{err.status_code} >= 500 && {err.status_code} < 600`
@5xx `{err.status_code} >= 500 && {err.status_code} < 600`
handle @5xx {
respond "It's a 5xx error."
}

View file

@ -20,7 +20,7 @@ window.$(function() {
# handle_path
Works the same as the [`handle` directive](/docs/caddyfile/directives/handle), but implicitly uses [`uri strip_prefix`](/docs/caddyfile/directives/uri) to strip the matched path prefix.
Works the same as the [`handle` directive](handle), but implicitly uses [`uri strip_prefix`](uri) to strip the matched path prefix.
Handling a request matching a certain path (while stripping that path from the request URI) is a common enough use case that it has its own directive for convenience.
@ -47,7 +47,7 @@ handle_path /prefix/* {
}
```
is effectively the same as this:
👆 is effectively the same as this 👇, but the `handle_path` form 👆 is slightly more succinct
```caddy-d
handle /prefix/* {
@ -56,4 +56,19 @@ handle /prefix/* {
}
```
but the `handle_path` form is slightly more succinct.
A full Caddyfile example, where `handle_path` and `handle` are mutually exclusive; but, be aware of the [subfolder problem <img src="/old/resources/images/external-link.svg" class="external-link">](https://caddy.community/t/the-subfolder-problem-or-why-cant-i-reverse-proxy-my-app-into-a-subfolder/8575)
```caddy
example.com {
# Serve your API, stripping the /api prefix
handle_path /api/* {
reverse_proxy localhost:9000
}
# Serve your static site
handle {
root * /srv
file_server
}
}
```

View file

@ -4,10 +4,12 @@ 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.
Manipulates HTTP response header fields. It can set, add, and delete header values, or perform replacements using regular expressions.
By default, header operations are performed immediately unless any of the headers are being deleted (`-` prefix) or setting a default value (`?` prefix). In those cases, the header operations are automatically deferred until the time they are being written to the client.
To manipulate HTTP request headers, you may use the [`request_header`](request_header) directive.
## Syntax
@ -38,7 +40,9 @@ 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.
- **&lt;field&gt;** is the name of the header field.
With no prefix, the field is set (overwritten).
Prefix with `+` to add the field instead of overwriting (setting) the field if it already exists; header fields can appear more than once in a request.
@ -48,7 +52,7 @@ header [<matcher>] [[+|-|?|>]<field> [<value>|<find>] [<replace>]] {
Prefix with `>` to set the field, and enable `defer`, as a shortcut.
- **&lt;value&gt;** is the header field value, if adding or setting a field.
- **&lt;value&gt;** is the header field value, when adding or setting a field.
- **&lt;find&gt;** is the substring or regular expression to search for.
@ -58,7 +62,7 @@ header [<matcher>] [[+|-|?|>]<field> [<value>|<find>] [<replace>]] {
For multiple header manipulations, you can open a block and specify one manipulation per line in the same way.
When using the `?` prefix to set a default header value, it is recommended to separate this into its own `header` directive. [Under the hood](/docs/modules/http.handlers.headers#response/require), using `?` configures a response matcher which applies to the directive's entire handler which only applies the header operations if the field is not yet set. For example, if in the same directive, you have these two manipulations: `-Hidden` and `?Foo default`, then the `Hidden` header is _only_ removed if `Foo` is empty, which is typically not the intended effect.
When using the `?` prefix to set a default header value, it is recommended to separate this into its own `header` directive. [Under the hood](/docs/modules/http.handlers.headers#response/require), using `?` configures a response matcher which applies to the directive's entire handler, which only applies the header operations if the field is not yet set. For example, in the same directive, you have these two manipulations: `-Hidden` and `?Foo default`, then the `Hidden` header is _only_ removed if `Foo` is empty, which is typically not the intended effect.
## Examples

View file

@ -4,6 +4,16 @@ title: log (Caddyfile directive)
<script>
window.$(function() {
// Fix > in code blocks
window.$('pre.chroma .k:contains(">")')
.each(function() {
const e = window.$(this);
// Skip if ends with >
if (e.text().trim().endsWith('>')) return;
// Replace > with <span class="p">&gt;</span>
e.html(e.html().replace(/&gt;/g, '<span class="p">&gt;</span>'));
});
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
addLinksToSubdirectives();
});
@ -15,14 +25,14 @@ Enables and configures HTTP request logging (also known as access logs).
<aside class="tip">
If you're looking to configure Caddy's runtime logs, you're looking for the [`log` global option](/docs/caddyfile/options#log) instead.
To configure Caddy's runtime logs, see the [`log` global option](/docs/caddyfile/options#log) instead.
</aside>
The `log` directive applies to the host/port of the site block it appears in, not any other part of the site address (e.g. path).
The `log` directive applies to the hostnames of the site block it appears in, unless overridden with the `hostnames` subdirective.
When configured, by default all requests to the site will be logged. To conditionally skip some requests from logging, use the [`skip_log` directive](/docs/caddyfile/directives/skip_log).
When configured, by default all requests to the site will be logged. To conditionally skip some requests from logging, use the [`skip_log` directive](skip_log).
- [Syntax](#syntax)
@ -60,25 +70,35 @@ log [<logger_name>] {
}
```
- **logger_name** is an optional override of the logger name for this site. By default, a logger name is generated automatically, e.g. `log0`, `log1`, and so on depending on the order of the sites in the Caddyfile. This is only useful if you wish to reliably refer to the output of this logger from another logger defined in global options. See [an example](#multiple-outputs) below.
- **logger_name** is an optional override of the logger name for this site.
- **hostnames** overrides the hostnames that this logger applies to. By default, the logger applies to the hostnames of the site block it appears in, i.e. the site addresses. This is useful if you wish to define different loggers per subdomain in a [wildcard site block](/docs/caddyfile/patterns#wildcard-certificates). See [an example](#wildcard-logs) below.
By default, a logger name is generated automatically, e.g. `log0`, `log1`, and so on depending on the order of the sites in the Caddyfile. This is only useful if you wish to reliably refer to the output of this logger from another logger defined in global options. See [an example](#multiple-outputs) below.
- **output** configures where to write the logs. See [Output modules](#output-modules) below. Default: `stderr`.
- **hostnames** is an optional override of the hostnames that this logger applies to.
- **format** describes how to encode, or format, the logs. See [Format modules](#format-modules) below. Default: `console` if `stderr` is detected to be a terminal, `json` otherwise.
By default, the logger applies to the hostnames of the site block it appears in, i.e. the site addresses. This is useful if you wish to define different loggers per subdomain in a [wildcard site block](/docs/caddyfile/patterns#wildcard-certificates). See [an example](#wildcard-logs) below.
- **level** is the minimum entry level to log. Default: `INFO`. Note that access logs currently only emit `INFO` and `ERROR` level logs.
- **output** configures where to write the logs. See [`output` modules](#output-modules) below.
Default: `stderr`.
- **format** describes how to encode, or format, the logs. See [`format` modules](#format-modules) below.
Default: `console` if `stderr` is detected to be a terminal, `json` otherwise.
- **level** is the minimum entry level to log. Default: `INFO`.
Note that access logs currently only emit `INFO` and `ERROR` level logs.
### Output modules
The **output** subdirective lets you customize where logs get written. It appears within a `log` block.
The **output** subdirective lets you customize where logs get written.
#### stderr
Standard error (console, default).
Standard error (console, is the default).
```caddy-d
output stderr
@ -104,6 +124,8 @@ output discard
A file. By default, log files are rotated ("rolled") to prevent disk space exhaustion.
Log rolling is provided by [lumberjack <img src="/old/resources/images/external-link.svg" class="external-link">](https://github.com/natefinch/lumberjack)
```caddy-d
output file <filename> {
roll_disabled
@ -116,11 +138,25 @@ output file <filename> {
```
- **&lt;filename&gt;** is the path to the log file.
- **roll_disabled** disables log rolling. This can lead to disk space depletion, so only use this if your log files are maintained some other way.
- **roll_size** is the size at which to roll the log file. The current implementation supports megabyte resolution; fractional values are rounded up to the next whole megabyte. For example, `1.1MiB` is rounded up to `2MiB`. Default: `100MiB`
- **roll_uncompressed** turns off gzip log compression. Default: gzip compression is enabled.
- **roll_local_time** sets the rolling to use local timestamps in filenames. Default: uses UTC time.
- **roll_keep** is how many log files to keep before deleting the oldest ones. Default: `10`
- **roll_size** is the size at which to roll the log file. The current implementation supports megabyte resolution; fractional values are rounded up to the next whole megabyte. For example, `1.1MiB` is rounded up to `2MiB`.
Default: `100MiB`
- **roll_uncompressed** turns off gzip log compression.
Default: gzip compression is enabled.
- **roll_local_time** sets the rolling to use local timestamps in filenames.
Default: uses UTC time.
- **roll_keep** is how many log files to keep before deleting the oldest ones.
Default: `10`
- **roll_keep_for** is how long to keep rolled files as a [duration string](/docs/conventions#durations). The current implementation supports day resolution; fractional values are rounded up to the next whole day. For example, `36h` (1.5 days) is rounded up to `48h` (2 days). Default: `2160h` (90 days)
@ -136,7 +172,9 @@ output net <address> {
```
- **&lt;address&gt;** is the [address](/docs/conventions#network-addresses) to write logs to.
- **dial_timeout** is how long to wait for a successful connection to the log socket. Log emissions may be blocked for up to this long if the socket goes down.
- **soft_start** will ignore errors when connecting to the socket, allowing you to load your config even if the remote log service is down. Logs will be emitted to stderr instead.
@ -171,33 +209,57 @@ format <encoder_module> {
```
- **message_key** The key for the message field of the log entry. Default: `msg`
- **level_key** The key for the level field of the log entry. Default: `level`
- **time_key** The key for the time field of the log entry. Default: `ts`
- **name_key** The key for the name field of the log entry (i.e. the name of the logger itself). Default: `name`
- **name_key** The key for the name field of the log entry. Default: `name`
- **caller_key** The key for the caller field of the log entry.
- **stacktrace_key** The key for the stacktrace field of the log entry.
- **line_ending** The line endings to use.
- **time_format** The format for timestamps. May be one of:
- **unix_seconds_float** Floating-point number of seconds since the Unix epoch; this is the default.
- **unix_milli_float** Floating-point number of milliseconds since the Unix epoch.
- **unix_nano** Integer number of nanoseconds since the Unix epoch.
- **iso8601** Example: `2006-01-02T15:04:05.000Z0700`
- **rfc3339** Example: `2006-01-02T15:04:05Z07:00`
- **rfc3339_nano** Example: `2006-01-02T15:04:05.999999999Z07:00`
- **wall** Example: `2006/01/02 15:04:05`
- **wall_milli** Example: `2006/01/02 15:04:05.000`
- **wall_nano** Example: `2006/01/02 15:04:05.000000000`
- **common_log** Example: `02/Jan/2006:15:04:05 -0700`
- **time_format** The format for timestamps.
Default: `wall_milli` if the format defaulted to `console`, `unix_seconds_float` otherwise.
May be one of:
- `unix_seconds_float` Floating-point number of seconds since the Unix epoch.
- `unix_milli_float` Floating-point number of milliseconds since the Unix epoch.
- `unix_nano` Integer number of nanoseconds since the Unix epoch.
- `iso8601` Example: `2006-01-02T15:04:05.000Z0700`
- `rfc3339` Example: `2006-01-02T15:04:05Z07:00`
- `rfc3339_nano` Example: `2006-01-02T15:04:05.999999999Z07:00`
- `wall` Example: `2006/01/02 15:04:05`
- `wall_milli` Example: `2006/01/02 15:04:05.000`
- `wall_nano` Example: `2006/01/02 15:04:05.000000000`
- `common_log` Example: `02/Jan/2006:15:04:05 -0700`
- Or, any compatible time layout string; see the [Go documentation](https://pkg.go.dev/time#pkg-constants) for full details.
Note that the parts of the format string are special constants for the layout; so `2006` is the year, `01` is the month, `Jan` is the month as a string, `02` is the day. Do not use the actual current date numbers in the format string.
- **time_local** Logs with the local system time rather than the default of UTC time.
- **duration_format** The format for durations. May be one of:
- **seconds** Floating-point number of seconds elapsed; this is the default.
- **nano** Integer number of nanoseconds elapsed.
- **string** Using Go's built-in string format, for example `1m32.05s` or `6.31ms`.
- **level_format** The format for levels. May be one of:
- **lower** Lowercase; this is the default.
- **upper** Uppercase.
- **color** Uppercase, with console colors.
- **duration_format** The format for durations.
Default: `seconds`.
May be one of:
- `seconds` Floating-point number of seconds elapsed.
- `nano` Integer number of nanoseconds elapsed.
- `string` Using Go's built-in string format, for example `1m32.05s` or `6.31ms`.
- **level_format** The format for levels.
Default: `color` if the format defaulted to `console`, `lower` otherwise.
May be one of:
- `lower` Lowercase.
- `upper` Uppercase.
- `color` Uppercase, with ANSI colors.
#### console
@ -244,6 +306,7 @@ Marks a field to be skipped from being encoded.
<field> delete
```
##### rename
Rename the key of a log field.
@ -252,6 +315,7 @@ Rename the key of a log field.
<field> rename <key>
```
##### replace
Marks a field to be replaced with the provided string at encoding time.
@ -260,13 +324,17 @@ Marks a field to be replaced with the provided string at encoding time.
<field> replace <replacement>
```
##### ip_mask
Masks IP addresses in the field using a CIDR mask, i.e. the number of bits from the IP to retain, starting from the left side. If the field is an array of strings (e.g. HTTP headers), each value in the array is masked. The value may be a comma separated string of IP addresses.
There is separate configuration for IPv4 and IPv6 addresses, since they have a different total number of bits.
Most commonly, the fields to filter would be `request>remote_ip` for the directly connecting client, `request>client_ip` for the parsed "real client" when [`trusted_proxies`](/docs/caddyfile/options#trusted-proxies) is configured, or `request>headers>X-Forwarded-For` if behind a reverse proxy.
Most commonly, the fields to filter would be:
- `request>remote_ip` for the directly connecting client
- `request>client_ip` for the parsed "real client" when [`trusted_proxies`](/docs/caddyfile/options#trusted-proxies) is configured
- `request>headers>X-Forwarded-For` if behind a reverse proxy
```caddy-d
<field> ip_mask {
@ -275,9 +343,10 @@ Most commonly, the fields to filter would be `request>remote_ip` for the directl
}
```
##### query
Marks a field to have one or more actions performed, to manipulate the query part of a URL field. Most commonly, the field to filter would be `request>uri`. The available actions are:
Marks a field to have one or more actions performed, to manipulate the query part of a URL field. Most commonly, the field to filter would be `request>uri`.
```caddy-d
<field> query {
@ -287,13 +356,18 @@ Marks a field to have one or more actions performed, to manipulate the query par
}
```
The available actions are:
- **delete** removes the given key from the query.
- **replace** replaces the value of the given query key with **replacement**. Useful to insert a redaction placeholder; you'll see that the query key was in the URL, but the value is hidden.
- **hash** replaces the value of the given query key with the first 4 bytes of the SHA-256 hash of the value, lowercase hexadecimal. Useful to obscure the value if it's sensitive, while being able to notice whether each request had a different value.
##### cookie
Marks a field to have one or more actions performed, to manipulate a `Cookie` HTTP header's value. Most commonly, the field to filter would be `request>headers>Cookie`. The available actions are:
Marks a field to have one or more actions performed, to manipulate a `Cookie` HTTP header's value. Most commonly, the field to filter would be `request>headers>Cookie`.
```caddy-d
<field> cookie {
@ -303,12 +377,17 @@ Marks a field to have one or more actions performed, to manipulate a `Cookie` HT
}
```
The available actions are:
- **delete** removes the given cookie by name from the header.
- **replace** replaces the value of the given cookie with **replacement**. Useful to insert a redaction placeholder; you'll see that the cookie was in the header, but the value is hidden.
- **hash** replaces the value of the given cookie with the first 4 bytes of the SHA-256 hash of the value, lowercase hexadecimal. Useful to obscure the value if it's sensitive, while being able to notice whether each request had a different value.
If many actions are defined for the same cookie name, only the first action will be applied.
##### regexp
Marks a field to have a regular expression replacement applied at encoding time. If the field is an array of strings (e.g. HTTP headers), each value in the array has replacements applied.
@ -321,6 +400,7 @@ The regular expression language used is RE2, included in Go. See the [RE2 syntax
In the replacement string, capture groups can be referenced with `${group}` where `group` is either the name or number of the capture group in the expression. Capture group `0` is the full regexp match, `1` is the first capture group, `2` is the second capture group, and so on.
##### hash
Marks a field to be replaced with the first 4 bytes (8 hex characters) of the SHA-256 hash of the value at encoding time. If the field is a string array (e.g. HTTP headers), each value in the array is hashed.
@ -337,30 +417,36 @@ Useful to obscure the value if it's sensitive, while being able to notice whethe
Enable access logging to the default logger.
In other words, by default this logs to the console or stderr, but this can be changed by reconfiguring the default logger with the [`log` global option](/docs/caddyfile/options#log):
In other words, by default this logs to `stderr`, but this can be changed by reconfiguring the `default` logger with the [`log` global option](/docs/caddyfile/options#log):
```caddy-d
log
```caddy
example.com {
log
}
```
Write logs to a file (with log rolling, which is enabled by default):
```caddy-d
log {
output file /var/log/access.log
```caddy
example.com {
log {
output file /var/log/access.log
}
}
```
Customize log rolling:
```caddy-d
log {
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
```caddy
example.com {
log {
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
}
```
@ -368,12 +454,14 @@ log {
Delete the `User-Agent` request header from the logs:
```caddy-d
log {
format filter {
wrap console
fields {
request>headers>User-Agent delete
```caddy
example.com {
log {
format filter {
wrap console
fields {
request>headers>User-Agent delete
}
}
}
}
@ -382,14 +470,16 @@ log {
Redact multiple sensitive cookies. (Note that some sensitive headers are logged with empty values by default; see the [`log_credentials` global option](/docs/caddyfile/options#log-credentials) to enable logging `Cookie` header values):
```caddy-d
log {
format filter {
wrap console
fields {
request>headers>Cookie cookie {
replace session REDACTED
delete secret
```caddy
example.com {
log {
format filter {
wrap console
fields {
request>headers>Cookie cookie {
replace session REDACTED
delete secret
}
}
}
}
@ -401,14 +491,16 @@ Mask the remote address from the request, keeping the first 16 bits (i.e. 255.25
Note that as of Caddy v2.7, both `remote_ip` and `client_ip` are logged, where `client_ip` is the "real IP" when [`trusted_proxies`](/docs/caddyfile/options#trusted-proxies) is configured:
```caddy-d
log {
format filter {
wrap console
fields {
request>remote_ip ip_mask {
ipv4 16
ipv6 32
```caddy
example.com {
log {
format filter {
wrap console
fields {
request>remote_ip ip_mask {
ipv4 16
ipv6 32
}
}
}
}
@ -416,23 +508,24 @@ log {
```
<span id="wildcard-logs" /> To write separate log files for each subdomain in a [wildcard site block](/docs/caddyfile/patterns#wildcard-certificates), by overriding `hostnames` for each logger:
<span id="wildcard-logs" /> To write separate log files for each subdomain in a [wildcard site block](/docs/caddyfile/patterns#wildcard-certificates), by overriding `hostnames` for each logger. This uses a [snippet](/docs/caddyfile/concepts#snippets) to avoid repetition:
```caddy
*.example.com {
(subdomain-log) {
log {
hostnames foo.example.com
output file /var/log/foo.example.com.log
hostnames {args[0]}
output file /var/log/{args[0]}.log
}
@foo host foo.example.com
}
*.example.com {
import subdomain-log foo.example.com
@foo host foo.example.com
handle @foo {
respond "foo"
}
log {
hostnames bar.example.com
output file /var/log/bar.example.com.log
}
import subdomain-log bar.example.com
@bar host bar.example.com
handle @bar {
respond "bar"

View file

@ -175,8 +175,14 @@ app2.example.com {
For a PHP site which does not use `index.php` as an entrypoint, you may fallback to emitting a `404` error instead. The error may be caught and handled with the [`handle_errors` directive](handle_errors):
```caddy-d
php_fastcgi localhost:9000 {
try_files {path} {path}/index.php =404
```caddy
example.com {
php_fastcgi localhost:9000 {
try_files {path} {path}/index.php =404
}
handle_errors {
respond "{err.status_code} {err.status_text}"
}
}
```

View file

@ -6,7 +6,7 @@ title: redir (Caddyfile directive)
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](/docs/caddyfile/directives#directive-order) (before [`rewrite`](/docs/caddyfile/directives/rewrite)).
This directive implies that a matched request is to be rejected as-is, and the client should try again at a different URL. For that reason, its [directive order](/docs/caddyfile/directives#directive-order) is very early.
## Syntax
@ -15,12 +15,18 @@ This directive implies that a matched request is to be rejected. It is ordered v
redir [<matcher>] <to> [<code>]
```
- **&lt;to&gt;** is the target location. Becomes the response's Location header.
- **&lt;to&gt;** is the target location. Becomes the response's [`Location` header <img src="/old/resources/images/external-link.svg" class="external-link">](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location).
- **&lt;code&gt;** is the HTTP status code to use for the redirect. Can be:
- A positive integer in the 3xx range, or 401
- `temporary` for a temporary redirect (302; default)
- `permanent` for a permanent redirect (301)
- A positive integer in the `3xx` range, or `401`
- `temporary` for a temporary redirect (`302`, this is the 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)
- A placeholder with a status code value
@ -29,24 +35,33 @@ redir [<matcher>] <to> [<code>]
Redirect all requests to `https://example.com`:
```caddy-d
redir https://example.com
```caddy
www.example.com {
redir https://example.com
}
```
Same, but preserve the existing URI by appending the [`{uri}` placeholder](/docs/caddyfile/concepts#placeholders):
```caddy-d
redir https://example.com{uri}
```caddy
www.example.com {
redir https://example.com{uri}
}
```
Same, but permanent:
```caddy-d
redir https://example.com{uri} permanent
```caddy
www.example.com {
redir https://example.com{uri} permanent
}
```
Redirect your old `/about-us` page to your new `/about` page:
```caddy-d
redir /about-us /about
```caddy
example.com {
redir /about-us /about
reverse_proxy localhost:9000
}
```

View file

@ -11,19 +11,22 @@ Manipulates or sets restrictions on the bodies of incoming requests.
```caddy-d
request_body [<matcher>] {
max_size <value>
max_size <value>
}
```
- **max_size** is the maximum size in bytes allowed for the request body. It accepts all size values supported by [go-humanize](https://pkg.go.dev/github.com/dustin/go-humanize#pkg-constants). Reads of more bytes will return an error with HTTP status 413.
- **max_size** is the maximum size in bytes allowed for the request body. It accepts all size values supported by [go-humanize](https://pkg.go.dev/github.com/dustin/go-humanize#pkg-constants). Reads of more bytes will return an error with HTTP status `413`.
## Examples
Limit request body sizes to 10 megabytes:
```caddy-d
request_body {
max_size 10MB
```caddy
example.com {
request_body {
max_size 10MB
}
reverse_proxy localhost:8080
}
```

View file

@ -8,6 +8,8 @@ Manipulates HTTP header fields on the request. It can set, add, and delete heade
If you intend to manipulate headers for proxying, use the [`header_up` subdirective](/docs/caddyfile/directives/reverse_proxy#header_up) of `reverse_proxy` instead, as those manipulations are proxy-aware.
To manipulate HTTP response headers, you may use the [`header`](header) directive.
## Syntax
@ -15,7 +17,9 @@ If you intend to manipulate headers for proxying, use the [`header_up` subdirect
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.
- **&lt;field&gt;** is the name of the header field.
With no prefix, the field is set (overwritten).
Prefix with `+` to add the field instead of overwriting (setting) the field if it already exists; header fields can appear more than once in a request.

View file

@ -18,7 +18,11 @@ respond [<matcher>] <status>|<body> [<status>] {
}
```
- **&lt;status&gt;** is the HTTP status code to write. If 103 (Early Hints), the response will be written without a body and the handler chain will continue. (HTTP 1xx responses are informational, not final.) Default: 200.
- **&lt;status&gt;** is the HTTP status code to write.
If `103` (Early Hints), the response will be written without a body and the handler chain will continue. (HTTP `1xx` responses are informational, not final.)
Default: `200`
- **&lt;body&gt;** is the response body to write.
@ -29,40 +33,49 @@ respond [<matcher>] <status>|<body> [<status>] {
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.
<aside class="tip">
Responding with an error status code is different than returning an error in the handler chain, which invokes error handlers internally.
Responding with an error status code is different than returning an error in the handler chain, which invokes error handlers internally.
</aside>
## Examples
Write a 200 status with an empty body to all health checks:
Write an empty 200 status with an empty body to all health checks, and a simple response body to all other requests:
```caddy-d
respond /health-check 200
```
Write a simple response body to all requests:
```caddy-d
respond "Hello, world!"
```caddy
example.com {
respond /health-check 200
respond "Hello, world!"
}
```
Write an error response and close the connection:
```caddy-d
respond /secret/* "Access denied" 403 {
close
<aside class="tip">
You might prefer to use the [`error` directive](error) instead, which triggers an error that can be handled with the [`handle_errors` directive](handle_errors).
</aside>
```caddy
example.com {
respond /secret/* "Access denied" 403 {
close
}
}
```
Write an HTML response, using [heredoc syntax](/docs/caddyfile/concepts#heredocs) to control whitespace, and also setting the `Content-Type` header to match the response body:
```caddy-d
header Content-Type text/html
respond <<HTML
<html>
<head><title>Foo</title></head>
<body>Foo</body>
</html>
HTML 200
```caddy
example.com {
header Content-Type text/html
respond <<HTML
<html>
<head><title>Foo</title></head>
<body>Foo</body>
</html>
HTML 200
}
```

View file

@ -530,7 +530,7 @@ transport http {
- **max_response_header** <span id="max_response_header"/> is the maximum amount of bytes to read from response headers. It accepts all formats supported by [go-humanize](https://github.com/dustin/go-humanize/blob/master/bytes.go). Default: `10MiB`.
- **proxy_protocol** <span id="proxy_protocol"/> enables [PROXY protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) (popularized by HAProxy) on the connection to the upstream, prepending the real client IP data. This is best paired with the [`servers > trusted_proxies` global option](/docs/caddyfile/options#trusted-proxies) if Caddy is behind another proxy. Versions `v1` and `v2` are supported. This should only be used if you know the upstream server is able to parse PROXY protocol. By default, this is disabled.
- **proxy_protocol** <span id="proxy_protocol"/> enables [PROXY protocol](https://github.com/haproxy/haproxy/blob/master/doc/proxy-protocol.txt) (popularized by HAProxy) on the connection to the upstream, prepending the real client IP data. This is best paired with the [`servers > trusted_proxies` global option](/docs/caddyfile/options#trusted-proxies) if Caddy is behind another proxy. Versions `v1` and `v2` are supported. This should only be used if you know the upstream server is able to parse PROXY protocol. By default, this is disabled.
- **dial_timeout** <span id="dial_timeout"/> is the maximum [duration](/docs/conventions#durations) to wait when connecting to the upstream socket. Default: `3s`.
@ -672,44 +672,54 @@ See the [`header`](/docs/caddyfile/matchers#header) request matcher for the supp
Reverse proxy all requests to a local backend:
```caddy-d
reverse_proxy localhost:9005
```caddy
example.com {
reverse_proxy localhost:9005
}
```
[Load-balance](#load-balancing) all requests [between 3 backends](#upstreams):
```caddy-d
reverse_proxy node1:80 node2:80 node3:80
```caddy
example.com {
reverse_proxy node1:80 node2:80 node3:80
}
```
Same, but only requests within `/api`, and sticky by using the [`cookie` policy](#lb_policy):
```caddy-d
reverse_proxy /api/* node1:80 node2:80 node3:80 {
lb_policy cookie api_sticky
```caddy
example.com {
reverse_proxy /api/* node1:80 node2:80 node3:80 {
lb_policy cookie api_sticky
}
}
```
Using [active health checks](#active-health-checks) to determine which backends are healthy, and enabling [retries](#lb_try_duration) on failed connections, holding the request until a healthy backend is found:
```caddy-d
reverse_proxy node1:80 node2:80 node3:80 {
health_uri /healthz
lb_try_duration 5s
```caddy
example.com {
reverse_proxy node1:80 node2:80 node3:80 {
health_uri /healthz
lb_try_duration 5s
}
}
```
Configure some [transport options](#transports):
```caddy-d
reverse_proxy localhost:8080 {
transport http {
dial_timeout 2s
response_header_timeout 30s
```caddy
example.com {
reverse_proxy localhost:8080 {
transport http {
dial_timeout 2s
response_header_timeout 30s
}
}
}
```
@ -717,19 +727,23 @@ reverse_proxy localhost:8080 {
Reverse proxy to an [HTTPS upstream](#https):
```caddy-d
reverse_proxy https://example.com {
header_up Host {upstream_hostport}
```caddy
example.com {
reverse_proxy https://example.com {
header_up Host {upstream_hostport}
}
}
```
Reverse proxy to an HTTPS upstream, but [⚠️ disable TLS verification](#tls_insecure_skip_verify). this is NOT RECOMMENDED, since it disables all security checks that HTTPS offers; proxying over HTTP in private networks is preferred if possible, because it avoids the false sense of security:
Reverse proxy to an HTTPS upstream, but [⚠️ disable TLS verification](#tls_insecure_skip_verify). This is NOT RECOMMENDED, since it disables all security checks that HTTPS offers; proxying over HTTP in private networks is preferred if possible, because it avoids the false sense of security:
```caddy-d
reverse_proxy 10.0.0.1:443 {
transport http {
tls_insecure_skip_verify
```caddy
example.com {
reverse_proxy 10.0.0.1:443 {
transport http {
tls_insecure_skip_verify
}
}
}
```
@ -737,46 +751,54 @@ reverse_proxy 10.0.0.1:443 {
Instead you may establish trust with the upstream by explicitly [trusting the upstream's certificate](#tls_trusted_ca_certs), and (optionally) setting TLS-SNI to match the hostname in the upstream's certificate:
```caddy-d
reverse_proxy 10.0.0.1:443 {
transport http {
tls_trusted_ca_certs /path/to/cert.pem
tls_server_name app.example.com
```caddy
example.com {
reverse_proxy 10.0.0.1:443 {
transport http {
tls_trusted_ca_certs /path/to/cert.pem
tls_server_name app.example.com
}
}
}
```
[Strip a path prefix](/docs/caddyfile/directives/handle_path) before proxying; but be aware of the [subfolder problem <img src="/old/resources/images/external-link.svg" class="external-link">](https://caddy.community/t/the-subfolder-problem-or-why-cant-i-reverse-proxy-my-app-into-a-subfolder/8575):
[Strip a path prefix](handle_path) before proxying; but be aware of the [subfolder problem <img src="/old/resources/images/external-link.svg" class="external-link">](https://caddy.community/t/the-subfolder-problem-or-why-cant-i-reverse-proxy-my-app-into-a-subfolder/8575):
```caddy-d
handle_path /prefix/* {
reverse_proxy localhost:9000
```caddy
example.com {
handle_path /prefix/* {
reverse_proxy localhost:9000
}
}
```
Replace a path prefix before proxying, using a [rewrite](/docs/caddyfile/directives/rewrite):
Replace a path prefix before proxying, using a [`rewrite`](/docs/caddyfile/directives/rewrite):
```caddy-d
handle_path /old-prefix/* {
rewrite * /new-prefix{path}
reverse_proxy localhost:9000
```caddy
example.com {
handle_path /old-prefix/* {
rewrite * /new-prefix{path}
reverse_proxy localhost:9000
}
}
```
`X-Accel-Redirect` support, i.e. serving static files as requested, by [intercepting the response](#intercepting-responses):
```caddy-d
reverse_proxy localhost:8080 {
@accel header X-Accel-Redirect *
handle_response @accel {
root * /path/to/private/files
rewrite * {rp.header.X-Accel-Redirect}
method * GET
file_server
```caddy
example.com {
reverse_proxy localhost:8080 {
@accel header X-Accel-Redirect *
handle_response @accel {
root * /path/to/private/files
rewrite * {rp.header.X-Accel-Redirect}
method * GET
file_server
}
}
}
```
@ -784,13 +806,15 @@ reverse_proxy localhost:8080 {
Custom error page for errors from upstream, by [intercepting error responses](#intercepting-responses) by status code:
```caddy-d
reverse_proxy localhost:8080 {
@error status 500 503
handle_response @error {
root * /path/to/error/pages
rewrite * /{rp.status_code}.html
file_server
```caddy
example.com {
reverse_proxy localhost:8080 {
@error status 500 503
handle_response @error {
root * /path/to/error/pages
rewrite * /{rp.status_code}.html
file_server
}
}
}
```
@ -798,18 +822,22 @@ reverse_proxy localhost:8080 {
Get backends [dynamically](#dynamic-upstreams) from [`A`/`AAAA` record](#aaaaa) DNS queries:
```caddy-d
reverse_proxy {
dynamic a example.com 9000
```caddy
example.com {
reverse_proxy {
dynamic a example.com 9000
}
}
```
Get backends [dynamically](#dynamic-upstreams) from [`SRV` record](#srv) DNS queries:
```caddy-d
reverse_proxy {
dynamic srv _api._tcp.example.com
```caddy
example.com {
reverse_proxy {
dynamic srv _api._tcp.example.com
}
}
```

View file

@ -4,11 +4,15 @@ title: rewrite (Caddyfile directive)
# rewrite
Rewrites the request internally. A rewrite changes some or all of the request URI. Note that the URI does not include scheme or authority (host & port), and clients typically do not send fragments. Thus, this directive is mostly used for path and query string manipulation.
Rewrites the request URI internally.
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 as only the first matching rewrite will be executed.
A rewrite changes some or all of the request URI. Note that the URI does not include scheme or authority (host & port), and clients typically do not send fragments. Thus, this directive is mostly used for **path** and **query** string manipulation.
Because `rewrite` essentially performs an internal redirect, the Caddyfile adapter will not fold any subsequent, adjacent handlers into the same route if their matchers happen to be exactly the same. This allows the matchers of the next handlers to be deferred until after the rewrite. In other words, a matcher that matches a request before the `rewrite` might not match the same request after the `rewrite`. If you want your `rewrite` to share a route with other handlers, use the [`route`](route) or [`handle`](handle) directives.
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 as only the first matching rewrite will be executed.
A [request matcher](/docs/caddyfile/matchers) that matches a request before the `rewrite` might not match the same request after the `rewrite`. If you want your `rewrite` to share a route with other handlers, use the [`route`](route) or [`handle`](handle) directives.
## Syntax
@ -20,36 +24,55 @@ rewrite [<matcher>] <to>
- **&lt;to&gt;** is the URI to rewrite the request to. Only the components of the URI (path or query string) that are specified in the rewrite will be operated on. 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:
```caddy-d
rewrite * /foo.html
```
Replace the query string on API requests with `a=b`, leaving the path unchanged:
```caddy-d
rewrite /api/* ?a=b
```
Preserve the existing query string and add a key-value pair:
```caddy-d
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:
```caddy-d
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:
- [`uri`](uri) manipulates a URI (strip prefix, suffix, or substring replacement).
- [`try_files`](try_files) rewrites the request based on the existence of files.
## Examples
Rewrite all requests to `index.html`, leaving any query string unchanged:
```caddy
example.com {
rewrite * /index.html
}
```
Prefixing all requests with `/api`, preserving the rest of the URI, then reverse proxying to an app:
```caddy
api.example.com {
rewrite * /api{uri}
reverse_proxy localhost:8080
}
```
Replace the query string on API requests with `a=b`, leaving the path unchanged:
```caddy
example.com {
rewrite * ?a=b
}
```
For only requests to `/api/`, preserve the existing query string and add a key-value pair:
```caddy
example.com {
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:
```caddy
example.com {
rewrite * /index.php?{query}&p={path}
}
```

View file

@ -8,7 +8,7 @@ Sets the root path of the site, used by various matchers and directives that acc
Specifically, this directive sets the `{http.vars.root}` placeholder. It is mutually exclusive to other `root` directives in the same block, so it is safe to define multiple roots with matchers that intersect: they will not cascade and overwrite each other.
This directive does not automatically enable serving static files, so it is often used in conjunction with the [`file_server` directive](/docs/caddyfile/directives/file_server) or the [`php_fastcgi` directive](/docs/caddyfile/directives/php_fastcgi).
This directive does not automatically enable serving static files, so it is often used in conjunction with the [`file_server` directive](file_server) or the [`php_fastcgi` directive](php_fastcgi).
## Syntax
@ -21,16 +21,30 @@ root [<matcher>] <path>
Note that the `<path>` argument could be confused by the parser for a [matcher token](/docs/caddyfile/matchers#syntax) if it begins with `/`. To disambiguate, specify a wildcard matcher token (`*`). See examples below.
## Examples
Set the site root to `/home/user/public_html` for all requests:
Set the site root to `/home/bob/public_html` (assumes Caddy is running as the user `bob`):
<aside class="tip">
If you're running Caddy as a systemd service, reading files from `/home` will not work, because the `caddy` user does not have "executable" permission on the `/home` directory (necessary for traversal). It's recommended that you place your files in `/srv` or `/var/www/html` instead.
</aside>
(Note that a [wildcard matcher](/docs/caddyfile/matchers#wildcard-matchers) is required here because the first argument is ambiguous with a [path matcher](/docs/caddyfile/matchers#path-matchers).)
```caddy-d
root * /home/user/public_html
root * /home/bob/public_html
```
<aside class="tip">
Note that a [wildcard matcher](/docs/caddyfile/matchers#wildcard-matchers) is required here because the first argument is ambiguous with a [path matcher](/docs/caddyfile/matchers#path-matchers).
</aside>
Set the site root to `public_html` (relative to current working directory) for all requests:
(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.)
@ -45,9 +59,11 @@ Change the site root only for requests in `/foo/*`:
root /foo/* /home/user/public_html/foo
```
The `root` directive is commonly paired with [`file_server`](/docs/caddyfile/directives/file_server) to serve static files and/or with [`php_fastcgi`](/docs/caddyfile/directives/php_fastcgi) to serve a PHP site:
The `root` directive is commonly paired with [`file_server`](file_server) to serve static files and/or with [`php_fastcgi`](php_fastcgi) to serve a PHP site:
```caddy-d
root * /home/user/public_html
file_server
```caddy
example.com {
root * /srv
file_server
}
```

View file

@ -29,58 +29,78 @@ The `route` directive is helpful in certain advanced use cases or edge cases to
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.
While the [built-in order](/docs/caddyfile/directives#directive-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.
To illustrate, consider the case of two terminating handlers: [`redir`](redir) and [`file_server`](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. So 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!):
```caddy
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:
```caddy
example.com
route {
example.com {
file_server /specific.html
redir https://anothersite.com{uri}
}
```
The problem is that after the [directives are sorted](/docs/caddyfile/directives#sorting-algorithm), `redir` comes before `file_server`.
But in this case the matcher for `redir` (an implicit [`*`](/docs/caddyfile/matchers#wildcard-matchers)) 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, to ensure that `file_server` is executed before `redir`:
```caddy
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 `route` 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.
## Similar directives
There are other directives that can wrap HTTP handler directives, but each has its use depending on the behavior you want to convey:
- [`handle`](handle) wraps other directives like `route` does, but with two distinctions: 1) handle blocks are mutually exclusive to each other, and 2) directives within a handle are [re-ordered](/docs/caddyfile/directives#directive-order) normally.
- [`handle_path`](handle_path) does the same as `handle`, but it strips a prefix from the request before running its handlers.
- [`handle_errors`](handle_errors) is like `handle`, but is only invoked when Caddy encounters an error during request handling.
## Examples
Strip `/api` prefix from request path just before proxying all API requests to a backend:
Proxy requests to `/api` as-is, and rewrite all other requests based on whether they match a file on disk, otherwise `/index.html`. Then that file is served.
```caddy-d
route /api/* {
uri strip_prefix /api
reverse_proxy localhost:9000
Since [`try_files`](try_files) has a higher directive order than [`reverse_proxy`](reverse_proxy), then it would normally get sorted higher and run first; this would cause the API requests to all get rewritten to `/index.html` and fail to match `/api*`, so none of them would get proxied and instead would result in a `404` from [`file_server`](file_server). Wrapping it all in a `route` ensures that `reverse_proxy` always runs first, before the request is rewritten.
```caddy
example.com {
root * /srv
route {
reverse_proxy /api* localhost:9000
try_files {path} /index.html
file_server
}
}
```
<aside class="tip">
This is not the only solution to this problem. You could also use a pair of [`handle`](handle) blocks, with the first matching `/api*` to `reverse_proxy`, and the second acting as a fallback and serving the files. See [this example](/docs/caddyfile/patterns#single-page-apps-spas) of an SPA.
</aside>

View file

@ -20,8 +20,15 @@ skip_log [<matcher>]
Skip access logging for static files stored in a subpath:
```caddy-d
skip_log /static*
```caddy
example.com {
root * /srv
log
skip_log /static*
file_server
}
```

View file

@ -17,17 +17,43 @@ templates [<matcher>] {
}
```
- **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.
- **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. You can change them if they interfere with the rest of your document.
Default: `{{printf "{{ }}"}}`.
- **root** is the site root, when using functions that access the file system.
Defaults to the site root set by the [`root`](root) directive, or the current working directory if not set.
Documentation for the built-in template functions can be found in [templates module](/docs/modules/http.handlers.templates#docs).
## Examples
Enable templates on all requests:
For a complete example of a site using templates to serve markdown, take a look at the source for [this very website](https://github.com/caddyserver/website)! Specifically, take a look at the [`Caddyfile`](https://github.com/caddyserver/website/blob/master/Caddyfile) and [`src/docs/index.html`](https://github.com/caddyserver/website/blob/master/src/docs/index.html).
```caddy-d
templates
Enable templates for a static site:
```caddy
example.com {
root * /srv
templates
file_server
}
```
For a complete example of a site using templates to serve markdown, take a look at the source for [this very website](https://github.com/caddyserver/website)! Specifically, take a look at the [`Caddyfile`](https://github.com/caddyserver/website/blob/master/Caddyfile) and [`src/docs/index.html`](https://github.com/caddyserver/website/blob/master/src/docs/index.html).
To serve a simple static response using a template, make sure to set `Content-Type`:
```caddy
example.com {
header Content-Type text/plain
templates
respond "Current year is: {{printf "{{"}}now | date "2006"{{printf "}}"}}"
}
```

View file

@ -168,7 +168,7 @@ These issuers come standard with the `tls` directive:
Obtains certificates using the ACME protocol. Note that `acme` is a default issuer (using Let's Encrypt), so configuring it explicitly is usually unnecessary.
```caddy
```caddy-d
... acme [<directory_url>] {
dir <directory_url>
test_dir <test_directory_url>
@ -253,7 +253,7 @@ Obtains certificates using the ACME protocol. Note that `acme` is a default issu
Obtains certificates using the ACME protocol, specifically with ZeroSSL. Note that `zerossl` is a default issuer, so configuring it explicitly is usually unnecessary.
```caddy
```caddy-d
... zerossl [<api_key>] {
...
}
@ -269,7 +269,7 @@ When explicitly configuring `zerossl`, configuring an `email` is required so tha
Obtains certificates from an internal certificate authority.
```caddy
```caddy-d
... internal {
ca <name>
lifetime <duration>
@ -324,66 +324,82 @@ get_certificate http <url>
## Examples
Use a custom certificate and key:
Use a custom certificate and key. The certificate should have [SANs](https://en.wikipedia.org/wiki/Subject_Alternative_Name) that match the site address:
```caddy-d
tls cert.pem key.pem
```caddy
example.com {
tls cert.pem key.pem
}
```
Use locally-trusted certificates for all hosts on the current site block, rather than public certificates via ACME / Let's Encrypt (useful in dev environments):
Use [locally-trusted](/docs/automatic-https#local-https) certificates for all hosts on the current site block, rather than public certificates via ACME / Let's Encrypt (useful in dev environments):
```caddy-d
tls internal
```caddy
example.com {
tls internal
}
```
Use locally-trusted certificates, but managed on-demand instead of in the background:
Use locally-trusted certificates, but managed [On-Demand](/docs/automatic-https#on-demand-tls) instead of in the background. This allows you to point any domain at your Caddy instance and have it automatically provision a certificate for you. This SHOULD NOT be used if your Caddy instance is publicly accessible, since an attacker could use it to exhaust your server's resources:
```caddy-d
tls internal {
on_demand
```caddy
https:// {
tls internal {
on_demand
}
}
```
Use custom options for the internal CA (cannot use the `tls internal` shortcut):
```caddy-d
tls {
issuer internal {
ca foo
```caddy
example.com {
tls {
issuer internal {
ca foo
}
}
}
```
Specify an email address for your ACME account (but if only one email is used for all sites, we recommend the `email` [global option](/docs/caddyfile/options) instead):
```caddy-d
tls your@email.com
```
Enable the DNS challenge for a domain managed on Cloudflare with account credentials in an environment variable:
```caddy-d
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
```caddy
example.com {
tls your@email.com
}
```
Get the certificate chain via HTTP, instead of having Caddy manage it:
Enable the DNS challenge for a domain managed on Cloudflare with account credentials in an environment variable. This unlocks wildcard certificate support, which requires DNS validation:
```caddy-d
tls {
get_certificate http http://localhost:9007/certs
```caddy
*.example.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
}
```
Get the certificate chain via HTTP, instead of having Caddy manage it. Note that [`get_certificate`](#certificate-managers) implies [`on_demand`](#on_demand) is enabled, fetching certificates using a module instead of triggering ACME issuance:
```caddy
https:// {
tls {
get_certificate http http://localhost:9007/certs
}
}
```
Enable TLS Client Authentication and require clients to present a valid certificate that is verified against all the provided CA's via `trusted_ca_cert_file`
```caddy-d
tls {
client_auth {
mode require_and_verify
trusted_ca_cert_file ../caddy.ca.cer
trusted_ca_cert_file ../root.ca.cer
```caddy
example.com {
tls {
client_auth {
mode require_and_verify
trusted_ca_cert_file ../caddy.ca.cer
trusted_ca_cert_file ../root.ca.cer
}
}
}
```

View file

@ -4,12 +4,10 @@ title: tracing (Caddyfile directive)
# tracing
It provides integration with OpenTelemetry tracing facilities.
Enables integration with OpenTelemetry tracing facilities, using [`opentelemetry-go` <img src="/old/resources/images/external-link.svg" class="external-link">](https://github.com/open-telemetry/opentelemetry-go).
When enabled, it will propagate an existing trace context or initialize a new one.
It is based on [github.com/open-telemetry/opentelemetry-go](https://github.com/open-telemetry/opentelemetry-go).
It uses [gRPC](https://github.com/grpc/) as an exporter protocol and W3C [tracecontext](https://www.w3.org/TR/trace-context/) and [baggage](https://www.w3.org/TR/baggage/) as propagators.
The trace ID is added to [access logs](/docs/caddyfile/directives/log) as the standard `traceID` field.
@ -47,11 +45,20 @@ export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://my-otlp-endpoint:55680
Here is a **Caddyfile** example:
```caddy-d
handle /example* {
tracing {
span example
```caddy
example.com {
handle /api* {
tracing {
span api
}
reverse_proxy localhost:8081
}
handle {
tracing {
span app
}
reverse_proxy localhost:8080
}
reverse_proxy 127.0.0.1:8081
}
```

View file

@ -17,13 +17,16 @@ try_files <files...> {
- **<files...>** is the list of files to try. The URI path 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), and [glob patterns](https://pkg.go.dev/path/filepath#Match) will be expanded.
To match directories, append a trailing forward slash `/` to the path. All file paths are relative to the site [root](root), and [glob patterns](https://pkg.go.dev/path/filepath#Match) will be expanded.
Each argument may also contain a query string, in which case the query string will also be changed if it matches that particular file.
If the `try_policy` is `first_exist` (the default), then the last item in the list may be a number prefixed by `=` (e.g. `=404`), which as a fallback, will emit an error with that code; the error can be caught and handled with [`handle_errors`](/docs/caddyfile/directives/handle_errors).
If the `try_policy` is `first_exist` (the default), then the last item in the list may be a number prefixed by `=` (e.g. `=404`), which as a fallback, will emit an error with that code; the error can be caught and handled with [`handle_errors`](handle_errors).
- **policy** is the policy for choosing the file among the list of files.
Default: `first_exist`
- **policy** is the policy for choosing the file among the list of files. Default: `first_exist`
## Expanded form
@ -40,15 +43,16 @@ Note that this directive does not accept a matcher token. If you need more compl
See the [`file` matcher](/docs/caddyfile/matchers#file) for more details.
## Examples
If the request does not match any static files, rewrite to an index/router file:
If the request does not match any static files, rewrite to your PHP index/router entrypoint:
```caddy-d
try_files {path} /index.php
```
Same, but adding the original path to the query string:
Same, but adding the original path to the query string (required by some legacy PHP apps):
```caddy-d
try_files {path} /index.php?{query}&p={path}
@ -60,7 +64,7 @@ Same, but also match directories:
try_files {path} {path}/ /index.php?{query}&p={path}
```
Attempt to rewrite to a file or directory if it exists, otherwise emit a 404 error (which can be caught and handled with [`handle_errors`](/docs/caddyfile/directives/handle_errors)):
Attempt to rewrite to a file or directory if it exists, otherwise emit a 404 error (which can be caught and handled with [`handle_errors`](handle_errors)):
```caddy-d
try_files {path} {path}/ =404

View file

@ -21,12 +21,19 @@ uri [<matcher>] path_regexp <target> <replacement>
```
- The first (non-matcher) argument specifies the operation:
- **strip_prefix** strips the prefix from the path.
- **strip_suffix** strips the suffix from the path.
- **replace** performs a substring replacement across the whole URI.
- **path_regexp** performs a regular expression replacement on the path portion of the URI.
- **&lt;target&gt;** is the prefix, suffix, or search string/regular expression. If a prefix, the leading forward slash may be omitted, since paths always start with a forward slash.
- **&lt;replacement&gt;** is the replacement string (only valid with `replace` and `path_regexp`). Supports using capture groups with `$name` or `${name}` syntax, or with a number for the index, such as `$1`. See the [Go documentation](https://golang.org/pkg/regexp/#Regexp.Expand) for details.
- **&lt;limit&gt;** is an optional limit to the maximum number of replacements (only valid with `replace`).
URI mutations occur on the normalized or unescaped form of the URI. However, escape sequences can be used in the prefix or suffix patterns to match only those literal escapes at those positions in the request path. For example, `uri strip_prefix /a/b` will rewrite both `/a/b/c` and `/a%2Fb/c` to `/c`; and `uri strip_prefix /a%2Fb` will rewrite `/a%2Fb/c` to `/c`, but won't match `/a/b/c`.
@ -38,6 +45,7 @@ The URI path is cleaned of directory traversal dots before modifications. Additi
Some other directives can also manipulate the request URI.
- [`rewrite`](rewrite) changes the entire path and query to a new value instead of partially changing the value.
- [`handle_path`](handle_path) does the same as [`handle`](handle), but it strips a prefix from the request before running its handlers. Can be used instead of `uri strip_prefix` to eliminate one extra line of configuration in many cases.

View file

@ -27,11 +27,13 @@ vars [<matcher>] [<name> <value>] {
To set a single variable, the value being conditional based on the request path, then responding with the value:
```caddy-d
vars /foo* isFoo "yep"
vars isFoo "nope"
```caddy
example.com {
vars /foo* isFoo "yep"
vars isFoo "nope"
respond {vars.isFoo}
respond {vars.isFoo}
}
```
To set multiple variables, each converted to the appropriate scalar type: