mirror of
https://github.com/caddyserver/website.git
synced 2025-04-21 12:36:16 -04:00
2.5.2 docs (#247)
* docs: Changes for v2.5.2 release * docs: Remove -X POST Curl automatically uses POST for -d and --data-binary. I intentionally left it in to be explicit to learners, but maybe best practices are better. * api: /adapt endpoint and Etag usage * api: Minor tweaks * Alright fine * Clarify Etag usage * CEL embedded matchers * Oops * Lots more adjustments Co-authored-by: Francis Lavoie <lavofr@gmail.com>
This commit is contained in:
parent
522d1961d1
commit
7819a84e59
30 changed files with 529 additions and 164 deletions
|
@ -68,7 +68,6 @@ Save this to a JSON file:
|
|||
Then upload it:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
</code></pre>
|
||||
|
@ -104,7 +103,6 @@ Let's change our welcome message from "Hello world!" to something a little more
|
|||
Save the config file, then update Caddy's active configuration by running the same POST request again:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
</code></pre>
|
||||
|
@ -130,15 +128,18 @@ Using the request URI's path, we can traverse into the config structure and upda
|
|||
|
||||
<pre><code class="cmd bash">curl \
|
||||
localhost:2019/config/apps/http/servers/example/routes/0/handle/0/body \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"Work smarter, not harder."'
|
||||
</code></pre>
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
Every time you change the config using the API, Caddy persists a copy of the new config so you can <a href="/docs/command-line#caddy-run"><b>--resume</b> it later</a>!
|
||||
|
||||
Every time you change the config using the API, Caddy persists a copy of the new config so you can [**--resume** it later](/docs/command-line#caddy-run)!
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
You can verify that it worked with a similar GET request, for example:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/config/apps/http/servers/example/routes</code></pre>
|
||||
|
@ -149,10 +150,14 @@ You should see:
|
|||
[{"handle":[{"body":"Work smarter, not harder.","handler":"static_response"}]}]
|
||||
```
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
You can use the <a href="https://stedolan.github.io/jq/">jq command</a> to prettify JSON output: <b><code>curl ... | jq</code></b>
|
||||
|
||||
You can use the [`jq` command](https://stedolan.github.io/jq/) to prettify JSON output: **`curl ... | jq`**
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<aside class="complete">Traverse config</aside>
|
||||
|
||||
**Important note:** This should be obvious, but once you use the API to make a change that is not in your original config file, your config file becomes obsolete. There are a few ways to handle this:
|
||||
|
@ -171,7 +176,6 @@ We can give our handler object an [`@id` tag](/docs/api#using-id-in-json) to mak
|
|||
|
||||
<pre><code class="cmd bash">curl \
|
||||
localhost:2019/config/apps/http/servers/example/routes/0/handle/0/@id \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"msg"'
|
||||
</code></pre>
|
||||
|
@ -186,10 +190,14 @@ This adds a property to our handler object: `"@id": "msg"`, so it now looks like
|
|||
}
|
||||
```
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
<b>@id</b> tags can go in any object and can have any primitive value (usually a string). <a href="/docs/api#using-id-in-json">Learn more</a>
|
||||
|
||||
**@id** tags can go in any object and can have any primitive value (usually a string). [Learn more](/docs/api#using-id-in-json)
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
We can then access it directly:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/id/msg</code></pre>
|
||||
|
@ -198,7 +206,6 @@ And now we can change the message with a shorter path:
|
|||
|
||||
<pre><code class="cmd bash">curl \
|
||||
localhost:2019/id/msg/body \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"Some shortcuts are good."'
|
||||
</code></pre>
|
||||
|
|
|
@ -42,6 +42,12 @@ To get started with the API, try our [API tutorial](/docs/api-tutorial) or, if y
|
|||
- **[Using `@id` in JSON](#using-id-in-json)**
|
||||
Easily traverse into the config structure
|
||||
|
||||
- **[Concurrent config changes](#concurrent-config-changes)**
|
||||
Avoid collisions and data loss when making unsynchronized changes to config
|
||||
|
||||
- **[POST /adapt](#post-adapt)**
|
||||
Adapts a configuration to JSON without running it
|
||||
|
||||
- **[GET /pki/ca/<id>](#get-pkicaid)**
|
||||
Returns information about a particular [PKI app](/docs/json/apps/pki/) CA
|
||||
|
||||
|
@ -64,13 +70,13 @@ If the new config is the same as the current one, no reload will occur. To force
|
|||
|
||||
Set a new active configuration:
|
||||
|
||||
<pre><code class="cmd bash">curl -X POST "http://localhost:2019/load" \
|
||||
<pre><code class="cmd bash">curl "http://localhost:2019/load" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json</code></pre>
|
||||
|
||||
Note: curl's `-d` flag removes newlines, so if your config format is sensitive to line breaks (e.g. the Caddyfile), use `--data-binary` instead:
|
||||
|
||||
<pre><code class="cmd bash">curl -X POST "http://localhost:2019/load" \
|
||||
<pre><code class="cmd bash">curl "http://localhost:2019/load" \
|
||||
-H "Content-Type: text/caddyfile" \
|
||||
--data-binary @Caddyfile</code></pre>
|
||||
|
||||
|
@ -152,14 +158,14 @@ baseSlice = append(baseSlice, newElems...)
|
|||
|
||||
Add a listener address:
|
||||
|
||||
<pre><code class="cmd bash">curl -X POST \
|
||||
<pre><code class="cmd bash">curl \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '":8080"' \
|
||||
"http://localhost:2019/config/apps/http/servers/myserver/listen"</code></pre>
|
||||
|
||||
Add multiple listener addresses:
|
||||
|
||||
<pre><code class="cmd bash">curl -X POST \
|
||||
<pre><code class="cmd bash">curl \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '[":8080", ":5133"]' \
|
||||
"http://localhost:2019/config/apps/http/servers/myserver/listen/..."</code></pre>
|
||||
|
@ -237,6 +243,47 @@ but with an ID, the path becomes
|
|||
|
||||
which is much easier to remember and write by hand.
|
||||
|
||||
## Concurrent config changes
|
||||
|
||||
<aside class="tip">
|
||||
|
||||
This section is for all `/config/` endpoints. It is experimental and subject to change.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
Caddy's config API provides [ACID guarantees](https://en.wikipedia.org/wiki/ACID) for individual requests, but changes that involve more than a single request are subject to collisions or data loss if not properly synchronized.
|
||||
|
||||
For example, two clients may `GET /config/foo` at the same time, make an edit within that scope (config path), then call `POST|PUT|PATCH|DELETE /config/foo/...` at the same time to apply their changes, resulting in a collision: either one will overwrite the other, or the second might leave the config in an unintended state since it was applied to a different version of the config than it was prepared against. This is because the changes are not aware of each other.
|
||||
|
||||
Caddy's API does not support transactions spanning multiple requests, and HTTP is a stateless protocol. However, you can use the `Etag` trailer and `If-Match` header to detect and prevent collisions for any and all changes as a kind of optimistic concurrency control. This is useful if there is any chance that you are using Caddy's `/config/...` endpoints concurrently without synchronization. All responses to `GET /config/...` requests have an HTTP trailer called `Etag` that contains the path and a hash of the contents in that scope (e.g. `Etag: "/config/apps/http/servers 65760b8e"`). Simply set the `If-Match` header on a mutative request to that of an Etag trailer from a previous `GET` request.
|
||||
|
||||
The basic algorithm for this is as follows:
|
||||
|
||||
1. Perform a `GET` request to any scope `S` within the config. Hold onto the `Etag` trailer of the response.
|
||||
2. Make your desired change on the returned config.
|
||||
3. Perform a `POST|PUT|PATCH|DELETE` request within scope `S`, setting the `If-Match` header to the recent `Etag` value.
|
||||
4. If the response is HTTP 412 (Precondition Failed), repeat from step 1, or give up after too many attempts.
|
||||
|
||||
This algorithm safely allows multiple, overlapping changes to Caddy's configuration without explicit synchronization. It is designed so that simultaneous changes to different parts of the config don't require a retry: only changes that overlap the same scope of the config can possibly cause a collision and thus require a retry.
|
||||
|
||||
|
||||
## POST /adapt
|
||||
|
||||
Adapts a configuration to Caddy JSON without loading or running it. If successful, the resulting JSON document is returned in the response body.
|
||||
|
||||
The Content-Type header is used to specify the configuration format in the same way that [/load](#post-load) works. For example, to adapt a Caddyfile, set `Content-Type: text/caddyfile`.
|
||||
|
||||
This endpoint will adapt any configuration format as long as the associated [config adapter](/docs/config-adapters) is plugged in to your Caddy build.
|
||||
|
||||
### Examples
|
||||
|
||||
Adapt a Caddyfile to JSON:
|
||||
|
||||
<pre><code class="cmd bash">curl "http://localhost:2019/adapt" \
|
||||
-H "Content-Type: text/caddyfile" \
|
||||
--data-binary @Caddyfile</code></pre>
|
||||
|
||||
|
||||
## GET /pki/ca/<id>
|
||||
|
||||
|
@ -278,16 +325,15 @@ Returns the current status of the configured reverse proxy upstreams (backends)
|
|||
|
||||
<pre><code class="cmd"><span class="bash">curl "http://localhost:2019/reverse_proxy/upstreams" | jq</span>
|
||||
[
|
||||
{"address": "10.0.1.1:80", "healthy": true, "num_requests": 4, "fails": 2},
|
||||
{"address": "10.0.1.2:80", "healthy": true, "num_requests": 5, "fails": 4},
|
||||
{"address": "10.0.1.3:80", "healthy": true, "num_requests": 3, "fails": 3}
|
||||
{"address": "10.0.1.1:80", "num_requests": 4, "fails": 2},
|
||||
{"address": "10.0.1.2:80", "num_requests": 5, "fails": 4},
|
||||
{"address": "10.0.1.3:80", "num_requests": 3, "fails": 3}
|
||||
]</code></pre>
|
||||
|
||||
Each entry in the JSON array is a configured [upstream](/docs/json/apps/http/servers/routes/handle/reverse_proxy/upstreams/) stored in the global upstream pool.
|
||||
|
||||
- **address** is the dial address of the upstream. For SRV upstreams, this is the `lookup_srv` DNS name.
|
||||
- **healthy** reflects whether Caddy believes the upstream to be healthy or not. Note that "health" is a distinct concept from "availability". An unhealthy backend will always be unavailable, but a healthy backend might not be available. Health is a global characteristic regardless of specific reverse proxy handler configuration, whereas availability is determined by the configuration of the specific reverse proxy handler. For example, a healthy backend would be unavailable if the handler is configured to only allow N requests at a time and it currently has N active requests. The "healthy" property does not reflect availability.
|
||||
- **num_requests** is the amount of active requests currently being handled by the upstream.
|
||||
- **fails** the current number of failed requests remembered, as configured by passive health checks.
|
||||
|
||||
If your goal is to determine a backend's _availability_, you will need to cross-check relevant properties of the upstream against the handler configuration you are utilizing. For example, if you've enabled [passive health checks](/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/) for your proxies, then you need to also take into consideration the `fails` and `num_requests` values to determine if an upstream is considered available: check that the `fails` amount is less than your configured maximum amount of failures for your proxy (i.e. [`max_fails`](/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/max_fails/)), and that `num_requests` is less than or equal to your configured amount of maximum requests per upstream (i.e. [`unhealthy_request_count`](/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/unhealthy_request_count/) for the whole proxy, or [`max_requests`](/docs/json/apps/http/servers/routes/handle/reverse_proxy/upstreams/max_requests/) for individual upstreams).
|
||||
If your goal is to determine a backend's availability, you will need to cross-check relevant properties of the upstream against the handler configuration you are utilizing. For example, if you've enabled [passive health checks](/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/) for your proxies, then you need to also take into consideration the `fails` and `num_requests` values to determine if an upstream is considered available: check that the `fails` amount is less than your configured maximum amount of failures for your proxy (i.e. [`max_fails`](/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/max_fails/)), and that `num_requests` is less than or equal to your configured amount of maximum requests per upstream (i.e. [`unhealthy_request_count`](/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/unhealthy_request_count/) for the whole proxy, or [`max_requests`](/docs/json/apps/http/servers/routes/handle/reverse_proxy/upstreams/max_requests/) for individual upstreams).
|
||||
|
|
|
@ -18,16 +18,23 @@ Caddy consists of a command, core library, and modules.
|
|||
|
||||
The **command** provides the [command line interface](/docs/command-line) you are hopefully familiar with. It's how you launch the process from your operating system. The amount of code and logic here is fairly minimal, and has only what is needed to bootstrap the core in the user's desired way. We intentionally avoid using flags and environment variables for configuration except as they pertain to bootstrapping config.
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
Modules can add subcommands to the command line interface! For instance, that's where the <a href="/docs/command-line#caddy-file-server">caddy file-server</a> command comes from. These added commands may have any flags or use any environment variables they want, even though the core Caddy commands minimize their use.
|
||||
|
||||
Modules can add subcommands to the command line interface! For instance, that's where the [`caddy file-server`](/docs/command-line#caddy-file-server) command comes from. These added commands may have any flags or use any environment variables they want, even though the core Caddy commands minimize their use.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
The **[core library](https://pkg.go.dev/github.com/caddyserver/caddy/v2?tab=doc)**, or "core" of Caddy, primarily manages configuration. It can [`Run()`](https://pkg.go.dev/github.com/caddyserver/caddy/v2?tab=doc#Run) a new configuration or [`Stop()`](https://pkg.go.dev/github.com/caddyserver/caddy/v2?tab=doc#Stop) a running config. It also provides various utilities, types, and values for modules to use.
|
||||
|
||||
**Modules** do everything else. Many modules come built into Caddy, which are called the _standard modules_. These are determined to be the most useful to the most users.
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
Sometimes the terms <i>module</i>, <i>plugin</i>, and <i>extension</i> get used interchangably, and usually that's OK. Technically, all modules are plugins, but not all plugins are modules. Modules are specifically a kind of plugin that extends Caddy's <a href="/docs/json/">config structure</a>.
|
||||
|
||||
Sometimes the terms *module*, *plugin*, and *extension* get used interchangably, and usually that's OK. Technically, all modules are plugins, but not all plugins are modules. Modules are specifically a kind of plugin that extends Caddy's [config structure](/docs/json/).
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
|
@ -64,7 +71,9 @@ When an app module is started, it initiates the app's module lifecycle.
|
|||
|
||||
|
||||
<aside class="tip">
|
||||
If you are a programmer who is building Caddy modules, you can find analogous information in our <a href="/docs/extending-caddy">Extending Caddy</a> guide, but with more focus on code.
|
||||
|
||||
If you are a programmer who is building Caddy modules, you can find analogous information in our [Extending Caddy](/docs/extending-caddy) guide, but with more focus on code.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
|
@ -116,8 +125,11 @@ When it is time for a config to be stopped, all modules get unloaded. If a modul
|
|||
|
||||
A module -- or any Caddy plugin -- gets "plugged in" to Caddy by adding an `import` for the module's package. By importing the package, [the module registers itself](https://pkg.go.dev/github.com/caddyserver/caddy/v2?tab=doc#RegisterModule) with the Caddy core, so when the Caddy process starts, it knows each module by name. It can even associate between module values and names, and vice-versa.
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
Plugins can be added without modifying the Caddy code base at all. There are instructions <a href="https://github.com/caddyserver/caddy/#with-version-information-andor-plugins">in the readme</a> for doing this!
|
||||
|
||||
Plugins can be added without modifying the Caddy code base at all. There are instructions [in the readme](https://github.com/caddyserver/caddy/#with-version-information-andor-plugins) for doing this!
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@ title: "Automatic HTTPS"
|
|||
|
||||
Automatic HTTPS provisions TLS certificates for all your sites and keeps them renewed. It also redirects HTTP to HTTPS for you! Caddy uses safe and modern defaults -- no downtime, extra configuration, or separate tooling is required.
|
||||
|
||||
<aside class="tip">Caddy innovated automatic HTTPS technology; we've been doing this since the first day it was feasible in 2015. Caddy's HTTPS automation logic is the most mature and robust in the world.</aside>
|
||||
<aside class="tip">
|
||||
Caddy innovated automatic HTTPS technology; we've been doing this since the first day it was feasible in 2015. Caddy's HTTPS automation logic is the most mature and robust in the world.
|
||||
</aside>
|
||||
|
||||
Here's a 28-second video showing how it works:
|
||||
|
||||
|
@ -40,19 +42,24 @@ Here's a 28-second video showing how it works:
|
|||
- Caddy serves public DNS names over HTTPS using certificates from a public ACME CA such as [Let's Encrypt](https://letsencrypt.org) or [ZeroSSL](https://zerossl.com).
|
||||
- Examples: `example.com`, `sub.example.com`, `*.example.com`
|
||||
|
||||
Caddy keeps all managed certificates renewed and redirects HTTP (default port 80) to HTTPS (default port 443) automatically.
|
||||
Caddy keeps all managed certificates renewed and redirects HTTP (default port `80`) to HTTPS (default port `443`) automatically.
|
||||
|
||||
**For local HTTPS:**
|
||||
|
||||
- Caddy may prompt for a password to install its unique root certificate into your trust store. This happens only once per root; and you can remove it at any time.
|
||||
- Any client accessing the site without trusting Caddy's root will show security errors.
|
||||
- Any client accessing the site without trusting Caddy's root CA certificate will show security errors.
|
||||
|
||||
**For public domain names:**
|
||||
|
||||
<aside class="tip">These are common requirements for any basic production website, not just Caddy. The main difference is to set your DNS records properly <b>before</b> running Caddy so it can provision certificates.</aside>
|
||||
<aside class="tip">
|
||||
|
||||
These are common requirements for any basic production website, not just Caddy. The main difference is to set your DNS records properly **before** running Caddy so it can provision certificates.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
- If your domain's A/AAAA records point to your server,
|
||||
- ports 80 and 443 are open externally,
|
||||
- ports `80` and `443` are open externally,
|
||||
- Caddy can bind to those ports (_or_ those ports are forwarded to Caddy),
|
||||
- your [data directory](/docs/conventions#data-directory) is writeable and persistent,
|
||||
- and your domain name appears somewhere relevant in the config,
|
||||
|
@ -68,16 +75,17 @@ Because HTTPS utilizes a shared, public infrastructure, you as the server admin
|
|||
Caddy implicitly activates automatic HTTPS when it knows a domain name (i.e. hostname) or IP address it is serving. There are various ways to tell Caddy your domain/IP, depending on how you run or configure Caddy:
|
||||
|
||||
- A [site address](/docs/caddyfile/concepts#addresses) in the [Caddyfile](/docs/caddyfile)
|
||||
- A [host matcher](/docs/json/apps/http/servers/routes/match/host/) in a [route](/docs/modules/http#servers/routes)
|
||||
- A [host matcher](/docs/json/apps/http/servers/routes/match/host/) in a [JSON route](/docs/modules/http#servers/routes)
|
||||
- Command line flags like [--domain](/docs/command-line#caddy-file-server) or [--from](/docs/command-line#caddy-reverse-proxy)
|
||||
- The [automate](/docs/json/apps/tls/certificates/automate/) certificate loader
|
||||
|
||||
Any of the following will prevent automatic HTTPS from being activated, either in whole or in part:
|
||||
|
||||
- [Explicitly disabling it](/docs/json/apps/http/servers/automatic_https/)
|
||||
- Explicitly disabling it [via JSON](/docs/json/apps/http/servers/automatic_https/) or [via Caddyfile](/docs/caddyfile/options#auto-https)
|
||||
- Not providing any hostnames or IP addresses in the config
|
||||
- Listening exclusively on the HTTP port
|
||||
- Manually loading certificates (unless [this config property](/docs/json/apps/http/servers/automatic_https/ignore_loaded_certificates/) is true)
|
||||
- Prefixing the [site address](/docs/caddyfile/concepts#addresses) with `http://` in the Caddyfile
|
||||
- Manually loading certificates (unless [`ignore_loaded_certificates`](/docs/json/apps/http/servers/automatic_https/ignore_loaded_certificates/) is set)
|
||||
|
||||
**Special cases:**
|
||||
|
||||
|
@ -89,8 +97,8 @@ Any of the following will prevent automatic HTTPS from being activated, either i
|
|||
When automatic HTTPS is activated, the following occurs:
|
||||
|
||||
- Certificates are obtained and renewed for [all domain names](#hostname-requirements)
|
||||
- The default port (if any) is changed to the [HTTPS port](/docs/modules/http#https_port) 443
|
||||
- HTTP is redirected to HTTPS (this uses [HTTP port](/docs/modules/http#http_port) 80)
|
||||
- The default port (if any) is changed to the [HTTPS port](/docs/modules/http#https_port) `443`
|
||||
- HTTP is redirected to HTTPS (this uses [HTTP port](/docs/modules/http#http_port) `80`)
|
||||
|
||||
Automatic HTTPS never overrides explicit configuration.
|
||||
|
||||
|
@ -126,9 +134,11 @@ The root's private key is uniquely generated using a cryptographically-secure ps
|
|||
|
||||
Although Caddy can be configured to sign with the root directly (to support non-compliant clients), this is disabled by default, and the root key is only used to sign intermediates.
|
||||
|
||||
The first time a root key is used, Caddy will try to install it into the system's local trust store(s). If it does not have permission to do so, it will prompt for a password. This behavior can be disabled in the configuration if it is not desired.
|
||||
The first time a root key is used, Caddy will try to install it into the system's local trust store(s). If it does not have permission to do so, it will prompt for a password. This behavior can be disabled in the configuration if it is not desired. If this fails due to being run as an unprivileged user, you may run [`caddy trust`](/docs/command-line#caddy-trust) to retry installation as a privileged user.
|
||||
|
||||
<aside class="tip">It is safe to trust Caddy's root certificate on your own machine as long as your computer is not compromised and your unique root key is not leaked.</aside>
|
||||
<aside class="tip">
|
||||
It is safe to trust Caddy's root certificate on your own machine as long as your computer is not compromised and your unique root key is not leaked.
|
||||
</aside>
|
||||
|
||||
After Caddy's root CA is installed, you will see it in your local trust store as "Caddy Local Authority" (unless you've configured a different name). You can uninstall it any time if you wish (the [`caddy untrust`](/docs/command-line#caddy-untrust) command makes this easy).
|
||||
|
||||
|
@ -161,29 +171,29 @@ The first two challenge types are enabled by default. If multiple challenges are
|
|||
|
||||
### HTTP challenge
|
||||
|
||||
The HTTP challenge performs an authoritative DNS lookup for the candidate hostname's A/AAAA record, then requests a temporary cryptographic resource over port 80 using HTTP. If the CA sees the expected resource, a certificate is issued.
|
||||
The HTTP challenge performs an authoritative DNS lookup for the candidate hostname's A/AAAA record, then requests a temporary cryptographic resource over port `80` using HTTP. If the CA sees the expected resource, a certificate is issued.
|
||||
|
||||
This challenge requires port 80 to be externally accessible. If Caddy cannot listen on port 80, packets from port 80 must be forwarded to Caddy's [HTTP port](/docs/json/apps/http/http_port/).
|
||||
This challenge requires port `80` to be externally accessible. If Caddy cannot listen on port 80, packets from port `80` must be forwarded to Caddy's [HTTP port](/docs/json/apps/http/http_port/).
|
||||
|
||||
This challenge is enabled by default and does not require explicit configuration.
|
||||
|
||||
|
||||
### TLS-ALPN challenge
|
||||
|
||||
The TLS-ALPN challenge performs an authoritative DNS lookup for the candidate hostname's A/AAAA record, then requests a temporary cryptographic resource over port 443 using a TLS handshake containing special ServerName and ALPN values. If the CA sees the expected resource, a certificate is issued.
|
||||
The TLS-ALPN challenge performs an authoritative DNS lookup for the candidate hostname's A/AAAA record, then requests a temporary cryptographic resource over port `443` using a TLS handshake containing special ServerName and ALPN values. If the CA sees the expected resource, a certificate is issued.
|
||||
|
||||
This challenge requires port 443 to be externally accessible. If Caddy cannot listen on port 443, packets from port 443 must be forwarded to Caddy's [HTTPS port](/docs/json/apps/http/https_port/).
|
||||
This challenge requires port `443` to be externally accessible. If Caddy cannot listen on port 443, packets from port `443` must be forwarded to Caddy's [HTTPS port](/docs/json/apps/http/https_port/).
|
||||
|
||||
This challenge is enabled by default and does not require explicit configuration.
|
||||
|
||||
|
||||
### DNS challenge
|
||||
|
||||
The DNS challenge performs an authoritative DNS lookup for the candidate hostname's TXT records, and looks for a special TXT record with a certain value. If the CA sees the expected value, a certificate is issued.
|
||||
The DNS challenge performs an authoritative DNS lookup for the candidate hostname's `TXT` records, and looks for a special `TXT` record with a certain value. If the CA sees the expected value, a certificate is issued.
|
||||
|
||||
This challenge does not require any open ports, and the server requesting a certificate does not need to be externally accessible. However, the DNS challenge requires configuration. Caddy needs to know the credentials to access your domain's DNS provider so it can set (and clear) the special TXT records. If the DNS challenge is enabled, other challenges are disabled by default.
|
||||
This challenge does not require any open ports, and the server requesting a certificate does not need to be externally accessible. However, the DNS challenge requires configuration. Caddy needs to know the credentials to access your domain's DNS provider so it can set (and clear) the special `TXT` records. If the DNS challenge is enabled, other challenges are disabled by default.
|
||||
|
||||
Since ACME CAs follow DNS standards when looking up TXT records for challenge verification, you can use CNAME records to delegate answering the challenge to other DNS zones. This can be used to delegate the `_acme-challenge` subdomain to another zone. This is particularly useful if your DNS provider doesn't provide an API, or isn't supported by one of the DNS plugins for Caddy.
|
||||
Since ACME CAs follow DNS standards when looking up `TXT` records for challenge verification, you can use CNAME records to delegate answering the challenge to other DNS zones. This can be used to delegate the `_acme-challenge` subdomain to another zone. This is particularly useful if your DNS provider doesn't provide an API, or isn't supported by one of the DNS plugins for Caddy.
|
||||
|
||||
DNS provider support is a community effort. [Learn how to enable the DNS challenge for your provider at our wiki.](https://caddy.community/t/how-to-use-dns-provider-modules-in-caddy-2/8148)
|
||||
|
||||
|
|
|
@ -19,10 +19,14 @@ Build:
|
|||
<pre><code class="cmd"><span class="bash">cd caddy/cmd/caddy/</span>
|
||||
<span class="bash">go build</span></code></pre>
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
Due to <a href="https://github.com/golang/go/issues/29228">a bug in Go</a>, these basic steps do not embed version information. If you want the version (<code>caddy version</code>), you need to compile Caddy as a dependency rather than as the main module. Instructions for this are in Caddy's <a href="https://github.com/caddyserver/caddy/blob/master/cmd/caddy/main.go">main.go</a> file. Or, you can use <a href="#xcaddy"><code>xcaddy</code></a> which automates this.
|
||||
|
||||
Due to [a bug in Go](https://github.com/golang/go/issues/29228), these basic steps do not embed version information. If you want the version (`caddy version`), you need to compile Caddy as a dependency rather than as the main module. Instructions for this are in Caddy's [main.go](https://github.com/caddyserver/caddy/blob/master/cmd/caddy/main.go) file. Or, you can use [`xcaddy`](#xcaddy) which automates this.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
## xcaddy
|
||||
|
||||
The [`xcaddy` command](https://github.com/caddyserver/xcaddy) is the easiest way to build Caddy with version information and/or plugins.
|
||||
|
|
|
@ -32,9 +32,12 @@ localhost
|
|||
```
|
||||
|
||||
<aside class="tip">
|
||||
If the HTTP and HTTPS ports (80 and 443, respectively) are privileged ports on your OS, you will either need to run with elevated privileges or use a higher port. To use a higher port, just change the address to something like <code>localhost:2015</code> and change the HTTP port using the <a href="/docs/caddyfile/options">http_port</a> Caddyfile option.
|
||||
|
||||
If the HTTP and HTTPS ports (80 and 443, respectively) are privileged ports on your OS, you will either need to run with elevated privileges or use a higher port. To use a higher port, just change the address to something like `localhost:2015` and change the HTTP port using the [http_port](/docs/caddyfile/options) Caddyfile option.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
Then hit enter and type what you want it to do. For this tutorial, make your Caddyfile look like this:
|
||||
|
||||
```caddy
|
||||
|
@ -48,18 +51,28 @@ Save that and run Caddy (since this is a training tutorial, we'll use the `--wat
|
|||
<pre><code class="cmd bash">caddy run --watch</code></pre>
|
||||
|
||||
<aside class="tip">
|
||||
If you get permissions errors, try using a higher port in your address (like <code>localhost:2015</code>) and <a href="/docs/caddyfile/options">change the HTTP port</a>, or run with elevated privileges.
|
||||
|
||||
If you get permissions errors, try using a higher port in your address (like `localhost:2015`) and [change the HTTP port](/docs/caddyfile/options), or run with elevated privileges.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
The first time, you'll be asked for your password. This is so Caddy can serve your site over HTTPS.
|
||||
|
||||
<aside class="tip">Caddy serves all sites over HTTPS by default as long as a host or IP is part of the site's address. <a href="/docs/automatic-https">Automatic HTTPS</a> can be disabled by prefixing the address with <code>http://</code> explicitly.</aside>
|
||||
<aside class="tip">
|
||||
|
||||
Caddy serves all sites over HTTPS by default as long as a host or IP is part of the site's address. [Automatic HTTPS](/docs/automatic-https) can be disabled by prefixing the address with `http://` explicitly.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<aside class="complete">First site</aside>
|
||||
|
||||
Open [localhost](https://localhost) in your browser and see your web server working, complete with HTTPS!
|
||||
|
||||
<aside class="tip">You might need to restart your browser if you get a certificate error the first time.</aside>
|
||||
<aside class="tip">
|
||||
You might need to restart your browser if you get a certificate error the first time.
|
||||
</aside>
|
||||
|
||||
That's not particularly exciting, so let's change our static response to a [file server](/docs/caddyfile/directives/file_server) with directory listings enabled:
|
||||
|
||||
|
@ -126,7 +139,9 @@ templates
|
|||
file_server browse
|
||||
```
|
||||
|
||||
<aside class="tip">Browsers don't support Zstandard encodings yet. Hopefully soon!</aside>
|
||||
<aside class="tip">
|
||||
Browsers don't support Zstandard encodings yet. Hopefully soon!
|
||||
</aside>
|
||||
|
||||
|
||||
<aside class="complete">Compression</aside>
|
||||
|
|
|
@ -172,17 +172,21 @@ These are examples of valid addresses:
|
|||
- `*.example.com`
|
||||
- `http://`
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
<a href="/docs/automatic-https">Automatic HTTPS</a> is enabled if your site's address contains a hostname or IP address. 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 explicitly <code>http://</code>.
|
||||
|
||||
[Automatic HTTPS](/docs/automatic-https) is enabled if your site's address contains a hostname or IP address. This behavior is purely implicit, however, so it never overrides any explicit configuration. For example, if the site's address is `http://example.com`, auto-HTTPS will not activate because the scheme is explicitly `http://`.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
From the address, Caddy can potentially infer the scheme, host and port of your site. If the address is without a port, the Caddyfile will choose the port matching the scheme if specified, or the default port of 443 will be assumed.
|
||||
|
||||
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 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`.
|
||||
|
||||
Wildcards (`*`) may be used, but only to represent precisely one label of the hostname. For example, `*.example.com` matches `foo.example.com` but not `foo.bar.example.com`, and `*` matches `localhost` but not `example.com`. To catch all hosts, omit the host portion of the address.
|
||||
|
||||
If multiple sites share the same definition, you can list all of them together:
|
||||
If multiple sites share the same definition, you can list all of them together; notice how the commas indicate the continuation of addresses:
|
||||
|
||||
```caddy
|
||||
localhost:8080, example.com, www.example.com
|
||||
|
@ -196,10 +200,10 @@ example.com,
|
|||
www.example.com
|
||||
```
|
||||
|
||||
Notice how the commas indicate the continuation of addresses.
|
||||
|
||||
An address must be unique; you cannot specify the same address more than once.
|
||||
|
||||
By default, sites bind on all network interfaces. If you wish to override this, use the [`bind` directive](/docs/caddyfile/directives/bind) or the [`default_bind` global option](/docs/caddyfile/options#default-bind) to do so.
|
||||
|
||||
|
||||
|
||||
## Matchers
|
||||
|
@ -258,6 +262,7 @@ You can use any [Caddy placeholders](/docs/conventions#placeholders) in the Cadd
|
|||
| `{upstream_hostport}` | `{http.reverse_proxy.upstream.hostport}` |
|
||||
| `{rp.*}` | `{http.reverse_proxy.*}` |
|
||||
| `{vars.*}` | `{http.vars.*}` |
|
||||
| `{err.*}` | `{http.error.*}` |
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ 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.)
|
||||
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.)
|
||||
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.)
|
||||
|
||||
bind also accepts an optional network name: `<network>/<host>`.
|
||||
`bind` accepts [network addresses](/docs/conventions#network-addresses), but may not include a port.
|
||||
|
||||
|
||||
## Syntax
|
||||
|
|
|
@ -37,7 +37,7 @@ example.com {
|
|||
|
||||
# Handle the error by serving an HTML page
|
||||
handle_errors {
|
||||
rewrite * /{http.error.status_code}.html
|
||||
rewrite * /{err.status_code}.html
|
||||
file_server
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ An opinionated directive which proxies a clone of the request to an authenticati
|
|||
- [Syntax](#syntax)
|
||||
- [Expanded Form](#expanded-form)
|
||||
- [Examples](#examples)
|
||||
- [Authelia](#authelia)
|
||||
- [Tailscale](#tailscale)
|
||||
|
||||
Caddy's [`reverse_proxy`](/docs/caddyfile/directives/reverse_proxy) is capable of performing "pre-check requests" to an external service, but this directive is tailored specifically for the authentication usecase. This directive is actually just a convenient way to use a longer, more common configuration (below).
|
||||
|
||||
|
@ -26,14 +28,22 @@ All the subdirectives of [`reverse_proxy`](/docs/caddyfile/directives/reverse_pr
|
|||
```caddy-d
|
||||
forward_auth [<matcher>] [<upstreams...>] {
|
||||
uri <to>
|
||||
copy_headers <fields...>
|
||||
copy_headers <fields...> {
|
||||
<fields...>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **<upstreams...>** is a list of upstreams (backends) to which to send auth requests.
|
||||
|
||||
- **uri** is the URI (path and query) to set on the request sent to the upstream. This will usually be the verification endpoint of the authentication gateway.
|
||||
|
||||
- **copy_headers** is a list of HTTP header fields to copy from the response to the original request, when the request has a success status code.
|
||||
|
||||
The field can be renamed by using `>` followed by the new name, for example `Before>After`.
|
||||
|
||||
A block may be used to list all the fields, one per line, if you prefer for readability.
|
||||
|
||||
Since this directive is an opinionated wrapper over a reverse proxy, you can use any of [`reverse_proxy`](/docs/caddyfile/directives/reverse_proxy#syntax)'s subdirectives to customize it.
|
||||
|
||||
|
||||
|
@ -67,20 +77,15 @@ reverse_proxy <upstreams...> {
|
|||
Remote-Email {rp.header.Remote-Email}
|
||||
}
|
||||
}
|
||||
|
||||
# On a failed response, copy the response back to
|
||||
# the client, with some hop-by-hop headers removed
|
||||
handle_response {
|
||||
copy_response_headers {
|
||||
exclude Connection Keep-Alive Te Trailers Transfer-Encoding Upgrade
|
||||
}
|
||||
copy_response
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
### Authelia
|
||||
|
||||
Delegating authentication to [Authelia](https://www.authelia.com/), before serving your app via a reverse proxy:
|
||||
|
||||
```caddy
|
||||
|
@ -99,3 +104,26 @@ app1.example.com {
|
|||
reverse_proxy app1:8080
|
||||
}
|
||||
```
|
||||
|
||||
For more information, see [Authelia's documentation](https://www.authelia.com/integration/proxies/caddy/) for integrating with Caddy.
|
||||
|
||||
|
||||
### Tailscale
|
||||
|
||||
Delegation authentication to [Tailscale](https://tailscale.com/) (currently named [`nginx-auth`](https://tailscale.com/blog/tailscale-auth-nginx/), but it still works with Caddy), and using the alternative syntax for `copy_headers` to rename the copied headers:
|
||||
|
||||
```caddy-d
|
||||
forward_auth unix//run/tailscale.nginx-auth.sock {
|
||||
uri /auth
|
||||
header_up Remote-Addr {remote_host}
|
||||
header_up Remote-Port {remote_port}
|
||||
header_up Original-URI {uri}
|
||||
copy_headers {
|
||||
Tailscale-User>X-Webauth-User
|
||||
Tailscale-Name>X-Webauth-Name
|
||||
Tailscale-Login>X-Webauth-Login
|
||||
Tailscale-Tailnet>X-Webauth-Tailnet
|
||||
Tailscale-Profile-Picture>X-Webauth-Profile-Picture
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -8,7 +8,7 @@ Sets up error handlers.
|
|||
|
||||
When the normal HTTP request handlers return an error, normal processing stops and the error handlers are invoked. Error handlers form a route which is just like normal routes, and they can do anything that normal routes can do. This enables great control and flexibility when handling errors during HTTP requests. For example, you can serve static error pages, templated error pages, or reverse proxy to another backend to handle errors.
|
||||
|
||||
A request's context is carried into error routes, so any values set on the request context such as [site root](root) will be preserved in error handlers, too. Additionally, new placeholders are available when handling errors. [The JSON docs for an HTTP server's error routes](/docs/json/apps/http/servers/errors/#routes) describe these placeholders. The `handle_errors` directive simply adds error routes, so you can use those placeholders within a `handle_errors` block.
|
||||
A request's context is carried into error routes, so any values set on the request context such as [site root](root) or [vars](vars) will be preserved in error handlers, too. Additionally, [new placeholders](#placeholders) are available when handling errors.
|
||||
|
||||
Note that certain directives, for example [`reverse_proxy`](reverse_proxy) which may write a response with an HTTP status which is classified as an error, will _not_ trigger the error routes.
|
||||
|
||||
|
@ -23,17 +23,29 @@ handle_errors {
|
|||
}
|
||||
```
|
||||
|
||||
- **<directives...>** is a list of HTTP handler directives, directive blocks, or matchers; one per line.
|
||||
- **<directives...>** is a list of HTTP handler [directives](/docs/caddyfile/directives) and [matchers](/docs/caddyfile/matchers), one per line.
|
||||
|
||||
|
||||
## Placeholders
|
||||
|
||||
The following placeholders are available while handling errors. They are [Caddyfile shorthands](/docs/caddyfile/concepts#placeholders) for the full placeholders which can be found in [the JSON docs for an HTTP server's error routes](/docs/json/apps/http/servers/errors/#routes).
|
||||
|
||||
| Placeholder | Description |
|
||||
|---|---|
|
||||
| `{err.status_code}` | The recommended HTTP status code |
|
||||
| `{err.status_text}` | The status text associated with the recommended status code |
|
||||
| `{err.message}` | The error message |
|
||||
| `{err.trace}` | The origin of the error |
|
||||
| `{err.id}` | An identifier for this occurrence of the error |
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Custom error pages based on the status code (i.e. a page called `404.html` for 404 errors). Note that [`file_server`](file_server) preserves the error's HTTP status code when run in `handle_errors`:
|
||||
Custom error pages based on the status code (i.e. a page called `404.html` for 404 errors). Note that [`file_server`](file_server) preserves the error's HTTP status code when run in `handle_errors` (assumes you set a [site root](/docs/caddyfile/directives/root) in your site beforehand):
|
||||
|
||||
```caddy-d
|
||||
handle_errors {
|
||||
rewrite * /{http.error.status_code}.html
|
||||
rewrite * /{err.status_code}.html
|
||||
file_server
|
||||
}
|
||||
```
|
||||
|
@ -52,9 +64,9 @@ Reverse proxy to a professional server that is highly qualified for handling HTT
|
|||
|
||||
```caddy-d
|
||||
handle_errors {
|
||||
rewrite * /{http.error.status_code}
|
||||
rewrite * /{err.status_code}
|
||||
reverse_proxy https://http.cat {
|
||||
header_up Host http.cat
|
||||
header_up Host {upstream_hostport}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -63,17 +75,26 @@ Simply use [`respond`](/docs/caddyfile/directives/respond) to return the error c
|
|||
|
||||
```caddy-d
|
||||
handle_errors {
|
||||
respond "{http.error.status_code} {http.error.status_text}"
|
||||
respond "{err.status_code} {err.status_text}"
|
||||
}
|
||||
```
|
||||
|
||||
To handle specific error codes differently, use an [`expression`](/docs/caddyfile/matchers#expression) matcher:
|
||||
To handle specific error codes differently, use an [`expression`](/docs/caddyfile/matchers#expression) matcher, using [`handle`](/docs/caddyfile/directives/handle) for mutual exclusivity:
|
||||
|
||||
```caddy-d
|
||||
handle_errors {
|
||||
@4xx expression `{http.error.status_code} >= 400 && {http.error.status_code} < 500`
|
||||
respond @4xx "It's a 4xx error!"
|
||||
@404-410 expression `{err.status_code} in [404, 410]`
|
||||
handle @404-410 {
|
||||
respond "It's a 404 or 410 error!"
|
||||
}
|
||||
|
||||
respond "It's not a 4xx error."
|
||||
@5xx expression `{err.status_code} >= 500 && {err.status_code} < 600`
|
||||
handle @5xx {
|
||||
respond "It's a 5xx error."
|
||||
}
|
||||
|
||||
handle {
|
||||
respond "It's another error"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -12,20 +12,37 @@ By default, header operations are performed immediately unless any of the header
|
|||
## Syntax
|
||||
|
||||
```caddy-d
|
||||
header [<matcher>] [[+|-|?]<field> [<value>|<find>|<default_value>] [<replace>]] {
|
||||
header [<matcher>] [[+|-|?]<field> [<value>|<find>] [<replace>]] {
|
||||
# Replace
|
||||
<field> <find> <replace>
|
||||
|
||||
# Add or Set
|
||||
[+]<field> <value>
|
||||
|
||||
# Delete
|
||||
-<field>
|
||||
?<field> <default_value>
|
||||
|
||||
# Default
|
||||
?<field> <value>
|
||||
|
||||
[defer]
|
||||
}
|
||||
```
|
||||
|
||||
- **<field>** 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.
|
||||
- **<field>** 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 overwriting (setting) the field if it already exists; header fields can appear more than once in a request.
|
||||
|
||||
Prefix with `-` to delete the field. The field may use prefix or suffix `*` wildcards to delete all matching fields.
|
||||
|
||||
Prefix with `?` to set a default value for the field. The field is only written if it doesn't yet exist.
|
||||
|
||||
- **<value>** is the header field value, if adding or setting a field.
|
||||
- **<default_value>** is the header field value that will be set only if the header does not already exist.
|
||||
|
||||
- **<find>** is the substring or regular expression to search for.
|
||||
|
||||
- **<replace>** is the replacement value; required if performing a search-and-replace.
|
||||
|
||||
- **defer** will force the header operations to be deferred until the response is being written out to the client. This is automatically enabled if any of the header fields are being deleted with `-`, or when setting a default value with `?`.
|
||||
|
||||
For multiple header manipulations, you can open a block and specify one manipulation per line in the same way.
|
||||
|
|
|
@ -14,9 +14,12 @@ $(function() {
|
|||
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 <a href="/docs/caddyfile/options#log"><code>log</code> global option</a> instead.
|
||||
|
||||
If you're looking to configure Caddy's runtime logs, you're looking for 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).
|
||||
|
||||
- [Syntax](#syntax)
|
||||
|
@ -131,9 +134,12 @@ output net <address> {
|
|||
The **format** subdirective lets you customize how logs get encoded (formatted). It appears within a `log` block.
|
||||
|
||||
<aside class="tip">
|
||||
<b>A note about Common Log Format (CLF):</b> CLF clashes with modern structured logs. To transform your access logs into the deprecated Common Log Format, please use the <a href="https://github.com/caddyserver/transform-encoder"><code>transform-encoder</code> plugin</a>.
|
||||
|
||||
**A note about Common Log Format (CLF):** CLF clashes with modern structured logs. To transform your access logs into the deprecated Common Log Format, please use the [`transform-encoder` plugin](https://github.com/caddyserver/transform-encoder).
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
In addition to the syntax for each individual encoder, these common properties can be set on most encoders:
|
||||
|
||||
```caddy-d
|
||||
|
|
|
@ -13,9 +13,16 @@ Manipulates HTTP header fields on the request. It can set, add, and delete heade
|
|||
request_header [<matcher>] [[+|-]<field> [<value>|<find>] [<replace>]]
|
||||
```
|
||||
|
||||
- **<field>** 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.
|
||||
- **<field>** 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 overwriting (setting) the field if it already exists; header fields can appear more than once in a request.
|
||||
|
||||
Prefix with `-` to delete the field. The field may use prefix or suffix `*` wildcards to delete all matching fields.
|
||||
|
||||
- **<value>** is the header field value, if adding or setting a field.
|
||||
|
||||
- **<find>** is the substring or regular expression to search for.
|
||||
|
||||
- **<replace>** is the replacement value; required if performing a search-and-replace.
|
||||
|
||||
|
||||
|
@ -26,3 +33,9 @@ Remove the Referer header from the request:
|
|||
```caddy-d
|
||||
request_header -Referer
|
||||
```
|
||||
|
||||
Delete all headers containing an underscore from the request:
|
||||
|
||||
```caddy-d
|
||||
request_header -*_*
|
||||
```
|
||||
|
|
|
@ -145,7 +145,7 @@ Additionally, upstream addresses cannot contain paths or query strings, as that
|
|||
|
||||
If the address is not a URL (i.e. does not have a scheme), then placeholders can be used, but this makes the upstream _dynamically static_, meaning that potentially many different backends act as a single, static upstream in terms of health checks and load balancing.
|
||||
|
||||
When proxying over HTTPS, you may need to override the `Host` header such that it matches the TLS SNI value, which is used by servers for routing and certificate selection. See the [Headers](#headers) section below for more details.
|
||||
When proxying over HTTPS, you may need to override the `Host` header such that it matches the TLS SNI value, which is used by servers for routing and certificate selection. See the [HTTPS](#https) section below for more details.
|
||||
|
||||
|
||||
#### Dynamic upstreams
|
||||
|
@ -158,7 +158,7 @@ Caddy's reverse proxy comes standard with some dynamic upstream modules. Note th
|
|||
Retrieves upstreams from SRV DNS records.
|
||||
|
||||
```caddy-d
|
||||
dynamic srv [<name>] {
|
||||
dynamic srv [<full_name>] {
|
||||
service <service>
|
||||
proto <proto>
|
||||
name <name>
|
||||
|
@ -169,14 +169,14 @@ Retrieves upstreams from SRV DNS records.
|
|||
}
|
||||
```
|
||||
|
||||
- **<name>** - The full domain name of the record to look up (i.e. `_service._proto.name`).
|
||||
- **service** - The service component of the full name.
|
||||
- **proto** - The protocol component of the full name. Either `tcp` or `udp`.
|
||||
- **name** - The name component. Or, if `service` and `proto` are empty, the full domain name to query.
|
||||
- **refresh** - How often to refresh cached results. Default: `1m`
|
||||
- **resolvers** - List of DNS resolvers to override system resolvers.
|
||||
- **dial_timeout** - Timeout for dialing the query.
|
||||
- **dial_fallback_delay** - Timeout for falling back from IPv6 to IPv4 via RFC 6555. Default: `300ms`
|
||||
- **<full_name>** is the full domain name of the record to look up (i.e. `_service._proto.name`).
|
||||
- **service** is the service component of the full name.
|
||||
- **proto** is the protocol component of the full name. Either `tcp` or `udp`.
|
||||
- **name** is the name component. Or, if `service` and `proto` are empty, the full domain name to query.
|
||||
- **refresh** is how often to refresh cached results. Default: `1m`
|
||||
- **resolvers** is the list of DNS resolvers to override system resolvers.
|
||||
- **dial_timeout** is the timeout for dialing the query.
|
||||
- **dial_fallback_delay** is how long to wait before spawning an RFC 6555 Fast Fallback connection. Default: `300ms`
|
||||
|
||||
|
||||
|
||||
|
@ -195,12 +195,12 @@ Retrieves upstreams from A/AAAA DNS records.
|
|||
}
|
||||
```
|
||||
|
||||
- **<name>, name** - The domain name to query.
|
||||
- **<port>, port** - The port to use for the backend.
|
||||
- **refresh** - How often to refresh cached results. Default: `1m`
|
||||
- **resolvers** - List of DNS resolvers to override system resolvers.
|
||||
- **dial_timeout** - Timeout for dialing the query.
|
||||
- **dial_fallback_delay** - Timeout for falling back from IPv6 to IPv4 via RFC 6555. Default: `300ms`
|
||||
- **name** is the domain name to query.
|
||||
- **port** is the port to use for the backend.
|
||||
- **refresh** is how often to refresh cached results. Default: `1m`
|
||||
- **resolvers** is the list of DNS resolvers to override system resolvers.
|
||||
- **dial_timeout** is the timeout for dialing the query.
|
||||
- **dial_fallback_delay** is how long to wait before spawning an RFC 6555 Fast Fallback connection. Default: `300ms`
|
||||
|
||||
|
||||
|
||||
|
@ -208,18 +208,43 @@ Retrieves upstreams from A/AAAA DNS records.
|
|||
|
||||
Load balancing is used whenever more than one upstream is defined.
|
||||
|
||||
- **lb_policy** <span id="lb_policy"/> is the name of the load balancing policy, along with any options. Default: `random`. Can be:
|
||||
- `random` - randomly choose an upstream
|
||||
- `random_choose <n>` - selects two or more upstreams randomly, then chooses one with least load (`n` is usually 2)
|
||||
- `first` - choose first available upstream, from the order they are defined in the config
|
||||
- `round_robin` - iterate each upstream in turn
|
||||
- `least_conn` - choose upstream with fewest number of current requests; if more than one host has the least number of requests, then one of the hosts is chosen at random
|
||||
- `ip_hash` - map the client IP to sticky upstream
|
||||
- `uri_hash` - map the request URI (path and query) to sticky upstream
|
||||
- `header [field]` - map request header to sticky upstream; if the specified header is not present, a random upstream is selected
|
||||
- `cookie [<name> [<secret>]]` - based on the given cookie (default name is `lb` if not specified), the cookie value is hashed, optionally with a secret for HMAC-SHA256; on the first request from a client, a random upstream is selected
|
||||
- **lb_policy** <span id="lb_policy"/> is the name of the load balancing policy, along with any options. Default: `random`.
|
||||
|
||||
For policies that involve hashing, the [highest-random-weight (HRW)](https://en.wikipedia.org/wiki/Rendezvous_hashing) algorithm is used to ensure that a client or request with the same hash key is mapped to the same upstream, even if the list of upstreams change.
|
||||
|
||||
- `random` randomly chooses an upstream
|
||||
|
||||
- `random_choose <n>` selects two or more upstreams randomly, then chooses one with least load (`n` is usually 2)
|
||||
|
||||
- `first` chooses the first available upstream, from the order they are defined in the config
|
||||
|
||||
- `round_robin` iterates each upstream in turn
|
||||
|
||||
- `least_conn` choose upstream with fewest number of current requests; if more than one host has the least number of requests, then one of those hosts is chosen at random
|
||||
|
||||
- `ip_hash` maps the client IP to a sticky upstream
|
||||
|
||||
- `uri_hash` maps the request URI (path and query) to a sticky upstream
|
||||
|
||||
- `header [field]` maps a request header to a sticky upstream, by hashing the header value; if the specified header field is not present, a random upstream is selected
|
||||
|
||||
- `cookie [<name> [<secret>]]` on the first request from a client (when there's no cookie), a random upstream is selected, and a `Set-Cookie` header is added to the response (default cookie name is `lb` if not specified). The cookie value is the upstream dial address of the chosen upstream, hashed with HMAC-SHA256 (using `<secret>` as the shared secret, empty string if not specified).
|
||||
|
||||
On subsequent requests where the cookie is present, the cookie value will be mapped to the same upstream if it's available; if not available or not found, a new random upstream is selected and the cookie is added to the response.
|
||||
|
||||
If you wish to use a particular upstream for debugging purposes, you may hash the upstream address with the secret, and set the cookie in your HTTP client (browser or otherwise). For example, with PHP, you could run the following to compute the cookie value, where `10.1.0.10:8080` is the address of one of your upstreams, and `secret` is your configured secret.
|
||||
```php
|
||||
echo hash_hmac('sha256', '10.1.0.10:8080', 'secret');
|
||||
// cdd96966817dd14a99f47ee17451464f29998da170814a16b483e4c1ff4c48cf
|
||||
```
|
||||
|
||||
You can set the cookie in your browser via the Javascript console, for example to set the cookie named `lb`:
|
||||
```js
|
||||
document.cookie = "lb=cdd96966817dd14a99f47ee17451464f29998da170814a16b483e4c1ff4c48cf";
|
||||
```
|
||||
|
||||
- **lb_try_duration** <span id="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. A reasonable starting point might be `5s` since the HTTP transport's default dial timeout is `3s`, so that should allow for at least one retry if the first selected upstream cannot be reached; but feel free to experiment to find the right balance for your usecase.
|
||||
|
||||
- **lb_try_interval** <span id="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.
|
||||
|
||||
|
||||
|
@ -229,11 +254,17 @@ Load balancing is used whenever more than one upstream is defined.
|
|||
Active health checks perform health checking in the background on a timer:
|
||||
|
||||
- **health_uri** <span id="health_uri"/> is the URI path (and optional query) for active health checks.
|
||||
|
||||
- **health_port** <span id="health_port"/> is the port to use for active health checks, if different from the upstream's port.
|
||||
|
||||
- **health_interval** <span id="health_interval"/> is a [duration value](/docs/conventions#durations) that defines how often to perform active health checks.
|
||||
|
||||
- **health_timeout** <span id="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** <span id="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` (which is the default), or `2xx`.
|
||||
|
||||
- **health_body** <span id="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.
|
||||
|
||||
- **health_headers** <span id="health_headers"/> allows specifying headers to set on the active health check requests. This is useful if you need to change the `Host` header, or if you need to provide some authentication to your backend as part of your health checks.
|
||||
|
||||
|
||||
|
@ -243,10 +274,16 @@ Active health checks perform health checking in the background on a timer:
|
|||
Passive health checks happen inline with actual proxied requests:
|
||||
|
||||
- **fail_duration** <span id="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; the default is `0` (off). A reasonable starting point might be `30s` to balance error rates with responsiveness when bringing an unhealthy upstream back online; but feel free to experiment to find the right balance for your usecase.
|
||||
|
||||
- **max_fails** <span id="max_fails"/> is the maximum number of failed requests within `fail_duration` that are needed before considering a backend to be down; must be >= `1`; default is `1`.
|
||||
|
||||
- **unhealthy_status** <span id="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** <span id="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** <span id="unhealthy_request_count"/> is the permissible number of simultaneous requests to a backend before marking it as down.
|
||||
|
||||
- **unhealthy_request_count** <span id="unhealthy_request_count"/> is the permissible number of simultaneous requests to a backend before marking it as down. In other words, if a particular backend is currently handling this many requests, then it's considered "overloaded" and other backends will be preferred instead.
|
||||
|
||||
This should be a reasonably large number; configuring this means that the proxy will have a limit of `unhealthy_request_count × upstreams_count` total simultaneous requests, and any requests after that point will result in an error due to no upstreams being available.
|
||||
|
||||
|
||||
|
||||
|
@ -255,8 +292,11 @@ Passive health checks happen inline with actual proxied requests:
|
|||
The proxy **buffers responses** by default for wire efficiency:
|
||||
|
||||
- **flush_interval** <span id="flush_interval"/> is a [duration value](/docs/conventions#durations) that adjusts how often Caddy should flush the response buffer to the client. By default, no periodic flushing is done. A negative value disables response buffering, and flushes immediately after each write to the client. This option is ignored when the upstream's response is recognized as a streaming response, or if its content length is `-1`; for such responses, writes are flushed to the client immediately.
|
||||
|
||||
- **buffer_requests** <span id="buffer_requests"/> will cause the proxy to read the entire request body into a buffer before sending it upstream. This is very inefficient and should only be done if the upstream requires reading request bodies without delay (which is something the upstream application should fix).
|
||||
|
||||
- **buffer_responses** <span id="buffer_responses"/> will cause the entire response body to be read and buffered in memory before being proxied to the client. This should be avoided if at all possible for performance reasons, but could be useful if the backend has tighter memory constraints.
|
||||
|
||||
- **max_buffer_size** <span id="max_buffer_size"/> if body buffering is enabled, this sets the maximum size of the buffers used for the requests and responses. This accepts all size formats supported by [go-humanize](https://github.com/dustin/go-humanize/blob/master/bytes.go).
|
||||
|
||||
|
||||
|
@ -265,8 +305,9 @@ The proxy **buffers responses** by default for wire efficiency:
|
|||
|
||||
The proxy can **manipulate headers** between itself and the backend:
|
||||
|
||||
- **header_up** <span id="header_up"/> Sets, adds (with the `+` prefix), removes (with the `-` prefix), or performs a replacement (by using two arguments, a search and replacement) in a request header going upstream to the backend.
|
||||
- **header_down** <span id="header_down"/> Sets, adds (with the `+` prefix), removes (with the `-` prefix), or performs a replacement (by using two arguments, a search and replacement) in a response header coming downstream from the backend.
|
||||
- **header_up** <span id="header_up"/> sets, adds (with the `+` prefix), deletes (with the `-` prefix), or performs a replacement (by using two arguments, a search and replacement) in a request header going upstream to the backend.
|
||||
|
||||
- **header_down** <span id="header_down"/> sets, adds (with the `+` prefix), deletes (with the `-` prefix), or performs a replacement (by using two arguments, a search and replacement) in a response header coming downstream from the backend.
|
||||
|
||||
For example, to set a request header, overwriting any existing values:
|
||||
|
||||
|
@ -281,12 +322,18 @@ header_down +Some-Header "first value"
|
|||
header_down +Some-Header "second value"
|
||||
```
|
||||
|
||||
To remove a request header, preventing it from reaching the backend:
|
||||
To delete a request header, preventing it from reaching the backend:
|
||||
|
||||
```caddy-d
|
||||
header_up -Some-Header
|
||||
```
|
||||
|
||||
To delete all matching request, using a suffix match:
|
||||
|
||||
```caddy-d
|
||||
header_up -Some-*
|
||||
```
|
||||
|
||||
To perform a regular expression replacement on a request header:
|
||||
|
||||
```caddy-d
|
||||
|
@ -300,11 +347,21 @@ The regular expression language used is RE2, included in Go. See the [RE2 syntax
|
|||
|
||||
By default, Caddy passes thru incoming headers—including `Host`—to the backend without modifications, with three exceptions:
|
||||
|
||||
- It sets or augments the [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) header field.
|
||||
- It sets the [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) header field.
|
||||
- It sets the [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) header field.
|
||||
- It sets or augments the [`X-Forwarded-For`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) header field.
|
||||
- It sets the [`X-Forwarded-Proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) header field.
|
||||
- It sets the [`X-Forwarded-Host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) header field.
|
||||
|
||||
For these `X-Forwarded-*` headers, by default, Caddy will ignore their values from incoming requests, to prevent spoofing. If Caddy is not the first server being connected to by your clients (for example when a CDN is in front of Caddy), you may configure `trusted_proxies` <span id="trusted_proxies"/> with a list of IP ranges (CIDRs) from which incoming requests are trusted to have sent good values for these headers. As a shortcut, `trusted_proxies private_ranges` may be configured to trust all private IP ranges.
|
||||
<span id="trusted_proxies"/> For these `X-Forwarded-*` headers, by default, Caddy will ignore their values from incoming requests, to prevent spoofing. If Caddy is not the first server being connected to by your clients (for example when a CDN is in front of Caddy), you may configure `trusted_proxies` with a list of IP ranges (CIDRs) from which incoming requests are trusted to have sent good values for these headers. As a shortcut, `private_ranges` may be configured to trust all private IP ranges.
|
||||
|
||||
```caddy-d
|
||||
trusted_proxies private_ranges
|
||||
```
|
||||
|
||||
<aside class="tip">
|
||||
|
||||
If you're using Cloudflare in front of Caddy, be aware that you may be vulnerable to spoofing of the `X-Forwarded-For` header. Our friends at [Authelia](https://www.authelia.com) have documented a [workaround](https://www.authelia.com/integration/proxies/fowarded-headers/) to configure Cloudflare to ignore incoming values for this header.
|
||||
|
||||
</aside>
|
||||
|
||||
Additionally, when using the [`http` transport](#the-http-transport), the `Accept-Encoding: gzip` header will be set, if it is missing in the request from the client. This behavior can be disabled with [`compression off`](#compression) on the transport.
|
||||
|
||||
|
@ -363,6 +420,8 @@ transport http {
|
|||
tls_timeout <duration>
|
||||
tls_trusted_ca_certs <pem_files...>
|
||||
tls_server_name <server_name>
|
||||
tls_renegotiation <level>
|
||||
tls_except_ports <ports...>
|
||||
keepalive [off|<duration>]
|
||||
keepalive_interval <interval>
|
||||
keepalive_idle_conns <max_count>
|
||||
|
@ -374,25 +433,56 @@ transport http {
|
|||
```
|
||||
|
||||
- **read_buffer** <span id="read_buffer"/> is the size of the read buffer in bytes. It accepts all formats supported by [go-humanize](https://github.com/dustin/go-humanize/blob/master/bytes.go). Default: `4KiB`.
|
||||
|
||||
- **write_buffer** <span id="write_buffer"/> is the size of the write buffer in bytes. It accepts all formats supported by [go-humanize](https://github.com/dustin/go-humanize/blob/master/bytes.go). Default: `4KiB`.
|
||||
|
||||
- **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`.
|
||||
|
||||
- **dial_timeout** <span id="dial_timeout"/> is how long to wait when connecting to the upstream socket. Accepts [duration values](/docs/conventions#durations). Default: No timeout.
|
||||
|
||||
- **dial_fallback_delay** <span id="dial_fallback_delay"/> is how long to wait before spawning an RFC 6555 Fast Fallback connection. A negative value disables this. Accepts [duration values](/docs/conventions#durations). Default: `300ms`.
|
||||
|
||||
- **response_header_timeout** <span id="response_header_timeout"/> is how long to wait for reading response headers from the upstream. Accepts [duration values](/docs/conventions#durations). Default: No timeout.
|
||||
|
||||
- **expect_continue_timeout** <span id="expect_continue_timeout"/> is how long to wait for the upstreams's first response headers after fully writing the request headers if the request has the header `Expect: 100-continue`. Accepts [duration values](/docs/conventions#durations). Default: No timeout.
|
||||
|
||||
- **resolvers** <span id="resolvers"/> is a list of DNS resolvers to override system resolvers.
|
||||
|
||||
- **tls** <span id="tls"/> uses HTTPS with the backend. This will be enabled automatically if you specify backends using the `https://` scheme or port `:443`, or if any of the below `tls_*` options are configured.
|
||||
|
||||
- **tls_client_auth** <span id="tls_client_auth"/> enables TLS client authentication one of two ways: (1) by specifying a domain name for which Caddy should obtain a certificate and keep it renewed, or (2) by specifying a certificate and key file to present for TLS client authentication with the backend.
|
||||
|
||||
- **tls_insecure_skip_verify** <span id="tls_insecure_skip_verify"/> turns off TLS handshake verification, making the connection insecure and vulnerable to man-in-the-middle attacks. _Do not use in production._
|
||||
|
||||
- **tls_timeout** <span id="tls_timeout"/> is a [duration value](/docs/conventions#durations) that specifies how long to wait for the TLS handshake to complete. Default: No timeout.
|
||||
|
||||
- **tls_trusted_ca_certs** <span id="tls_trusted_ca_certs"/> is a list of PEM files that specify CA public keys to trust when connecting to the backend.
|
||||
- **tls_server_name** <span id="tls_server_name"/> sets the server name used when verifying the certificate received in the TLS handshake. By default, this will use the upstream address' host part. You only need to override this if your upstream address does not match the certificate the upstream is likely to use. For example if the upstream address is an IP address, then you would need to configure this to the hostname being served by the upstream server. Currently, this does not support placeholders, so a static value must be used.
|
||||
|
||||
- **tls_server_name** <span id="tls_server_name"/> sets the server name used when verifying the certificate received in the TLS handshake. By default, this will use the upstream address' host part.
|
||||
|
||||
You only need to override this if your upstream address does not match the certificate the upstream is likely to use. For example if the upstream address is an IP address, then you would need to configure this to the hostname being served by the upstream server.
|
||||
|
||||
A request placeholder may be used, in which case a clone of the HTTP transport config will be used on every request, which may incur a performance penalty.
|
||||
|
||||
- **tls_renegotiation** <span id="tls_renegotiation"/> sets the TLS renegotiation level. TLS renegotiation is the act of performing subsequent handshakes after the first. The level may be one of:
|
||||
- `never` (the default) disables renegotiation.
|
||||
- `once` allows a remote server to request renegotiation once per connection.
|
||||
- `freely` allows a remote server to repeatedly request renegotiation.
|
||||
|
||||
- **tls_except_ports** <span id="tls_except_ports"/> when TLS is enabled, if the upstream target uses one of the given ports, TLS will be disabled for those connections. This may be useful when configuring dynamic upstreams, where some upstreams expect HTTP and others expect HTTPS requests.
|
||||
|
||||
- **keepalive** <span id="keepalive"/> is either `off` or a [duration value](/docs/conventions#durations) that specifies how long to keep connections open (timeout). Default: `2m`.
|
||||
|
||||
- **keepalive_interval** <span id="keepalive"/> is a [duration value](/docs/conventions#durations) that specifies how often to probe for liveness. Default: `30s`.
|
||||
|
||||
- **keepalive_idle_conns** <span id="keepalive_idle_conns"/> defines the maximum number of connections to keep alive. Default: No limit.
|
||||
|
||||
- **keepalive_idle_conns_per_host** <span id="keepalive_idle_conns_per_host"/> if non-zero, controls the maximum idle (keep-alive) connections to keep per-host. Default: `32`.
|
||||
|
||||
- **versions** <span id="versions"/> allows customizing which versions of HTTP to support. As a special case, "h2c" is a valid value which will enable cleartext HTTP/2 connections to the upstream (however, this is a non-standard feature that does not use Go's default HTTP transport, so it is exclusive of other features; subject to change or removal). Default: `1.1 2`, or if scheme is `h2c://`, `h2c 2`
|
||||
|
||||
- **compression** <span id="compression"/> can be used to disable compression to the backend by setting it to `off`.
|
||||
|
||||
- **max_conns_per_host** <span id="max_conns_per_host"/> optionally limits the total number of connections per host, including connections in the dialing, active, and idle states. Default: No limit.
|
||||
|
||||
|
||||
|
@ -412,15 +502,23 @@ transport fastcgi {
|
|||
```
|
||||
|
||||
- **root** <span id="root"/> is the root of the site. Default: `{http.vars.root}` or current working directory.
|
||||
|
||||
- **split** <span id="split"/> is where to split the path to get PATH_INFO at the end of the URI.
|
||||
|
||||
- **env** <span id="env"/> sets an extra environment variable to the given value. Can be specified more than once for multiple environment variables.
|
||||
|
||||
- **resolve_root_symlink** <span id="resolve_root_symlink"/> enables resolving the `root` directory to its actual value by evaluating a symbolic link, if one exists.
|
||||
|
||||
- **dial_timeout** <span id="dial_timeout"/> is how long to wait when connecting to the upstream socket. Accepts [duration values](/docs/conventions#durations). Default: `3s`.
|
||||
|
||||
- **read_timeout** <span id="read_timeout"/> is how long to wait when reading from the FastCGI server. Accepts [duration values](/docs/conventions#durations). Default: no timeout.
|
||||
|
||||
- **write_timeout** <span id="write_timeout"/> is how long to wait when sending to the FastCGI server. Accepts [duration values](/docs/conventions#durations). Default: no timeout.
|
||||
|
||||
<aside class="tip">
|
||||
If you're trying to serve a modern PHP application, you may be looking for the <a href="/docs/caddyfile/directives/php_fastcgi"><code>php_fastcgi</code> directive</a>, which is a shortcut for a proxy using the `fastcgi` directive, with the necessary rewrites for using `index.php` as the routing entrypoint.
|
||||
|
||||
If you're trying to serve a modern PHP application, you may be looking for the [`php_fastcgi` directive](/docs/caddyfile/directives/php_fastcgi), which is a shortcut for a proxy using the `fastcgi` directive, with the necessary rewrites for using `index.php` as the routing entrypoint.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
|
|
|
@ -58,9 +58,12 @@ route {
|
|||
```
|
||||
|
||||
<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.
|
||||
|
||||
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
|
||||
|
|
|
@ -180,15 +180,15 @@ Full matcher documentation can be found [in each respective matcher module's doc
|
|||
|
||||
### expression
|
||||
|
||||
⚠️ _This module is still experimental and, as such, may experience breaking changes._
|
||||
|
||||
```caddy-d
|
||||
expression <cel...>
|
||||
```
|
||||
|
||||
By any [CEL (Common Expression Language)](https://github.com/google/cel-spec) expression that returns `true` or `false`.
|
||||
|
||||
As a special case, 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.
|
||||
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 other matcher for the supported syntax within CEL expressions.
|
||||
|
||||
#### Examples:
|
||||
|
||||
|
@ -201,9 +201,14 @@ 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 {http.error.status_code} == 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*)')
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
@ -211,11 +216,20 @@ expression {http.error.status_code} == 404
|
|||
|
||||
```caddy-d
|
||||
file {
|
||||
root <paths>
|
||||
root <path>
|
||||
try_files <files...>
|
||||
try_policy first_exist|smallest_size|largest_size|most_recent_modified
|
||||
split_path <delims...>
|
||||
}
|
||||
file <files...>
|
||||
|
||||
expression `file({
|
||||
'root': '<path>',
|
||||
'try_files': ['<files...>'],
|
||||
'try_policy': 'first_exist|smallest_size|largest_size|most_recent_modified',
|
||||
'split_path': ['<delims...>']
|
||||
})`
|
||||
expression file('<files...>')
|
||||
```
|
||||
|
||||
By files.
|
||||
|
@ -235,10 +249,16 @@ Because `try_files` with a policy of `first_exist` is so common, there is a one-
|
|||
file <files...>
|
||||
```
|
||||
|
||||
An empty `file` matcher (one with no files listed after it) will see if the requested file—verbatim from the URI, relative to the [site root](/docs/caddyfile/directives/root)—exists.
|
||||
An empty `file` matcher (one with no files listed after it) will see if the requested file—verbatim from the URI, relative to the [site root](/docs/caddyfile/directives/root)—exists. This is effectively the same as `file {path}`.
|
||||
|
||||
|
||||
<aside class="tip">
|
||||
|
||||
Since rewriting based on the existence of a file on disk is so common, there is also a [`try_files` directive](/docs/caddyfile/directives/try_files) which is a shortcut of the `file` matcher and a [`rewrite` handler](/docs/caddyfile/directives/rewrite).
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
Upon matching, two new placeholders will be made available:
|
||||
|
||||
- `{http.matchers.file.relative}` The root-relative path of the file. This is often useful when rewriting requests.
|
||||
|
@ -273,6 +293,8 @@ file {path}.html {path} =404
|
|||
|
||||
```caddy-d
|
||||
header <field> [<value>]
|
||||
|
||||
expression header({'<field>': '<value>'})
|
||||
```
|
||||
|
||||
By request header fields.
|
||||
|
@ -305,9 +327,7 @@ 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
|
||||
}
|
||||
@not_foo header !Foo
|
||||
```
|
||||
|
||||
|
||||
|
@ -317,6 +337,9 @@ Match requests that do not have the `Foo` header field at all:
|
|||
|
||||
```caddy-d
|
||||
header_regexp [<name>] <field> <regexp>
|
||||
|
||||
expression header_regexp('<name>', '<field>', '<regexp>')
|
||||
expression header_regexp('<field>', '<regexp>')
|
||||
```
|
||||
|
||||
Like [`header`](#header), but supports regular expressions. Capture groups can be accessed via [placeholder](/docs/caddyfile/concepts#placeholders) like `{re.name.capture_group}` where `name` is the name of the regular expression (optional, but recommended) and `capture_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.
|
||||
|
@ -340,6 +363,8 @@ header_regexp login Cookie login_([a-f0-9]+)
|
|||
|
||||
```caddy-d
|
||||
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.
|
||||
|
@ -359,6 +384,8 @@ host sub.example.com
|
|||
|
||||
```caddy-d
|
||||
method <verbs...>
|
||||
|
||||
expression method('<verbs...>')
|
||||
```
|
||||
|
||||
By the method (verb) of the HTTP request. Verbs should be uppercase, like `POST`. Can match one or many methods.
|
||||
|
@ -437,6 +464,8 @@ not {
|
|||
|
||||
```caddy-d
|
||||
path <paths...>
|
||||
|
||||
expression path('<paths...>')
|
||||
```
|
||||
|
||||
By request path, meaning the path component of the request's URI. Path matches are exact, but wildcards `*` may be used:
|
||||
|
@ -457,6 +486,9 @@ Multiple `path` matchers will be OR'ed together.
|
|||
|
||||
```caddy-d
|
||||
path_regexp [<name>] <regexp>
|
||||
|
||||
expression path_regexp('<name>', '<regexp>')
|
||||
expression path_regexp('<regexp>')
|
||||
```
|
||||
|
||||
Like [`path`](#path), but supports regular expressions. Capture groups can be accessed via [placeholder](/docs/caddyfile/concepts#placeholders) like `{re.name.capture_group}` where `name` is the name of the regular expression (optional, but recommended) and `capture_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.
|
||||
|
@ -482,6 +514,8 @@ path_regexp static \.([a-f0-9]{6})\.(css|js)$
|
|||
|
||||
```caddy-d
|
||||
protocol http|https|grpc
|
||||
|
||||
expression protocol('http|https|grpc')
|
||||
```
|
||||
|
||||
By request protocol.
|
||||
|
@ -495,6 +529,9 @@ There can only be one `protocol` matcher per named matcher.
|
|||
|
||||
```caddy-d
|
||||
query <key>=<val>...
|
||||
|
||||
expression query({'<key>': '<val>'})
|
||||
expression query({'<key>': ['<vals...>']})
|
||||
```
|
||||
|
||||
By query string parameters. Should be a sequence of `key=value` pairs. Keys are matched exactly, case-sensitively. Values can contain placeholders. Values are matched exactly, but also support `*` to match any value.
|
||||
|
@ -516,6 +553,9 @@ query sort=asc
|
|||
|
||||
```caddy-d
|
||||
remote_ip [forwarded] <ranges...>
|
||||
|
||||
expression remote_ip('<ranges...>')
|
||||
expression remote_ip('forwarded', '<ranges...>')
|
||||
```
|
||||
|
||||
By remote (client) IP address. Accepts exact IPs or CIDR ranges. If the first argument is `forwarded`, then the first IP in the `X-Forwarded-For` request header, if present, will be preferred as the reference IP, rather than the immediate peer's IP, which is the default. IPv6 zones are supported.
|
||||
|
|
|
@ -49,7 +49,7 @@ Possible options are:
|
|||
debug
|
||||
http_port <port>
|
||||
https_port <port>
|
||||
default_bind <host>
|
||||
default_bind <hosts...>
|
||||
order <dir1> first|last|[before|after <dir2>]
|
||||
storage <module_name> {
|
||||
<options...>
|
||||
|
@ -155,7 +155,7 @@ The port for the server to use for HTTPS. For internal use only; does not change
|
|||
|
||||
|
||||
##### `default_bind`
|
||||
The default bind address to be used for all sites, if the [`bind` directive](/docs/caddyfile/directives/bind) is not used in the site. Default: empty, which binds to all interfaces.
|
||||
The default bind address(es) to be used for all sites, if the [`bind` directive](/docs/caddyfile/directives/bind) is not used in the site. Default: empty, which binds to all interfaces.
|
||||
|
||||
|
||||
##### `order`
|
||||
|
@ -298,9 +298,12 @@ Customizes [HTTP servers](/docs/json/apps/http/servers/) with settings that pote
|
|||
Can be specified more than once, with different `listener_address` values, to configure different options per server. For example, `servers :443` will only apply to the server that is bound to the listener address `:443`. Omitting the listener address will apply the options to any remaining server.
|
||||
|
||||
<aside class="tip">
|
||||
Use the <a href="/docs/command-line#caddy-adapt"><code>caddy adapt</code></a> command to find the listen address for the servers in your Caddyfile.
|
||||
|
||||
Use the [`caddy adapt`](/docs/command-line#caddy-adapt) command to find the listen address for the servers in your Caddyfile.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
For example, to configure different options for the servers on port `:80` and `:443`, you would specify two `servers` blocks:
|
||||
|
||||
```caddy
|
||||
|
|
|
@ -260,7 +260,8 @@ Because this command uses the API, the admin endpoint must not be disabled.
|
|||
<pre><code class="cmd bash">caddy reverse-proxy
|
||||
[--from <addr>]
|
||||
--to <addr>
|
||||
[--change-host-header]</code></pre>
|
||||
[--change-host-header]
|
||||
[--internal-certs]</code></pre>
|
||||
|
||||
Spins up a simple but production-ready HTTP(S) reverse proxy.
|
||||
|
||||
|
@ -270,6 +271,8 @@ Spins up a simple but production-ready HTTP(S) reverse proxy.
|
|||
|
||||
`--change-host-header` will cause Caddy to change the Host header from the incoming value to the address of the upstream.
|
||||
|
||||
`--internal-certs` will cause Caddy to issue certificates using its internal issuer (effectively self-signed) for the domain specified in the `--from` address.
|
||||
|
||||
Both `--from` and `--to` parameters can be URLs, as scheme and domain name will be inferred from the provided URL (paths and query strings ignored). Or they can be a simple network address and not a complete URL.
|
||||
|
||||
This command disables the admin API so it is easier to run multiple instances on a local development machine.
|
||||
|
@ -334,9 +337,12 @@ Once started, you can use [`caddy stop`](#caddy-stop) or the [`POST /stop`](/doc
|
|||
[--config <path> [--adapter <name>]]</code></pre>
|
||||
|
||||
<aside class="tip">
|
||||
Stopping (and restarting) the server is orthogonal to config changes. <b>Do not use the stop command to change configuration in production, unless you want downtime.</b> Use the <a href="#caddy-reload">caddy reload</a> command instead.
|
||||
|
||||
Stopping (and restarting) the server is orthogonal to config changes. **Do not use the stop command to change configuration in production, unless you want downtime.** Use the [`caddy reload`](#caddy-reload) command instead.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
Gracefully stops the running Caddy process (other than the process of the stop command) and causes it to exit. It uses the [`POST /stop`](/docs/api#post-stop) endpoint of the admin API to perform a graceful shutdown.
|
||||
|
||||
The address of this request can be customized using the `--address` flag, or from the given `--config`, if the running instance's admin API is not using the default listen address.
|
||||
|
|
|
@ -32,7 +32,6 @@ You can use a config adapter by specifying it on the command line by using the `
|
|||
Or via the API at the [`/load` endpoint](/docs/api#post-load):
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/yaml" \
|
||||
--data-binary @caddy.yaml</code></pre>
|
||||
|
||||
|
|
|
@ -51,7 +51,9 @@ unix//path/to/socket
|
|||
```
|
||||
|
||||
<aside class="tip">
|
||||
Caddy network addresses are not URLs. URLs couple the lower and higher layers of the <a href="https://en.wikipedia.org/wiki/OSI_model#Layer_architecture">OSI model</a>, but Caddy often uses network addresses independently of a specific application, so combining them would be problematic. In Caddy, network addresses refer precisely to resources that can be dialed or bound at L3-L5, but URLs combine L3-L7, which is too many. A network address requires a host+port and path to be mutually exclusive, but URLs do not. Network addresses sometimes support port ranges, but URLs do not.
|
||||
|
||||
Caddy network addresses are not URLs. URLs couple the lower and higher layers of the [OSI model](https://en.wikipedia.org/wiki/OSI_model#Layer_architecture), but Caddy often uses network addresses independently of a specific application, so combining them would be problematic. In Caddy, network addresses refer precisely to resources that can be dialed or bound at L3-L5, but URLs combine L3-L7, which is too many. A network address requires a host+port and path to be mutually exclusive, but URLs do not. Network addresses sometimes support port ranges, but URLs do not.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
|
@ -60,9 +62,12 @@ unix//path/to/socket
|
|||
Caddy's configuration supports the use of _placeholders_ (variables). Using placeholders is a simple way to inject dynamic values into a static configuration.
|
||||
|
||||
<aside class="tip">
|
||||
Placeholders are a similar idea to variables in other software. For example, <a href="https://nginx.org/en/docs/varindex.html">nginx has variables</a> like $uri and $document_root.
|
||||
|
||||
Placeholders are a similar idea to variables in other software. For example, [nginx has variables](https://nginx.org/en/docs/varindex.html) like `$uri` and `$document_root`.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
Placeholders are bounded on either side by curly braces `{ }` and contain the variable name inside, for example: `{foo.bar}`. Placeholder braces can be escaped, `\{like so\}`. Variable names are typically namespaced with dots to avoid collisions across modules.
|
||||
|
||||
Which placeholders are available depends on the context. Not all placeholders are available in all parts of the config. For example, [the HTTP app sets placeholders](/docs/json/apps/http/#docs) that are only available in areas of the config related to handling HTTP requests.
|
||||
|
@ -94,10 +99,13 @@ This section contains information about where to find various files. File and di
|
|||
There is no single, conventional place for you to put your config files. Put them wherever makes the most sense to you.
|
||||
|
||||
<aside class="tip">
|
||||
The only exception to this might be a file named "Caddyfile" in the current working directory, which the caddy command tries for convenience if no other config file is specified.
|
||||
|
||||
The only exception to this might be a file named `Caddyfile` in the current working directory, which the caddy command tries for convenience if no other config file is specified.
|
||||
|
||||
</aside>
|
||||
|
||||
Distributions that ship with a default config file should document where this config file is at, even if it might be obvious to the package/distro maintainers.
|
||||
|
||||
Distributions that ship with a default config file should document where this config file is at, even if it might be obvious to the package/distro maintainers. For most Linux installations, the Caddyfile will be found at `/etc/caddy/Caddyfile`.
|
||||
|
||||
|
||||
### Data directory
|
||||
|
@ -128,9 +136,12 @@ It is crucial that this directory is persistent and writeable by Caddy.
|
|||
This is where Caddy may store certain configuration to disk. Most notably, it persists the last active configuration (by default) to this folder for easy resumption later using [`caddy run --resume`](/docs/command-line#caddy-run).
|
||||
|
||||
<aside class="tip">
|
||||
The configuration directory is <i>not</i> where you need to store <a href="#your-config-files">your config files</a>. (Though, you are allowed to.)
|
||||
|
||||
The configuration directory is *not* where you need to store [your config files](#your-config-files). (Though, you are allowed to.)
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
If the `XDG_CONFIG_HOME` environment variable is set, it is `$XDG_CONFIG_HOME/caddy`.
|
||||
|
||||
Otherwise, its path varies by platform, adhering to OS conventions:
|
||||
|
@ -150,7 +161,7 @@ It is crucial that this directory is persistent and writeable by Caddy.
|
|||
|
||||
## Durations
|
||||
|
||||
Duration strings are commonly used throughout Caddy's configuration. They take on the same format as [Go's time.ParseDuration syntax](https://golang.org/pkg/time/#ParseDuration) except you can also use `d` for day (we assume 1 day = 24 hours for simplicity). Valid units are:
|
||||
Duration strings are commonly used throughout Caddy's configuration. They take on the same format as [Go's `time.ParseDuration` syntax](https://golang.org/pkg/time/#ParseDuration) except you can also use `d` for day (we assume 1 day = 24 hours for simplicity). Valid units are:
|
||||
|
||||
- `ns` (nanosecond)
|
||||
- `us`/`µs` (microsecond)
|
||||
|
|
|
@ -49,9 +49,12 @@ foo.gizmo
|
|||
...</code></pre>
|
||||
|
||||
<aside class="tip">
|
||||
The <a href="https://github.com/caddyserver/xcaddy"><code>xcaddy</code> command</a> is an important part of every module developer's workflow. It compiles Caddy with your plugin, then runs it with the given arguments. It discards the temporary binary each time (similar to <code>go run</code>).
|
||||
|
||||
The [`xcaddy` command](https://github.com/caddyserver/xcaddy) is an important part of every module developer's workflow. It compiles Caddy with your plugin, then runs it with the given arguments. It discards the temporary binary each time (similar to `go run`).
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
Congratulations, your module registers with Caddy and can be used in [Caddy's config document](/docs/json/) in whatever places use modules in the same namespace.
|
||||
|
||||
Under the hood, `xcaddy` is simply making a new Go module that requires both Caddy and your plugin (with an appropriate `replace` to use your local development version), then adds an import to ensure it is compiled in:
|
||||
|
|
|
@ -45,9 +45,12 @@ This blocks forever, but what is it doing? At the moment... nothing. By default,
|
|||
<pre><code class="cmd bash">curl localhost:2019/config/</code></pre>
|
||||
|
||||
<aside class="tip">
|
||||
This is <b>not</b> your website: the administration endpoint at localhost:2019 is used for controlling Caddy and is restricted to localhost by default.
|
||||
|
||||
This is **not** your website: the administration endpoint at localhost:2019 is used for controlling Caddy and is restricted to localhost by default.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<aside class="complete">Try the API</aside>
|
||||
|
||||
We can make Caddy useful by giving it a config. This can be done many ways, but we'll start by making a POST request to the [/load](/docs/api#post-load) endpoint using `curl` in the next section.
|
||||
|
@ -83,13 +86,15 @@ Save this to a JSON file (e.g. `caddy.json`):
|
|||
```
|
||||
|
||||
<aside class="tip">
|
||||
You do not have to use config files, but we are for this tutorial. Caddy's <a href="/docs/api">admin API</a> is designed for use by other programs or scripts.
|
||||
|
||||
You do not have to use config files, but we are for this tutorial. Caddy's [admin API](/docs/api) is designed for use by other programs or scripts.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
Then upload it:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
</code></pre>
|
||||
|
@ -196,9 +201,12 @@ It is important to note that both JSON and the Caddyfile (and [any other support
|
|||
## API vs. Config files
|
||||
|
||||
<aside class="tip">
|
||||
Under the hood, even config files go through Caddy's API endpoints; the <code>caddy</code> command just wraps up those API calls for you.
|
||||
|
||||
Under the hood, even config files go through Caddy's API endpoints; the `caddy` command just wraps up those API calls for you.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
You will also want to decide whether your workflow is API-based or CLI-based. (You _can_ use both the API and config files on the same server, but we don't recommend it: best to have one source of truth.)
|
||||
|
||||
API | Config files
|
||||
|
|
|
@ -16,7 +16,9 @@ This page describes various methods for installing Caddy on your system.
|
|||
- [DigitalOcean](#digitalocean)
|
||||
|
||||
<aside class="tip">
|
||||
Our <a href="https://github.com/caddyserver/dist">official packages</a> come only with the standard modules. If you need third-party plugins, <a href="/docs/build#xcaddy">build from source with <code>xcaddy</code></a> or use <a href="/download">our download page</a>.
|
||||
|
||||
Our [official packages](https://github.com/caddyserver/dist) come only with the standard modules. If you need third-party plugins, [build from source with `xcaddy`](/docs/build#xcaddy) or use [our download page](/download).
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
|
|
|
@ -131,9 +131,12 @@ As you saw above, messages are emitted by **loggers**. The messages are then sen
|
|||
Caddy lets you [configure multiple logs](/docs/json/logging/logs/) which can process messages. A log consists of an encoder, writer, minimum level, sampling ratio, and a list of loggers to include or exclude. In Caddy, there is always a default log named `default`. You can customize it by specifying a log keyed as `"default"` in [this object](/docs/json/logging/logs/) in the config.
|
||||
|
||||
<aside class="tip">
|
||||
Now would be a good time to <a href="/docs/json/logging/">explore Caddy's logging docs</a> so you can become familiar with the structure and parameters we're talking about.
|
||||
|
||||
Now would be a good time to [explore Caddy's logging docs](/docs/json/logging/) so you can become familiar with the structure and parameters we're talking about.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
- **Encoder:** The format for the log. Transforms the in-memory data representation into a byte slice. Encoders have access to all fields of a log message.
|
||||
- **Writer:** The log output. Can be any log writer module, like to a file or network socket. It simply writes bytes.
|
||||
- **Level:** Logs have various levels, from DEBUG to FATAL. Messages lower than the specified level will be ignored by the log.
|
||||
|
|
|
@ -135,9 +135,9 @@ All Caddy HTTP middleware handlers are instrumented automatically for
|
|||
determining request latency, time-to-first-byte, errors, and request/response
|
||||
body sizes.
|
||||
|
||||
<aside class="tip">Because all middleware handlers are instrumented, and many
|
||||
requests are handled by multiple handlers, make sure not to simply sum
|
||||
all the counters together.</aside>
|
||||
<aside class="tip">
|
||||
Because all middleware handlers are instrumented, and many requests are handled by multiple handlers, make sure not to simply sum all the counters together.
|
||||
</aside>
|
||||
|
||||
For the histogram metrics below, the buckets are currently not configurable.
|
||||
For durations, the default ([`prometheus.DefBuckets`](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#pkg-variables)
|
||||
|
@ -220,9 +220,12 @@ Label | Description
|
|||
Once you have Prometheus scraping Caddy's metrics, you can start to see some
|
||||
interesting metrics about how Caddy's performing.
|
||||
|
||||
<aside class="tip">If you've started up a Prometheus server to scrape Caddy with
|
||||
the config above, try pasting these queries into the Prometheus UI at
|
||||
<a href="http://localhost:9090/graph">http://localhost:9090/graph</a></aside>
|
||||
<aside class="tip">
|
||||
|
||||
If you've started up a Prometheus server to scrape Caddy with the config above, try pasting these queries into the Prometheus UI at [http://localhost:9090/graph](http://localhost:9090/graph)
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
For example, to see the per-second request rate, as averaged over 5 minutes:
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ First start Caddy:
|
|||
Caddy is currently running idle (with a blank configuration). Give it a simple config with `curl`:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @- << EOF
|
||||
{
|
||||
|
@ -44,7 +43,6 @@ EOF</code></pre>
|
|||
Giving a POST body with [Heredoc](https://en.wikipedia.org/wiki/Here_document#Unix_shells) can be tedious, so if you prefer to use files, save the JSON to a file called `caddy.json` and then use this command instead:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
</code></pre>
|
||||
|
|
|
@ -13,9 +13,12 @@ localhost
|
|||
```
|
||||
|
||||
<aside class="tip">
|
||||
If the HTTP and HTTPS ports (80 and 443, respectively) are privileged ports on your OS, you will either need to run with elevated privileges or use a higher port. To use a higher port, just change the address to something like <code>localhost:2015</code> and change the HTTP port using the <a href="/docs/caddyfile/options">http_port</a> Caddyfile option.
|
||||
|
||||
If the HTTP and HTTPS ports (80 and 443, respectively) are privileged ports on your OS, you will either need to run with elevated privileges or use a higher port. To use a higher port, just change the address to something like `localhost:2015` and change the HTTP port using the [`http_port`](/docs/caddyfile/options) Caddyfile option.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
Then hit enter and type what you want it to do, so it looks like this:
|
||||
|
||||
```caddy
|
||||
|
@ -56,7 +59,6 @@ localhost:2016 {
|
|||
You can give Caddy the updated configuration two ways, either with the API directly:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: text/caddyfile" \
|
||||
--data-binary @Caddyfile
|
||||
</code></pre>
|
||||
|
|
|
@ -30,7 +30,9 @@ Before continuing, verify correct records with an authoritative lookup. Replace
|
|||
|
||||
Also make sure your server is externally reachable on ports 80 and 443 from a public interface.
|
||||
|
||||
<aside class="tip">If you're on your home or other restricted network, you may need to forward ports or adjust firewall settings.</aside>
|
||||
<aside class="tip">
|
||||
If you're on your home or other restricted network, you may need to forward ports or adjust firewall settings.
|
||||
</aside>
|
||||
|
||||
All we have to do is start Caddy with your domain name in the config. There are several ways to do this.
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ errors {
|
|||
|
||||
```
|
||||
handle_errors {
|
||||
rewrite * /{http.error.status_code}.html
|
||||
rewrite * /{err.status_code}.html
|
||||
file_server
|
||||
}
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue