mirror of
https://github.com/caddyserver/website.git
synced 2025-04-20 20:16:16 -04:00
Merge branch 'master' into saas
This commit is contained in:
commit
d9f90d7993
25 changed files with 641 additions and 275 deletions
|
@ -128,6 +128,8 @@ The first time a root key is used, Caddy will try to install it into the system'
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
|
Note that automatically installing the certificate into the local trust stores is for convenience only and isn't guaranteed to work, especially if containers are being used or if Caddy is being run as an unprivileged system service. Ultimately, if you are relying on internal PKI, it is the system administrator's responsibility to ensure Caddy's root CA is properly added to the necessary trust stores (this is outside the scope of the web server).
|
||||||
|
|
||||||
|
|
||||||
### CA Intermediates
|
### CA Intermediates
|
||||||
|
|
||||||
|
@ -182,22 +184,34 @@ DNS provider support is a community effort. [Learn how to enable the DNS challen
|
||||||
|
|
||||||
## On-Demand TLS
|
## On-Demand TLS
|
||||||
|
|
||||||
Caddy pioneered a new technology we call **On-Demand TLS**. Many businesses rely on this feature to scale their TLS deployments at lower cost and without operational headaches when serving tens of thousands of sites.
|
Caddy pioneered a new technology we call **On-Demand TLS**, which dynamically obtains a new certificate during the first TLS handshake that requires it, rather than at config load. Crucially, this does not require specifying the domain names in your configuration ahead of time.
|
||||||
|
|
||||||
This unique feature obtains the certificate for a name during the first TLS handshake that requires it, rather than at config load. This is useful if:
|
Many businesses rely on this unique feature to scale their TLS deployments at lower cost and without operational headaches when serving tens of thousands of sites.
|
||||||
|
|
||||||
- you do not know all the domain names up front,
|
On-demand TLS is useful if:
|
||||||
- domain names might not be properly configured right away (e.g. DNS records not yet set),
|
|
||||||
- or you are not in control of the domain names (e.g. they are customer domains).
|
|
||||||
|
|
||||||
When on-demand TLS is enabled, a TLS handshake may trigger maintenance for the relevant certificate. If no existing certificate is available, this process slows down only the initial TLS handshake while a certificate is obtained in the foreground; all other handshakes will not be affected (except those waiting on the same certificate). If an existing certificate can be used, the handshake will complete immediately, and maintenance (i.e. renewal) will happen in the background.
|
- you do not know all the domain names when you start or reload your server,
|
||||||
|
- domain names might not be properly configured right away (DNS records not yet set),
|
||||||
|
- you are not in control of the domain names (e.g. they are customer domains).
|
||||||
|
|
||||||
You can enable it using the [on_demand](/docs/json/apps/tls/automation/on_demand/) property in your TLS automation config, or the [on_demand Caddyfile subdirective](/docs/caddyfile/directives/tls#syntax). Note that enabling on-demand TLS is separate from configuring how it works. **Important:** To prevent abuse, you should specify rate limits and/or an endpoint that Caddy can query to ask if a certificate is allowed to be obtained for a hostname.
|
When on-demand TLS is enabled, you do not need to specify the domain names in your config in order to get certificates for them. Instead, when a TLS handshake is received for a server name (SNI) that Caddy does not yet have a certificate for, the handshake is held while Caddy obtains a certificate to use to complete the handshake. The delay is usually only a few seconds, and only that initial handshake is slow. All future handshakes are fast because certificates are cached and reused, and renewals happen in the background. Future handshakes may trigger maintenance for the certificate to keep it renewed, but this maintenance happens in the background if the certificate hasn't expired yet.
|
||||||
|
|
||||||
|
### Using On-Demand TLS
|
||||||
|
|
||||||
|
**In production environments, on-demand TLS must be both enabled and restricted. Enabling without restricting opens your server to attack.**
|
||||||
|
|
||||||
|
Enabling on-demand TLS happens in [TLS automation policies](/docs/json/apps/tls/automation/policies/) if using the JSON config, or [in site blocks with the `tls` directive](/docs/caddyfile/directives/tls) if using the Caddyfile.
|
||||||
|
|
||||||
|
To prevent abuse of this feature, you must configure restrictions. This is done in the [`automation` object of the JSON config](/docs/json/apps/tls/automation/on_demand/), or the [`on_demand_tls` global option](/docs/caddyfile/options#on-demand-tls) of the Caddyfile. Restrictions are "global" and aren't configurable per-site or per-domain. The primary restriction is an "ask" endpoint to which Caddy will send an HTTP request to ask if it has permission to obtain and manage a certificate for the domain in the handshake. This means you will need some internal backend that can, for example, query the accounts table of your database and see if a customer has signed up with that domain name.
|
||||||
|
|
||||||
|
You can also configure rate limits as restrictions, though rate limits alone are not a sufficient protection.
|
||||||
|
|
||||||
Be mindful of how quickly your CA is able to issue certificates. If it takes more than a few seconds, this will negatively impact the user experience (for the first client only).
|
Be mindful of how quickly your CA is able to issue certificates. If it takes more than a few seconds, this will negatively impact the user experience (for the first client only).
|
||||||
|
|
||||||
Due to its deferred nature and potential for abuse (if not mitigated through proper configuration), we recommend enabling on-demand TLS only when your actual use case is described above.
|
Due to its deferred nature and potential for abuse (if not mitigated through proper configuration), we recommend enabling on-demand TLS only when your actual use case is described above.
|
||||||
|
|
||||||
|
[See our wiki article for more information about using on-demand TLS effectively.](https://caddy.community/t/serving-tens-of-thousands-of-domains-over-https-with-caddy/11179)
|
||||||
|
|
||||||
## Errors
|
## Errors
|
||||||
|
|
||||||
Caddy does its best to continue if errors occur with certificate management.
|
Caddy does its best to continue if errors occur with certificate management.
|
||||||
|
@ -243,7 +257,7 @@ Before attempting any ACME transactions, Caddy will test the configured storage
|
||||||
|
|
||||||
Caddy can obtain and manage wildcard certificates when it is configured to serve a site with a qualifying wildcard name. A site name qualifies for a wildcard if only its left-most domain label is a wildcard. For example, `*.example.com` qualifies, but these do not: `sub.*.example.com`, `foo*.example.com`, `*bar.example.com`, and `*.*.example.com`.
|
Caddy can obtain and manage wildcard certificates when it is configured to serve a site with a qualifying wildcard name. A site name qualifies for a wildcard if only its left-most domain label is a wildcard. For example, `*.example.com` qualifies, but these do not: `sub.*.example.com`, `foo*.example.com`, `*bar.example.com`, and `*.*.example.com`.
|
||||||
|
|
||||||
If using the Caddyfile, Caddy takes site names literally with regards to the certificate subject names. In other words, a site defined as `sub.example.com` will cause Caddy to manage a certificate for `sub.example.com`, and a site defined as `*.example.com` will cause Caddy to manage a wildcard certificate for `*.example.com`. If you need different behavior, the [JSON config](/docs/json/) gives you precise control over certificate subjects and site names ("host matchers").
|
If using the Caddyfile, Caddy takes site names literally with regards to the certificate subject names. In other words, a site defined as `sub.example.com` will cause Caddy to manage a certificate for `sub.example.com`, and a site defined as `*.example.com` will cause Caddy to manage a wildcard certificate for `*.example.com`. You can see this demonstrated on our [Common Caddyfile Patterns](/docs/caddyfile/patterns#wildcard-certificates) page. If you need different behavior, the [JSON config](/docs/json/) gives you more precise control over certificate subjects and site names ("host matchers").
|
||||||
|
|
||||||
Wildcard certificates represent a wide degree of authority and should only be used when you have so many subdomains that managing individual certificates for them would strain the PKI or cause you to hit CA-enforced rate limits.
|
Wildcard certificates represent a wide degree of authority and should only be used when you have so many subdomains that managing individual certificates for them would strain the PKI or cause you to hit CA-enforced rate limits.
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ title: "Build from source"
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
|
|
||||||
- [Go](https://golang.org/doc/install) 1.15 or newer
|
- [Go](https://golang.org/doc/install) 1.16 or newer
|
||||||
|
|
||||||
Clone the repository:
|
Clone the repository:
|
||||||
|
|
||||||
|
|
|
@ -252,6 +252,7 @@ You can use any [Caddy placeholders](/docs/conventions#placeholders) in the Cadd
|
||||||
| `{tls_client_serial}` | `{http.request.tls.client.serial}` |
|
| `{tls_client_serial}` | `{http.request.tls.client.serial}` |
|
||||||
| `{tls_client_subject}` | `{http.request.tls.client.subject}` |
|
| `{tls_client_subject}` | `{http.request.tls.client.subject}` |
|
||||||
| `{tls_client_certificate_pem}` | `{http.request.tls.client.certificate_pem}` |
|
| `{tls_client_certificate_pem}` | `{http.request.tls.client.certificate_pem}` |
|
||||||
|
| `{upstream_hostport}` | `{http.reverse_proxy.upstream.hostport}` |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,37 @@
|
||||||
title: Caddyfile Directives
|
title: Caddyfile Directives
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#directive-table table {
|
||||||
|
margin: 0 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#directive-table tr:hover {
|
||||||
|
background: rgba(0, 0, 0, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#directive-table tr td:first-child {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#directive-table a:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: block;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
# Caddyfile Directives
|
# Caddyfile Directives
|
||||||
|
|
||||||
The following directives come standard with Caddy, and can be used in the HTTP Caddyfile:
|
The following directives come standard with Caddy, and can be used in the HTTP Caddyfile:
|
||||||
|
|
||||||
|
<div id="directive-table">
|
||||||
|
|
||||||
Directive | Description
|
Directive | Description
|
||||||
----------|------------
|
----------|------------
|
||||||
**[abort](/docs/caddyfile/directives/abort)** | Aborts the HTTP request
|
**[abort](/docs/caddyfile/directives/abort)** | Aborts the HTTP request
|
||||||
|
@ -38,6 +65,7 @@ Directive | Description
|
||||||
**[try_files](/docs/caddyfile/directives/try_files)** | Rewrite that depends on file existence
|
**[try_files](/docs/caddyfile/directives/try_files)** | Rewrite that depends on file existence
|
||||||
**[uri](/docs/caddyfile/directives/uri)** | Manipulate the URI
|
**[uri](/docs/caddyfile/directives/uri)** | Manipulate the URI
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
|
|
||||||
|
@ -83,29 +111,33 @@ header
|
||||||
request_body
|
request_body
|
||||||
|
|
||||||
redir
|
redir
|
||||||
rewrite
|
|
||||||
|
|
||||||
|
# URI manipulation
|
||||||
|
rewrite
|
||||||
uri
|
uri
|
||||||
try_files
|
try_files
|
||||||
|
|
||||||
|
# middleware handlers; some wrap responses
|
||||||
basicauth
|
basicauth
|
||||||
request_header
|
request_header
|
||||||
encode
|
encode
|
||||||
|
push
|
||||||
templates
|
templates
|
||||||
|
|
||||||
|
# special routing & dispatching directives
|
||||||
handle
|
handle
|
||||||
handle_path
|
handle_path
|
||||||
route
|
route
|
||||||
push
|
|
||||||
|
|
||||||
|
# handlers that typically respond to requests
|
||||||
|
abort
|
||||||
|
error
|
||||||
respond
|
respond
|
||||||
metrics
|
metrics
|
||||||
reverse_proxy
|
reverse_proxy
|
||||||
php_fastcgi
|
php_fastcgi
|
||||||
file_server
|
file_server
|
||||||
acme_server
|
acme_server
|
||||||
abort
|
|
||||||
error
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can override/customize this ordering by using the [`order` global option](/docs/caddyfile/options) or the [`route` directive](/docs/caddyfile/directives/route).
|
You can override/customize this ordering by using the [`order` global option](/docs/caddyfile/options) or the [`route` directive](/docs/caddyfile/directives/route).
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
title: encode (Caddyfile directive)
|
title: encode (Caddyfile directive)
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
|
||||||
|
addLinksToSubdirectives();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
# encode
|
# encode
|
||||||
|
|
||||||
Encodes responses using the configured encoding(s). A typical use for encoding is compression.
|
Encodes responses using the configured encoding(s). A typical use for encoding is compression.
|
||||||
|
@ -27,10 +34,10 @@ encode [<matcher>] <formats...> {
|
||||||
```
|
```
|
||||||
|
|
||||||
- **<formats...>** is the list of encoding formats to enable. If multiple encodings are enabled, the encoding is chosen based the request's Accept-Encoding header; if the client has no strong preference (q-factor), then the first supported encoding is used.
|
- **<formats...>** is the list of encoding formats to enable. If multiple encodings are enabled, the encoding is chosen based the request's Accept-Encoding header; if the client has no strong preference (q-factor), then the first supported encoding is used.
|
||||||
- **gzip** enables Gzip compression, optionally at the specified level.
|
- **gzip** <span id="gzip"/> enables Gzip compression, optionally at the specified level.
|
||||||
- **zstd** enables Zstandard compression.
|
- **zstd** <span id="zstd"/> enables Zstandard compression.
|
||||||
- **minimum_length** the minimum number of bytes a response should have to be encoded (default: 512).
|
- **minimum_length** <span id="minimum_length"/> the minimum number of bytes a response should have to be encoded (default: 512).
|
||||||
- **match** is a [response matcher](#response-matcher). Only matching responses are encoded. The default looks like this:
|
- **match** <span id="match"/> is a [response matcher](#response-matcher). Only matching responses are encoded. The default looks like this:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
match {
|
match {
|
||||||
|
|
|
@ -20,6 +20,7 @@ file_server [<matcher>] [browse] {
|
||||||
browse [<template_file>]
|
browse [<template_file>]
|
||||||
precompressed <formats...>
|
precompressed <formats...>
|
||||||
status <status>
|
status <status>
|
||||||
|
disable_canonical_uris
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ file_server [<matcher>] [browse] {
|
||||||
- **<template_file>** is an optional custom template file to use for directory listings. Defaults to the template that can be found [here in the source code ](https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/fileserver/browsetpl.go). Browse templates can use actions from [the standard templates module](/docs/modules/http.handlers.templates#docs) as well.
|
- **<template_file>** is an optional custom template file to use for directory listings. Defaults to the template that can be found [here in the source code ](https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/fileserver/browsetpl.go). Browse templates can use actions from [the standard templates module](/docs/modules/http.handlers.templates#docs) as well.
|
||||||
- **precompressed** is the list of encoding formats to search for precompressed sidecar files. Arguments are an ordered list of encoding formats to search for precompressed sidecar files. Supported formats are `gzip`, `zstd` and `br`.
|
- **precompressed** is the list of encoding formats to search for precompressed sidecar files. Arguments are an ordered list of encoding formats to search for precompressed sidecar files. Supported formats are `gzip`, `zstd` and `br`.
|
||||||
- **status** is an optional status code override to be used when writing the response. Particularly useful when responding to a request with a custom error page. Can be a 3-digit status code, For example: `404`. Placeholders are supported. By default, the written status code will typically be `200`, or `206` for partial content.
|
- **status** is an optional status code override to be used when writing the response. Particularly useful when responding to a request with a custom error page. Can be a 3-digit status code, For example: `404`. Placeholders are supported. By default, the written status code will typically be `200`, or `206` for partial content.
|
||||||
|
- **disable_canonical_uris** disables the default behaviour of redirecting to add a trailing slash if the request path is a directory, or remove the trailing slash if the request path is a file. Note that by default, canonicalization will not happen if the last element of the request's path (the filename) underwent an internal rewrite, to avoid clobbering an explicit rewrite with implicit behaviour.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ title: header (Caddyfile directive)
|
||||||
|
|
||||||
Manipulates HTTP header fields on the response. It can set, add, and delete header values, or perform replacements using regular expressions.
|
Manipulates HTTP header fields on the response. It can set, add, and delete header values, or perform replacements using regular expressions.
|
||||||
|
|
||||||
By default, header operations are performed immediately unless any of the headers are being deleted (`-` prefix) or setting a defualt value (`?` prefix). In those cases, the header operations are automatically deferred until the time they are being written to the client.
|
By default, header operations are performed immediately unless any of the headers are being deleted (`-` prefix) or setting a default value (`?` prefix). In those cases, the header operations are automatically deferred until the time they are being written to the client.
|
||||||
|
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
|
|
|
@ -32,7 +32,7 @@ Import a snippet that sets CORS headers using an import argument:
|
||||||
(cors) {
|
(cors) {
|
||||||
@origin header Origin {args.0}
|
@origin header Origin {args.0}
|
||||||
header @origin Access-Control-Allow-Origin "{args.0}"
|
header @origin Access-Control-Allow-Origin "{args.0}"
|
||||||
header @origin Access-Control-Request-Method GET
|
header @origin Access-Control-Allow-Methods "OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE"
|
||||||
}
|
}
|
||||||
|
|
||||||
example.com {
|
example.com {
|
||||||
|
|
|
@ -2,12 +2,37 @@
|
||||||
title: log (Caddyfile directive)
|
title: log (Caddyfile directive)
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
|
||||||
|
addLinksToSubdirectives();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
# log
|
# log
|
||||||
|
|
||||||
Enables and configures HTTP request logging (also known as access logs).
|
Enables and configures HTTP request logging (also known as access logs).
|
||||||
|
|
||||||
The `log` directive applies to the host/port of the site block it appears in, not any other part of the site address (e.g. path).
|
The `log` directive applies to the host/port of the site block it appears in, not any other part of the site address (e.g. path).
|
||||||
|
|
||||||
|
- [Syntax](#syntax)
|
||||||
|
- [Output modules](#output-modules)
|
||||||
|
- [stderr](#stderr)
|
||||||
|
- [stdout](#stdout)
|
||||||
|
- [discard](#discard)
|
||||||
|
- [file](#file)
|
||||||
|
- [net](#net)
|
||||||
|
- [Format modules](#format-modules)
|
||||||
|
- [console](#console)
|
||||||
|
- [json](#json)
|
||||||
|
- [single_field](#single-field)
|
||||||
|
- [filter](#filter)
|
||||||
|
- [delete](#delete)
|
||||||
|
- [replace](#replace)
|
||||||
|
- [ip_mask](#ip-mask)
|
||||||
|
- [Examples](#examples)
|
||||||
|
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
@ -20,7 +45,9 @@ log {
|
||||||
|
|
||||||
- **output** configures where to write the logs. See [Output modules](#output-modules) below. Default: `stderr`
|
- **output** configures where to write the logs. See [Output modules](#output-modules) below. Default: `stderr`
|
||||||
- **format** describes how to encode, or format, the logs. See [Format modules](#format-modules) below. Default: `console` if `stdout` is detected to be a terminal, `json` otherwise.
|
- **format** describes how to encode, or format, the logs. See [Format modules](#format-modules) below. Default: `console` if `stdout` is detected to be a terminal, `json` otherwise.
|
||||||
- **level** is the minimum entry level to log. Default: `INFO`
|
- **level** is the minimum entry level to log. Default: `INFO`. Note that access logs currently only emit `INFO` and `ERROR` level logs.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Output modules
|
### Output modules
|
||||||
|
|
||||||
|
@ -81,7 +108,7 @@ output net <address> {
|
||||||
```
|
```
|
||||||
|
|
||||||
- **<address>** is the [address](/docs/conventions#network-addresses) to write logs to.
|
- **<address>** is the [address](/docs/conventions#network-addresses) to write logs to.
|
||||||
- **<dial_timeout>** is how long to wait for a successful connection to the log socket. Log emissions may be blocked for up to this long if the socket goes down.
|
- **dial_timeout** is how long to wait for a successful connection to the log socket. Log emissions may be blocked for up to this long if the socket goes down.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,6 +160,8 @@ format json
|
||||||
|
|
||||||
#### single_field
|
#### single_field
|
||||||
|
|
||||||
|
<span class="warning">⚠️ This format is deprecated, and will be removed in a future version.</span>
|
||||||
|
|
||||||
Writes only a single field from the structure log entry. Useful if one of the fields has all the information you need.
|
Writes only a single field from the structure log entry. Useful if one of the fields has all the information you need.
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
@ -199,6 +228,7 @@ Enable access logging (to the console):
|
||||||
log
|
log
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Write logs to a file (with log rolling, which is enabled by default):
|
Write logs to a file (with log rolling, which is enabled by default):
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
@ -207,6 +237,7 @@ log {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Customize log rolling:
|
Customize log rolling:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
@ -219,7 +250,10 @@ log {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Use common log format (deprecated, but can be useful for older setups):
|
|
||||||
|
Use Common Log Format (CLF):
|
||||||
|
|
||||||
|
<span class="warning">⚠️ The `single_field` format is deprecated and will be removed in a future version. To encode logs in common log format, please use the [`format-encoder`](https://github.com/caddyserver/format-encoder) plugin.</span>
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
log {
|
log {
|
||||||
|
@ -227,6 +261,7 @@ log {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Delete the Authorization request header from the logs:
|
Delete the Authorization request header from the logs:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
@ -240,6 +275,7 @@ log {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Mask the remote address from the request, keeping the first 16 bytes (i.e. 255.255.0.0) for IPv4 addresses, and the first 64 bytes from IPv6 addresses, and also deletes the `common_log` field which would normally contain an unmasked IP address:
|
Mask the remote address from the request, keeping the first 16 bytes (i.e. 255.255.0.0) for IPv4 addresses, and the first 64 bytes from IPv6 addresses, and also deletes the `common_log` field which would normally contain an unmasked IP address:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
|
|
@ -2,6 +2,28 @@
|
||||||
title: reverse_proxy (Caddyfile directive)
|
title: reverse_proxy (Caddyfile directive)
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
// Fix response matchers to render with the right color,
|
||||||
|
// and link to response matchers section
|
||||||
|
$('pre.chroma .k:contains("@")')
|
||||||
|
.map(function(k, item) {
|
||||||
|
let text = item.innerText.replace(/</g,'<').replace(/>/g,'>');
|
||||||
|
let url = '#' + item.innerText.replace(/_/g, "-");
|
||||||
|
$(item).addClass('nd').removeClass('k')
|
||||||
|
$(item).html('<a href="#response-matcher" style="color: inherit;" title="Response matcher">' + text + '</a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fix matcher placeholder
|
||||||
|
$('pre.chroma .k:contains("handle_response")').first().nextAll().slice(0, 3)
|
||||||
|
.wrapAll('<span class="nd">').parent()
|
||||||
|
.html('<a href="#response-matcher" style="color: inherit;" title="Response matcher">[<matcher>]</a>')
|
||||||
|
|
||||||
|
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
|
||||||
|
addLinksToSubdirectives();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
# reverse_proxy
|
# reverse_proxy
|
||||||
|
|
||||||
Proxies requests to one or more backends with configurable transport, load balancing, health checking, header manipulation, and buffering options.
|
Proxies requests to one or more backends with configurable transport, load balancing, health checking, header manipulation, and buffering options.
|
||||||
|
@ -15,7 +37,7 @@ Proxies requests to one or more backends with configurable transport, load balan
|
||||||
- [Headers](#headers)
|
- [Headers](#headers)
|
||||||
- [Transports](#transports)
|
- [Transports](#transports)
|
||||||
- [The `http` transport](#the-http-transport)
|
- [The `http` transport](#the-http-transport)
|
||||||
- [The `fastcgi` tranport](#the-fastcgi-transport)
|
- [The `fastcgi` transport](#the-fastcgi-transport)
|
||||||
- [Intercepting responses](#intercepting-responses)
|
- [Intercepting responses](#intercepting-responses)
|
||||||
- [Examples](#examples)
|
- [Examples](#examples)
|
||||||
|
|
||||||
|
@ -83,7 +105,7 @@ reverse_proxy [<matcher>] [<upstreams...>] {
|
||||||
### Upstreams
|
### Upstreams
|
||||||
|
|
||||||
- **<upstreams...>** is a list of upstreams (backends) to which to proxy.
|
- **<upstreams...>** is a list of upstreams (backends) to which to proxy.
|
||||||
- **to** is an alternate way to specify the list of upstreams, one (or more) per line.
|
- **to** <span id="to"/> is an alternate way to specify the list of upstreams, one (or more) per line.
|
||||||
|
|
||||||
Upstream addresses can take the form of a conventional [Caddy network address](/docs/conventions#network-addresses) or a URL that contains only scheme and host/port, with a special exception that the scheme may be prefixed by `srv+` to enable SRV DNS record lookups for load balancing. Valid examples:
|
Upstream addresses can take the form of a conventional [Caddy network address](/docs/conventions#network-addresses) or a URL that contains only scheme and host/port, with a special exception that the scheme may be prefixed by `srv+` to enable SRV DNS record lookups for load balancing. Valid examples:
|
||||||
|
|
||||||
|
@ -103,25 +125,27 @@ 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 dynamic, meaning that the potentially many different backends act as one upstream in terms of health checks and load balancing.
|
If the address is not a URL (i.e. does not have a scheme), then placeholders can be used, but this makes the upstream dynamic, meaning that the potentially many different backends act as one upstream in terms of health checks and load balancing.
|
||||||
|
|
||||||
|
When proxying over HTTPS, you may need to override the `Host` header (which by default, retains the value from the original request) such that the `Host` header matches the TLS SNI value, which is used by servers for routing and certificate selection. See the [Headers](#headers) section below for more details.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Load balancing
|
### Load balancing
|
||||||
|
|
||||||
Load balancing is used whenever more than one upstream is defined.
|
Load balancing is used whenever more than one upstream is defined.
|
||||||
|
|
||||||
- **lb_policy** is the name of the load balancing policy, along with any options. Default: `random`. Can be:
|
- **lb_policy** <span id="lb_policy"/> is the name of the load balancing policy, along with any options. Default: `random`. Can be:
|
||||||
- `first` - choose first available upstream
|
|
||||||
- `header` - map request header to sticky upstream
|
|
||||||
- `ip_hash` - map client IP to sticky upstream
|
|
||||||
- `least_conn` - choose upstream with fewest number of current requests
|
|
||||||
- `random` - randomly choose an upstream
|
- `random` - randomly choose an upstream
|
||||||
- `random_choose <n>` - selects two or more upstreams randomly, then chooses one with least load (`n` is usually 2)
|
- `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
|
- `round_robin` - iterate each upstream in turn
|
||||||
|
- `least_conn` - choose upstream with fewest number of current requests
|
||||||
|
- `ip_hash` - map client IP to sticky upstream
|
||||||
- `uri_hash` - map URI to sticky upstream
|
- `uri_hash` - map URI to sticky upstream
|
||||||
|
- `header [field]` - map request header to sticky upstream
|
||||||
- `cookie [<name> [<secret>]]` - based on the given cookie (default name is `lb` if not specified), which value is hashed; optionally with a secret for HMAC-SHA256
|
- `cookie [<name> [<secret>]]` - based on the given cookie (default name is `lb` if not specified), which value is hashed; optionally with a secret for HMAC-SHA256
|
||||||
|
|
||||||
- **lb_try_duration** is a [duration value](/docs/conventions#durations) that defines how long to try selecting available backends for each request if the next available host is down. By default, this retry is disabled. Clients will wait for up to this long while the load balancer tries to find an available upstream host.
|
- **lb_try_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.
|
||||||
- **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.
|
- **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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,13 +153,13 @@ Load balancing is used whenever more than one upstream is defined.
|
||||||
|
|
||||||
Active health checks perform health checking in the background on a timer:
|
Active health checks perform health checking in the background on a timer:
|
||||||
|
|
||||||
- **health_uri** is the URI path (and optional query) for active health checks.
|
- **health_uri** <span id="health_uri"/> is the URI path (and optional query) for active health checks.
|
||||||
- **health_port** is the port to use for active health checks, if different from the upstream's port.
|
- **health_port** <span id="health_port"/> is the port to use for active health checks, if different from the upstream's port.
|
||||||
- **health_interval** is a [duration value](/docs/conventions#durations) that defines how often to perform active health checks.
|
- **health_interval** <span id="health_interval"/> is a [duration value](/docs/conventions#durations) that defines how often to perform active health checks.
|
||||||
- **health_timeout** is a [duration value](/docs/conventions#durations) that defines how long to wait for a reply before marking the backend as down.
|
- **health_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** 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_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** 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_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** 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.
|
- **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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -143,11 +167,11 @@ Active health checks perform health checking in the background on a timer:
|
||||||
|
|
||||||
Passive health checks happen inline with actual proxied requests:
|
Passive health checks happen inline with actual proxied requests:
|
||||||
|
|
||||||
- **fail_duration** is a [duration value](/docs/conventions#durations) that defines how long to remember a failed request. A duration > 0 enables passive health checking.
|
- **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.
|
||||||
- **max_fails** is the maximum number of failed requests within fail_timeout that are needed before considering a backend to be down; must be >= 1; default is 1.
|
- **max_fails** <span id="max_fails"/> is the maximum number of failed requests within fail_timeout that are needed before considering a backend to be down; must be >= 1; default is 1.
|
||||||
- **unhealthy_status** counts a request as failed if the response comes back with one of these status codes. Can be a 3-digit status code or a status code class ending in `xx`, for example: `404` or `5xx`.
|
- **unhealthy_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** is a [duration value](/docs/conventions#durations) that counts a request as failed if it takes this long to get a response.
|
- **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** 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,26 +179,41 @@ Passive health checks happen inline with actual proxied requests:
|
||||||
|
|
||||||
The proxy **buffers responses** by default for wire efficiency:
|
The proxy **buffers responses** by default for wire efficiency:
|
||||||
|
|
||||||
- **flush_interval** is a [duration value](/docs/conventions#durations) that defines how often Caddy should flush the buffered response body to the client. Set to -1 to disable buffering. It is set to -1 automatically for requests that have a `text/event-stream` response or for HTTP/2 requests where the Content-Length is unspecified.
|
- **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** 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_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** 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.
|
- **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** 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).
|
- **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).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Headers
|
### Headers
|
||||||
|
|
||||||
It can also **manipulate headers** between itself and the backend:
|
The proxy can **manipulate headers** between itself and the backend:
|
||||||
|
|
||||||
- **header_up** Sets, adds, removes, or performs a replacement in a request header going upstream to the backend.
|
- **header_up** <span id="header_up"/> Sets, adds, removes, or performs a replacement in a request header going upstream to the backend.
|
||||||
- **header_down** Sets, adds, removes, or performs a replacement in a response header coming downstream from the backend.
|
- **header_down** <span id="header_down"/> Sets, adds, removes, or performs a replacement in a response header coming downstream from the backend.
|
||||||
|
|
||||||
|
|
||||||
|
#### Defaults
|
||||||
|
|
||||||
By default, Caddy passes thru incoming headers to the backend—including the `Host` header—without modifications, with two exceptions:
|
By default, Caddy passes thru incoming headers to the backend—including the `Host` header—without modifications, with two exceptions:
|
||||||
|
|
||||||
- It adds or augments the [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) header field.
|
- It adds 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-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) header field.
|
||||||
|
|
||||||
Since these header fields are only de-facto standards, Caddy may stop setting them implicitly in the future if the standardized [Forwarded](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded) header field becomes more widely adopted.
|
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.
|
||||||
|
|
||||||
|
#### HTTPS
|
||||||
|
|
||||||
|
For HTTPS upstreams, since the `Host` header retains its original value, it is typically necessary to override the header with the configured upstream address, such that the `Host` header matches the TLS SNI value. A `X-Forwarded-Host` header may also be added to inform the upstream of the original `Host` header's value. For example:
|
||||||
|
|
||||||
|
```caddy-d
|
||||||
|
reverse_proxy https://example.com {
|
||||||
|
header_up Host {upstream_hostport}
|
||||||
|
header_up X-Forwarded-Host {host}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,7 +221,7 @@ Since these header fields are only de-facto standards, Caddy may stop setting th
|
||||||
|
|
||||||
Caddy's proxy **transport** is pluggable:
|
Caddy's proxy **transport** is pluggable:
|
||||||
|
|
||||||
- **transport** defines how to communicate with the backend. Default is `http`.
|
- **transport** <span id="transport"/> defines how to communicate with the backend. Default is `http`.
|
||||||
|
|
||||||
|
|
||||||
#### The `http` transport
|
#### The `http` transport
|
||||||
|
@ -211,25 +250,25 @@ transport http {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- **read_buffer** is the size of the read buffer in bytes.
|
- **read_buffer** <span id="read_buffer"/> is the size of the read buffer in bytes.
|
||||||
- **write_buffer** is the size of the write buffer in bytes.
|
- **write_buffer** <span id="write_buffer"/> is the size of the write buffer in bytes.
|
||||||
- **max_response_header** is the maximum amount of bytes to read from response headers.
|
- **max_response_header** <span id="max_response_header"/> is the maximum amount of bytes to read from response headers.
|
||||||
- **dial_timeout** is how long to wait when connecting to the upstream socket. Accepts [duration values](/docs/conventions#durations).
|
- **dial_timeout** <span id="dial_timeout"/> is how long to wait when connecting to the upstream socket. Accepts [duration values](/docs/conventions#durations).
|
||||||
- **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).
|
- **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).
|
||||||
- **response_header_timeout** is how long to wait for reading response headers from the upstream. Accepts [duration values](/docs/conventions#durations).
|
- **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).
|
||||||
- **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).
|
- **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).
|
||||||
- **tls** uses HTTPS with the backend. This will be enabled automatically if you specify backends using the `https://` scheme or port `:443`.
|
- **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`.
|
||||||
- **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_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** turns off security. _Do not use in production._
|
- **tls_insecure_skip_verify** <span id="tls_insecure_skip_verify"/> turns off security. _Do not use in production._
|
||||||
- **tls_timeout** is a [duration value](/docs/conventions#durations) that specifies how long to wait for the TLS handshake to complete.
|
- **tls_timeout** <span id="tls_timeout"/> is a [duration value](/docs/conventions#durations) that specifies how long to wait for the TLS handshake to complete.
|
||||||
- **tls_trusted_ca_certs** is a list of PEM files that specify CA public keys to trust when connecting to the backend.
|
- **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** sets the ServerName (SNI) to put in the ClientHello; only needed if the remote server requires it.
|
- **tls_server_name** <span id="tls_server_name"/> sets the ServerName (SNI) to put in the ClientHello; only needed if the remote server requires it.
|
||||||
- **keepalive** is either `off` or a [duration value](/docs/conventions#durations) that specifies how long to keep connections open.
|
- **keepalive** <span id="keepalive"/> is either `off` or a [duration value](/docs/conventions#durations) that specifies how long to keep connections open.
|
||||||
- **keepalive_idle_conns** defines the maximum number of connections to keep alive.
|
- **keepalive_idle_conns** <span id="keepalive_idle_conns"/> defines the maximum number of connections to keep alive.
|
||||||
- **keepalive_idle_conns_per_host** if non-zero, controls the maximum idle (keep-alive) connections to keep per-host. Default: `32`
|
- **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** 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`
|
- **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** can be used to disable compression to the backend by setting it to `off`.
|
- **compression** <span id="compression"/> can be used to disable compression to the backend by setting it to `off`.
|
||||||
- **max_conns_per_host** optionally limits the total number of connections per host, including connections in the dialing, active, and idle states. Has no limit by default.
|
- **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. Has no limit by default.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,13 +286,13 @@ transport fastcgi {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- **root** is the root of the site. Default: `{http.vars.root}` or current working directory.
|
- **root** <span id="root"/> is the root of the site. Default: `{http.vars.root}` or current working directory.
|
||||||
- **split** is where to split the path to get PATH_INFO at the end of the URI.
|
- **split** <span id="split"/> is where to split the path to get PATH_INFO at the end of the URI.
|
||||||
- **env** sets an extra environment variable to the given value. Can be specified more than once for multiple environment variables.
|
- **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** enables resolving the `root` directory to its actual value by evaluating a symbolic link, if one exists.
|
- **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** is how long to wait when connecting to the upstream socket. Accepts [duration values](/docs/conventions#durations). Default: no timeout.
|
- **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.
|
||||||
- **read_timeout** is how long to wait when reading from the FastCGI server. Accepts [duration values](/docs/conventions#durations). Default: no timeout.
|
- **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** is how long to wait when sending to 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.
|
||||||
|
|
||||||
|
|
||||||
### Intercepting responses
|
### Intercepting responses
|
||||||
|
@ -261,7 +300,7 @@ transport fastcgi {
|
||||||
The reverse proxy can be configured to intercept responses from the backend. To facilitate this, response matchers can be defined (similar to the syntax for request matchers) and the first matching `handle_response` route will be invoked. When this happens, the response from the backend is not written to the client, and the configured `handle_response` route will be executed instead, and it is up to that route to write a response.
|
The reverse proxy can be configured to intercept responses from the backend. To facilitate this, response matchers can be defined (similar to the syntax for request matchers) and the first matching `handle_response` route will be invoked. When this happens, the response from the backend is not written to the client, and the configured `handle_response` route will be executed instead, and it is up to that route to write a response.
|
||||||
|
|
||||||
- **@name** is the name of a [response matcher](#response-matcher). As long as each response matcher has a unique name, multiple matchers can be defined. A response can be matched on the status code and presence or value of a response header.
|
- **@name** is the name of a [response matcher](#response-matcher). As long as each response matcher has a unique name, multiple matchers can be defined. A response can be matched on the status code and presence or value of a response header.
|
||||||
- **handle_response** defines the route to execute when matched by the given matcher (or, if a matcher is omitted, all responses). The first matching block will be applied. Inside a `handle_response` block, any other [directives](/docs/caddyfile/directives) can be used.
|
- **handle_response** <span id="handle_response"/> defines the route to execute when matched by the given matcher (or, if a matcher is omitted, all responses). The first matching block will be applied. Inside a `handle_response` block, any other [directives](/docs/caddyfile/directives) can be used.
|
||||||
|
|
||||||
Three placeholders will be made available to the `handle_response` routes:
|
Three placeholders will be made available to the `handle_response` routes:
|
||||||
|
|
||||||
|
@ -295,12 +334,14 @@ Reverse proxy all requests to a local backend:
|
||||||
reverse_proxy localhost:9005
|
reverse_proxy localhost:9005
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Load-balance all requests between 3 backends:
|
Load-balance all requests between 3 backends:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
reverse_proxy node1:80 node2:80 node3:80
|
reverse_proxy node1:80 node2:80 node3:80
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Same, but only requests within `/api`, and with header affinity:
|
Same, but only requests within `/api`, and with header affinity:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
@ -309,24 +350,11 @@ reverse_proxy /api/* node1:80 node2:80 node3:80 {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Set the upstream Host header to the address of the upstream (by default, it will retain its original, incoming value):
|
|
||||||
|
|
||||||
```caddy-d
|
|
||||||
reverse_proxy localhost:9000 {
|
|
||||||
header_up Host {http.reverse_proxy.upstream.hostport}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Reverse proxy to an HTTPS endpoint:
|
|
||||||
|
|
||||||
```caddy-d
|
|
||||||
reverse_proxy https://example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
Configure some transport options:
|
Configure some transport options:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
reverse_proxy https://example.com {
|
reverse_proxy localhost:8080 {
|
||||||
transport http {
|
transport http {
|
||||||
dial_timeout 2s
|
dial_timeout 2s
|
||||||
tls_timeout 2s
|
tls_timeout 2s
|
||||||
|
@ -334,6 +362,17 @@ reverse_proxy https://example.com {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Reverse proxy to an HTTPS endpoint:
|
||||||
|
|
||||||
|
```caddy-d
|
||||||
|
reverse_proxy https://example.com {
|
||||||
|
header_up Host {upstream_hostport}
|
||||||
|
header_up X-Forwarded-Host {host}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Replace a path prefix before proxying:
|
Replace a path prefix before proxying:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
@ -343,6 +382,7 @@ handle_path /old-prefix/* {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
X-Accel-Redirect support:
|
X-Accel-Redirect support:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
@ -356,6 +396,7 @@ reverse_proxy localhost:8080 {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Custom error page for errors from upstream:
|
Custom error page for errors from upstream:
|
||||||
|
|
||||||
```caddy-d
|
```caddy-d
|
||||||
|
|
|
@ -67,7 +67,7 @@ And now `file_server` will be chained in before `redir` because the order is tak
|
||||||
|
|
||||||
There are other directives that can wrap HTTP handler directives, but each has its use depending on the behavior you want to convey:
|
There are other directives that can wrap HTTP handler directives, but each has its use depending on the behavior you want to convey:
|
||||||
|
|
||||||
- [`handle`](route) wraps other directives like `route` does, but with two distinctions: 1) handle blocks are mutually exclusive to each other, and 2) directives with a handle are [re-ordered]([directive order](/docs/caddyfile/directives#directive-order) normally.
|
- [`handle`](handle) wraps other directives like `route` does, but with two distinctions: 1) handle blocks are mutually exclusive to each other, and 2) directives with a handle are [re-ordered]([directive order](/docs/caddyfile/directives#directive-order) normally.
|
||||||
- [`handle_path`](handle_path) does the same as `handle`, but it strips a prefix from the request before running its handlers.
|
- [`handle_path`](handle_path) does the same as `handle`, but it strips a prefix from the request before running its handlers.
|
||||||
- [`handle_errors`](handle_errors) is like `handle`, but is only invoked when Caddy encounters an error during request handling.
|
- [`handle_errors`](handle_errors) is like `handle`, but is only invoked when Caddy encounters an error during request handling.
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
title: tls (Caddyfile directive)
|
title: tls (Caddyfile directive)
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
|
||||||
|
addLinksToSubdirectives();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
# tls
|
# tls
|
||||||
|
|
||||||
Configures TLS for the site.
|
Configures TLS for the site.
|
||||||
|
@ -22,6 +29,7 @@ tls [internal|<email>] | [<cert_file> <key_file>] {
|
||||||
load <paths...>
|
load <paths...>
|
||||||
ca <ca_dir_url>
|
ca <ca_dir_url>
|
||||||
ca_root <pem_file>
|
ca_root <pem_file>
|
||||||
|
key_type ed25519|p256|p384|rsa2048|rsa4096
|
||||||
dns <provider_name> [<params...>]
|
dns <provider_name> [<params...>]
|
||||||
resolvers <dns_servers...>
|
resolvers <dns_servers...>
|
||||||
eab <key_id> <mac_key>
|
eab <key_id> <mac_key>
|
||||||
|
@ -40,8 +48,8 @@ tls [internal|<email>] | [<cert_file> <key_file>] {
|
||||||
- **internal** means to use Caddy's internal, locally-trusted CA to produce certificates for this site.
|
- **internal** means to use Caddy's internal, locally-trusted CA to produce certificates for this site.
|
||||||
- **<email>** is the email address to use for the ACME account managing the site's certificates.
|
- **<email>** is the email address to use for the ACME account managing the site's certificates.
|
||||||
- **<cert_file>** and **<key_file>** are the paths to the certificate and private key PEM files. Specifying just one is invalid.
|
- **<cert_file>** and **<key_file>** are the paths to the certificate and private key PEM files. Specifying just one is invalid.
|
||||||
- **protocols** specifies the minimum and maximum protocol versions. Default min: `tls1.2`. Default max: `tls1.3`
|
- **protocols** <span id="protocols"/> specifies the minimum and maximum protocol versions. Default min: `tls1.2`. Default max: `tls1.3`
|
||||||
- **ciphers** specifies the list of cipher suite names in descending preference order. It is recommended to not change these unless you know what you're doing. Note that cipher suites are not customizable for TLS 1.3; and not all TLS 1.2 ciphers are enabled by default. The supported names are (in no particular order here):
|
- **ciphers** <span id="ciphers"/> specifies the list of cipher suite names in descending preference order. It is recommended to not change these unless you know what you're doing. Note that cipher suites are not customizable for TLS 1.3; and not all TLS 1.2 ciphers are enabled by default. The supported names are (in no particular order here):
|
||||||
- TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
- TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||||
- TLS_RSA_WITH_AES_128_CBC_SHA
|
- TLS_RSA_WITH_AES_128_CBC_SHA
|
||||||
- TLS_RSA_WITH_AES_256_CBC_SHA
|
- TLS_RSA_WITH_AES_256_CBC_SHA
|
||||||
|
@ -61,21 +69,22 @@ tls [internal|<email>] | [<cert_file> <key_file>] {
|
||||||
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||||
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
- **curves** specifies the list of EC curves to support. It is recommended to not change these. Supported values are:
|
- **curves** <span id="curves"/> specifies the list of EC curves to support. It is recommended to not change these. Supported values are:
|
||||||
- x25519
|
- x25519
|
||||||
- secp256r1
|
- secp256r1
|
||||||
- secp384r1
|
- secp384r1
|
||||||
- secp521r1
|
- secp521r1
|
||||||
- **alpn** is the list of values to advertise in the ALPN extension of the TLS handshake.
|
- **alpn** <span id="alpn"/> is the list of values to advertise in the ALPN extension of the TLS handshake.
|
||||||
- **load** specifies a list of folders from which to load PEM files that are certificate+key bundles.
|
- **load** <span id="load"/> specifies a list of folders from which to load PEM files that are certificate+key bundles.
|
||||||
- **ca** changes the ACME CA endpoint. This is most often used to set [Let's Encrypt's staging endpoint](https://letsencrypt.org/docs/staging-environment/) when testing, or an internal ACME server. (To change this value for the whole Caddyfile, use the `acme_ca` [global option](/docs/caddyfile/options) instead.)
|
- **ca** <span id="ca"/> changes the ACME CA endpoint. This is most often used to set [Let's Encrypt's staging endpoint](https://letsencrypt.org/docs/staging-environment/) when testing, or an internal ACME server. (To change this value for the whole Caddyfile, use the `acme_ca` [global option](/docs/caddyfile/options) instead.)
|
||||||
- **ca_root** specifies a PEM file that contains a trusted root certificate for the ACME CA endpoint, if not in the system trust store.
|
- **ca_root** <span id="ca_root"/> specifies a PEM file that contains a trusted root certificate for the ACME CA endpoint, if not in the system trust store.
|
||||||
- **dns** enables the [DNS challenge](/docs/automatic-https#dns-challenge) using the specified provider plugin, which must be plugged in from one of the [caddy-dns](https://github.com/caddy-dns) repositories. Each provider plugin may have their own syntax following their name; refer to their docs for details. Maintaining support for each DNS provider 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)
|
- **key_type** <span id="key_type"/> is the type of key to use when generating CSRs. Only set this if you have a specific requirement.
|
||||||
- **resolvers** customizes the DNS resolvers used when performing the DNS challenge; these take precedence over system resolvers or any default ones. If set here, the resolvers will propagate to all configured certificate issuers.
|
- **dns** <span id="dns"/> enables the [DNS challenge](/docs/automatic-https#dns-challenge) using the specified provider plugin, which must be plugged in from one of the [caddy-dns](https://github.com/caddy-dns) repositories. Each provider plugin may have their own syntax following their name; refer to their docs for details. Maintaining support for each DNS provider 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)
|
||||||
- **eab** configures ACME external account binding (EAB) for this site, using the key ID and MAC key provided by your CA.
|
- **resolvers** <span id="resolvers"/> customizes the DNS resolvers used when performing the DNS challenge; these take precedence over system resolvers or any default ones. If set here, the resolvers will propagate to all configured certificate issuers.
|
||||||
- **on_demand** enables [on-demand TLS](/docs/automatic-https#on-demand-tls) for the hostnames given in the site block's address(es). **Security warning:** Doing so in production is insecure unless you also configure the [`on_demand_tls` global option](https://caddyserver.com/docs/caddyfile/options#on-demand-tls) to mitigate abuse.
|
- **eab** <span id="eab"/> configures ACME external account binding (EAB) for this site, using the key ID and MAC key provided by your CA.
|
||||||
- **client_auth** enables and configures TLS client authentication:
|
- **on_demand** <span id="on_demand"/> enables [on-demand TLS](/docs/automatic-https#on-demand-tls) for the hostnames given in the site block's address(es). **Security warning:** Doing so in production is insecure unless you also configure the [`on_demand_tls` global option](https://caddyserver.com/docs/caddyfile/options#on-demand-tls) to mitigate abuse.
|
||||||
- **mode** is the mode for authenticating the client. Allowed values are:
|
- **client_auth** <span id="client_auth"/> enables and configures TLS client authentication:
|
||||||
|
- **mode** <span id="mode"/> is the mode for authenticating the client. Allowed values are:
|
||||||
|
|
||||||
| Mode | Description |
|
| Mode | Description |
|
||||||
|--------------------|------------------------------------------------------------------------------------------|
|
|--------------------|------------------------------------------------------------------------------------------|
|
||||||
|
@ -86,14 +95,14 @@ tls [internal|<email>] | [<cert_file> <key_file>] {
|
||||||
|
|
||||||
Default: `require_and_verify` if any `trusted_ca_cert` or `trusted_leaf_cert` are provided; otherwise, `require`.
|
Default: `require_and_verify` if any `trusted_ca_cert` or `trusted_leaf_cert` are provided; otherwise, `require`.
|
||||||
|
|
||||||
- **trusted_ca_cert** is a base64 DER-encoded CA certificate against which to validate client certificates.
|
- **trusted_ca_cert** <span id="trusted_ca_cert"/> is a base64 DER-encoded CA certificate against which to validate client certificates.
|
||||||
- **trusted_ca_cert_file** is a path to a PEM CA certificate file against which to validate client certificates.
|
- **trusted_ca_cert_file** <span id="trusted_ca_cert_file"/> is a path to a PEM CA certificate file against which to validate client certificates.
|
||||||
- **trusted_leaf_cert** is a base64 DER-encoded client leaf certificate to accept.
|
- **trusted_leaf_cert** <span id="trusted_leaf_cert"/> is a base64 DER-encoded client leaf certificate to accept.
|
||||||
- **trusted_leaf_cert_file** is a path to a PEM CA certificate file against which to validate client certificates.
|
- **trusted_leaf_cert_file** <span id="trusted_leaf_cert_file"/> is a path to a PEM CA certificate file against which to validate client certificates.
|
||||||
|
|
||||||
Multiple `trusted_*` directives may be used to specify multiple CA or leaf certificates. Client certificates which are not listed as one of the leaf certificates or signed by any of the specified CAs will be rejected according to the **mode**.
|
Multiple `trusted_*` directives may be used to specify multiple CA or leaf certificates. Client certificates which are not listed as one of the leaf certificates or signed by any of the specified CAs will be rejected according to the **mode**.
|
||||||
|
|
||||||
- **issuer** configures a custom certificate issuer, or a source from which to obtain certificates. Which issuer is used and the options that follow in this segment depend on the issuer modules that are available (see below for the standard issuers; plugins may add others). Some of the other subdirectives such as `ca` and `dns` are actually shortcuts for configuring the `acme` issuer (and this subdirective was added later), so specifying this directive and some of the others is confusing and thus prohibited. This subdirective can be specified multiple times to configure multiple, redundant issuers; if one fails to issue a cert, the next one will be tried.
|
- **issuer** <span id="issuer"/> configures a custom certificate issuer, or a source from which to obtain certificates. Which issuer is used and the options that follow in this segment depend on the issuer modules that are available (see below for the standard issuers; plugins may add others). Some of the other subdirectives such as `ca` and `dns` are actually shortcuts for configuring the `acme` issuer (and this subdirective was added later), so specifying this directive and some of the others is confusing and thus prohibited. This subdirective can be specified multiple times to configure multiple, redundant issuers; if one fails to issue a cert, the next one will be tried.
|
||||||
|
|
||||||
### Issuers
|
### Issuers
|
||||||
|
|
||||||
|
@ -109,7 +118,6 @@ Obtains certificates using the ACME protocol.
|
||||||
test_dir <test_directory_url>
|
test_dir <test_directory_url>
|
||||||
email <email>
|
email <email>
|
||||||
timeout <duration>
|
timeout <duration>
|
||||||
key_type ed25519|p256|p384|rsa2048|rsa4096
|
|
||||||
disable_http_challenge
|
disable_http_challenge
|
||||||
disable_tlsalpn_challenge
|
disable_tlsalpn_challenge
|
||||||
alt_http_port <port>
|
alt_http_port <port>
|
||||||
|
@ -126,24 +134,23 @@ Obtains certificates using the ACME protocol.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- **dir** is the URL to the ACME CA's directory. Default: `https://acme-v02.api.letsencrypt.org/directory`
|
- **dir** <span id="dir"/> is the URL to the ACME CA's directory. Default: `https://acme-v02.api.letsencrypt.org/directory`
|
||||||
- **test_dir** is an optional fallback directory to use when retrying challenges; if all challenges fail, this endpoint will be used during retries; useful if a CA has a staging endpoint where you want to avoid rate limits on their production endpoint. Default: `https://acme-staging-v02.api.letsencrypt.org/directory`
|
- **test_dir** <span id="test_dir"/> is an optional fallback directory to use when retrying challenges; if all challenges fail, this endpoint will be used during retries; useful if a CA has a staging endpoint where you want to avoid rate limits on their production endpoint. Default: `https://acme-staging-v02.api.letsencrypt.org/directory`
|
||||||
- **email** is the ACME account contact email address.
|
- **email** <span id="email"/> is the ACME account contact email address.
|
||||||
- **timeout** is how long to wait before timing out an ACME operation.
|
- **timeout** <span id="timeout"/> is a [duration value](/docs/conventions#durations) that sets how long to wait before timing out an ACME operation.
|
||||||
- **key_type** is the type of key to use when generating CSRs. Only set this if you have a specific requirement.
|
- **disable_http_challenge** <span id="disable_http_challenge"/> will disable the HTTP challenge.
|
||||||
- **disable_http_challenge** will disable the HTTP challenge.
|
- **disable_tlsalpn_challenge** <span id="disable_tlsalpn_challenge"/> will disable the TLS-ALPN challenge.
|
||||||
- **disable_tlsalpn_challenge** will disable the TLS-ALPN challenge.
|
- **alt_http_port** <span id="alt_http_port"/> is an alternate port on which to serve the HTTP challenge; it has to happen on port 80 so you must forward packets to this alternate port.
|
||||||
- **alt_http_port** is an alternate port on which to serve the HTTP challenge; it has to happen on port 80 so you must forward packets to this alternate port.
|
- **alt_tlsalpn_port** <span id="alt_tlsalpn_port"/> is an alternate port on which to serve the TLS-ALPN challenge; it has to happen on port 443 so you must forward packets to this alternate port.
|
||||||
- **alt_tlsalpn_port** is an alternate port on which to serve the TLS-ALPN challenge; it has to happen on port 443 so you must forward packets to this alternate port.
|
- **eab** <span id="eab"/> specifies an External Account Binding which may be required with some ACME CAs.
|
||||||
- **eab** specifies an External Account Binding which may be required with some ACME CAs.
|
- **trusted_roots** <span id="trusted_roots"/> is one or more root certificates (as PEM filenames) to trust when connecting to the ACME CA server.
|
||||||
- **trusted_roots** is one or more root certificates (as PEM filenames) to trust when connecting to the ACME CA server.
|
- **dns** <span id="dns"/> configures the DNS challenge.
|
||||||
- **dns** configures the DNS challenge.
|
- **propagation_timeout** <span id="propagation_timeout"/> is a [duration value](/docs/conventions#durations) that sets how long to wait for DNS TXT records to propagate when using the DNS challenge. Default 2 minutes.
|
||||||
- **propagation_timeout** is a [duration value](/docs/conventions#durations) that sets how long to wait for DNS TXT records to propagate. Default 2 minutes.
|
- **resolvers** <span id="resolvers"/> customizes the DNS resolvers used when performing the DNS challenge; these take precedence over system resolvers or any default ones.
|
||||||
- **resolvers** customizes the DNS resolvers used when performing the DNS challenge; these take precedence over system resolvers or any default ones.
|
- **preferred_chains** <span id="preferred_chains"/> specifies which certificate chains Caddy should prefer; useful if your CA provides multiple chains. Use one of the following options:
|
||||||
- **preferred_chains** specifies which certificate chains Caddy should prefer; useful if your CA provides multiple chains. Use one of the following options:
|
- **smallest** <span id="smallest"/> will tell Caddy to prefer chains with the fewest amount of bytes.
|
||||||
- **smallest** will tell Caddy to prefer chains with the fewest amount of bytes.
|
- **root_common_name** <span id="root_common_name"/> is a list of one or more common names; Caddy will choose the first chain that has a root that matches with at least one of the specified common names.
|
||||||
- **root_common_name** is a list of one or more common names; Caddy will choose the first chain that has a root that matches with at least one of the specified common names.
|
- **any_common_name** <span id="any_common_name"/> is a list of one or more common names; Caddy will choose the first chain that has an issuer that matches with at least one of the specified common names.
|
||||||
- **any_common_name** is a list of one or more common names; Caddy will choose the first chain that has an issuer that matches with at least one of the specified common names.
|
|
||||||
|
|
||||||
|
|
||||||
#### zerossl
|
#### zerossl
|
||||||
|
|
|
@ -2,6 +2,31 @@
|
||||||
title: Request matchers (Caddyfile)
|
title: Request matchers (Caddyfile)
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
// We'll add links on the matchers in the code blocks
|
||||||
|
// to their associated anchor tags.
|
||||||
|
let headers = $('article h3').map((i, el) => el.id.replace(/-/g, "_")).toArray();
|
||||||
|
$('pre.chroma .k')
|
||||||
|
.filter((k, item) => headers.includes(item.innerText))
|
||||||
|
.map(function(k, item) {
|
||||||
|
let text = item.innerText.replace(/</g,'<').replace(/>/g,'>');
|
||||||
|
let url = '#' + item.innerText.replace(/_/g, "-");
|
||||||
|
$(item).html('<a href="' + url + '" style="color: inherit;" title="' + text + '">' + text + '</a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Link matcher tokens based on their contents to the syntax section
|
||||||
|
$('pre.chroma .nd')
|
||||||
|
.map(function(k, item) {
|
||||||
|
let text = item.innerText.replace(/</g,'<').replace(/>/g,'>');
|
||||||
|
let anchor = "named-matchers"
|
||||||
|
if (text == "*") anchor = "wildcard-matchers"
|
||||||
|
if (text.startsWith('/')) anchor = "path-matchers"
|
||||||
|
$(item).html('<a href="#' + anchor + '" style="color: inherit;" title="Matcher token">' + text + '</a>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
# Request Matchers
|
# Request Matchers
|
||||||
|
|
||||||
**Request matchers** can be used to filter (or classify) requests by specific criteria.
|
**Request matchers** can be used to filter (or classify) requests by specific criteria.
|
||||||
|
|
|
@ -2,6 +2,26 @@
|
||||||
title: Global options (Caddyfile)
|
title: Global options (Caddyfile)
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
// We'll add links on the options in the code block at the top
|
||||||
|
// to their associated anchor tags.
|
||||||
|
let headers = $('article h5').map((i, el) => el.id.replace(/-/g, "_")).toArray();
|
||||||
|
$('pre.chroma .k')
|
||||||
|
.filter((k, item) => headers.includes(item.innerText))
|
||||||
|
.map(function(k, item) {
|
||||||
|
let text = item.innerText.replace(/</g,'<').replace(/>/g,'>');
|
||||||
|
let url = '#' + item.innerText.replace(/_/g, "-");
|
||||||
|
$(item).html('<a href="' + url + '" style="color: inherit;" title="' + text + '">' + text + '</a>');
|
||||||
|
});
|
||||||
|
$('pre.chroma .k:contains("servers")')
|
||||||
|
.map(function(k, item) {
|
||||||
|
let text = item.innerText.replace(/</g,'<').replace(/>/g,'>');
|
||||||
|
$(item).html('<a href="#server-options" style="color: inherit;" title="Server Options">' + text + '</a>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
# Global options
|
# Global options
|
||||||
|
|
||||||
The Caddyfile has a way for you to specify options that apply globally. Some options act as default values, while others customize the behavior of the Caddyfile [adapter](/docs/config-adapters).
|
The Caddyfile has a way for you to specify options that apply globally. Some options act as default values, while others customize the behavior of the Caddyfile [adapter](/docs/config-adapters).
|
||||||
|
@ -116,7 +136,7 @@ Customizes the [admin API endpoint](/docs/api). If `off`, then the admin endpoin
|
||||||
- **enforce_origin** enables enforcement of the Origin header. (This is different from enforcing origins generally, which is always done.)
|
- **enforce_origin** enables enforcement of the Origin header. (This is different from enforcing origins generally, which is always done.)
|
||||||
|
|
||||||
##### `log`
|
##### `log`
|
||||||
Customizes the named logger. The name can be passed to indicate a specific logger to customize the behavior for. If no name is specified, the behavior of the default logger is modified. This option can be specified multiple times to configure different loggers. You can read more about the default logger and other logging behaviors in the [logging documentation](/docs/logging/).
|
Customizes the named logger. The name can be passed to indicate a specific logger to customize the behavior for. If no name is specified, the behavior of the default logger is modified. This option can be specified multiple times to configure different loggers. You can read more about the default logger and other logging behaviors in the [logging documentation](/docs/logging).
|
||||||
|
|
||||||
- **output** configures where to write the logs. See the [log directive](/docs/caddyfile/directives/log#output-modules) documentation for more information, which has the same structure.
|
- **output** configures where to write the logs. See the [log directive](/docs/caddyfile/directives/log#output-modules) documentation for more information, which has the same structure.
|
||||||
- **format** describes how to encode, or format, the logs. See the [log directive](/docs/caddyfile/directives/log#format-modules) documentation for more information, which has the same structure.
|
- **format** describes how to encode, or format, the logs. See the [log directive](/docs/caddyfile/directives/log#format-modules) documentation for more information, which has the same structure.
|
||||||
|
|
|
@ -23,6 +23,9 @@ The ellipses `...` indicates a continuation, i.e. one or more parameters.
|
||||||
- **[caddy adapt](#caddy-adapt)**
|
- **[caddy adapt](#caddy-adapt)**
|
||||||
Adapts a config document to native JSON
|
Adapts a config document to native JSON
|
||||||
|
|
||||||
|
- **[caddy build-info](#caddy-build-info)**
|
||||||
|
Prints build information
|
||||||
|
|
||||||
- **[caddy environ](#caddy-environ)**
|
- **[caddy environ](#caddy-environ)**
|
||||||
Prints the environment
|
Prints the environment
|
||||||
|
|
||||||
|
@ -62,6 +65,15 @@ The ellipses `...` indicates a continuation, i.e. one or more parameters.
|
||||||
- **[caddy untrust](#caddy-untrust)**
|
- **[caddy untrust](#caddy-untrust)**
|
||||||
Untrusts a certificate from local trust store(s)
|
Untrusts a certificate from local trust store(s)
|
||||||
|
|
||||||
|
- **[caddy upgrade](#caddy-upgrade)**
|
||||||
|
Upgrades Caddy to the latest release
|
||||||
|
|
||||||
|
- **[caddy add-package](#caddy-add-package)**
|
||||||
|
Upgrades Caddy to the latest release, with additional plugins added
|
||||||
|
|
||||||
|
- **[caddy remove-package](#caddy-remove-package)**
|
||||||
|
Upgrades Caddy to the latest release, with some plugins removed
|
||||||
|
|
||||||
- **[caddy validate](#caddy-validate)**
|
- **[caddy validate](#caddy-validate)**
|
||||||
Tests whether a config file is valid
|
Tests whether a config file is valid
|
||||||
|
|
||||||
|
@ -167,8 +179,7 @@ This command disables the admin API, making it easier to run multiple instances
|
||||||
|
|
||||||
### `caddy fmt`
|
### `caddy fmt`
|
||||||
|
|
||||||
<pre><code class="cmd bash">caddy fmt [<path>]
|
<pre><code class="cmd bash">caddy fmt [--overwrite] [<path>]</code></pre>
|
||||||
[--overwrite]</code></pre>
|
|
||||||
|
|
||||||
Formats or prettifies a Caddyfile, then exits. The result is printed to stdout unless `--overwrite` is used.
|
Formats or prettifies a Caddyfile, then exits. The result is printed to stdout unless `--overwrite` is used.
|
||||||
|
|
||||||
|
@ -305,7 +316,7 @@ Same as [`caddy run`](#caddy-run), but in the background. This command only bloc
|
||||||
|
|
||||||
Note: the flag `--config` doesn't support `-` to read the config from stdin.
|
Note: the flag `--config` doesn't support `-` to read the config from stdin.
|
||||||
|
|
||||||
Use of this command is discouraged with system services or on Windows. On Windows, the child process will remain attached to the terminal, so closing the window will forcefully stop Caddy, which is not obvious.
|
Use of this command is discouraged with system services or on Windows. On Windows, the child process will remain attached to the terminal, so closing the window will forcefully stop Caddy, which is not obvious. Consider running Caddy [as a service](/docs/running) instead.
|
||||||
|
|
||||||
Once started, you can use [`caddy stop`](#caddy-stop) or [the /stop API endpoint](/docs/api#post-stop) to exit the background process.
|
Once started, you can use [`caddy stop`](#caddy-stop) or [the /stop API endpoint](/docs/api#post-stop) to exit the background process.
|
||||||
|
|
||||||
|
@ -362,6 +373,27 @@ The upgrade process is fault tolerant; the current binary is backed up first and
|
||||||
This command may require elevated privileges if your user does not have permission to write to the executable file.
|
This command may require elevated privileges if your user does not have permission to write to the executable file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### `caddy add-package`
|
||||||
|
|
||||||
|
<pre><code class="cmd bash">caddy add-package <packages...></code></pre>
|
||||||
|
|
||||||
|
Similarly to `caddy upgrade`, replaces the current Caddy binary with the latest version with the same modules installed, _plus_ the packages listed as arguments included in the new binary. Find the list of packages you can install from [our download page](https://caddyserver.com/download). Each argument should be the full package name.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
<pre><code class="cmd bash">caddy add-package github.com/caddy-dns/cloudflare</code></pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### `caddy remove-package`
|
||||||
|
|
||||||
|
<pre><code class="cmd bash">caddy remove-package <packages...></code></pre>
|
||||||
|
|
||||||
|
Similarly to `caddy upgrade`, replaces the current Caddy binary with the latest version with the same modules installed, but _without_ the packages listed as arguments, if they existed in the current binary. Run `caddy list-modules --packages` to see the list of package names of non-standard modules included in the current binary.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### `caddy validate`
|
### `caddy validate`
|
||||||
|
|
||||||
<pre><code class="cmd bash">caddy validate
|
<pre><code class="cmd bash">caddy validate
|
||||||
|
|
|
@ -69,8 +69,10 @@ Placeholder | Description
|
||||||
`{system.slash}` | The system's filepath separator
|
`{system.slash}` | The system's filepath separator
|
||||||
`{system.os}` | The system's OS
|
`{system.os}` | The system's OS
|
||||||
`{system.arch}` | The system's architecture
|
`{system.arch}` | The system's architecture
|
||||||
`{time.now}` | The current timestamp
|
`{time.now}` | The current time as a Go Time struct
|
||||||
`{time.now.common_log}` | The current timestamp in Common Log Format
|
`{time.now.unix}` | The current time as a unix timestamp in seconds
|
||||||
|
`{time.now.unix_ms}` | The current time as a unix timestamp in milliseconds
|
||||||
|
`{time.now.common_log}` | The current time in Common Log Format
|
||||||
`{time.now.year}` | The current year in YYYY format
|
`{time.now.year}` | The current year in YYYY format
|
||||||
|
|
||||||
Not all config fields support placeholders, but most do where you would expect it.
|
Not all config fields support placeholders, but most do where you would expect it.
|
||||||
|
|
|
@ -14,7 +14,6 @@ This page describes various methods for installing Caddy on your system.
|
||||||
- [Arch Linux, Manjaro, Parabola](#arch-linux-manjaro-parabola)
|
- [Arch Linux, Manjaro, Parabola](#arch-linux-manjaro-parabola)
|
||||||
- [Docker](#docker)
|
- [Docker](#docker)
|
||||||
- [DigitalOcean](#digitalocean)
|
- [DigitalOcean](#digitalocean)
|
||||||
- [Linux service](#linux-service)
|
|
||||||
|
|
||||||
<aside class="tip">
|
<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 <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>.
|
||||||
|
@ -27,11 +26,13 @@ This page describes various methods for installing Caddy on your system.
|
||||||
- [Webi](#webi)
|
- [Webi](#webi)
|
||||||
- [Chocolatey](#chocolatey)
|
- [Chocolatey](#chocolatey)
|
||||||
- [Ansible](#ansible)
|
- [Ansible](#ansible)
|
||||||
|
- [Scoop](#scoop)
|
||||||
|
- [Termux](#termux)
|
||||||
|
|
||||||
|
|
||||||
## Static binaries
|
## Static binaries
|
||||||
|
|
||||||
Simply downloading a Caddy binary does not <a href="#linux-service">install it as a service</a>, but can be useful in dev or when upgrading an existing installation.
|
Simply downloading a Caddy binary does not [install it as a service](/docs/running#manual-installation), but can be useful in dev or when upgrading an existing installation.
|
||||||
|
|
||||||
- [**View releases on GitHub**](https://github.com/caddyserver/caddy/releases) (expand "Assets")
|
- [**View releases on GitHub**](https://github.com/caddyserver/caddy/releases) (expand "Assets")
|
||||||
- [**Use our download page**](/download)
|
- [**Use our download page**](/download)
|
||||||
|
@ -39,14 +40,12 @@ Simply downloading a Caddy binary does not <a href="#linux-service">install it a
|
||||||
|
|
||||||
## Debian, Ubuntu, Raspbian
|
## Debian, Ubuntu, Raspbian
|
||||||
|
|
||||||
Installing this package automatically starts and runs Caddy for you as a systemd service named `caddy` using our official [`caddy.service`](https://github.com/caddyserver/dist/blob/master/init/caddy.service) unit file.
|
Installing this package automatically starts and runs Caddy as a [systemd service](/docs/running#linux-service) named `caddy`, and also comes with a `caddy-api` service which is _not_ enabled by default, should you need it.
|
||||||
|
|
||||||
This package also comes with a `caddy-api` systemd service using our official [`caddy-api.service`](https://github.com/caddyserver/dist/blob/master/init/caddy-api.service) unit file, which is disabled by default. If you plan to configure Caddy solely through its [API](/docs/api), then you should disable the `caddy` service, and enable the `caddy-api` service.
|
|
||||||
|
|
||||||
Stable releases:
|
Stable releases:
|
||||||
|
|
||||||
<pre><code class="cmd"><span class="bash">sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https</span>
|
<pre><code class="cmd"><span class="bash">sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https</span>
|
||||||
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add -</span>
|
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo tee /etc/apt/trusted.gpg.d/caddy-stable.asc</span>
|
||||||
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list</span>
|
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list</span>
|
||||||
<span class="bash">sudo apt update</span>
|
<span class="bash">sudo apt update</span>
|
||||||
<span class="bash">sudo apt install caddy</span></code></pre>
|
<span class="bash">sudo apt install caddy</span></code></pre>
|
||||||
|
@ -54,17 +53,20 @@ Stable releases:
|
||||||
Testing releases (includes betas and release candidates):
|
Testing releases (includes betas and release candidates):
|
||||||
|
|
||||||
<pre><code class="cmd"><span class="bash">sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https</span>
|
<pre><code class="cmd"><span class="bash">sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https</span>
|
||||||
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/gpg.key' | sudo apt-key add -</span>
|
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/gpg.key' | sudo tee /etc/apt/trusted.gpg.d/caddy-testing.asc</span>
|
||||||
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-testing.list</span>
|
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-testing.list</span>
|
||||||
<span class="bash">sudo apt update</span>
|
<span class="bash">sudo apt update</span>
|
||||||
<span class="bash">sudo apt install caddy</span></code></pre>
|
<span class="bash">sudo apt install caddy</span></code></pre>
|
||||||
|
|
||||||
[**View the Cloudsmith repos**](https://cloudsmith.io/~caddy/repos/)
|
[**View the Cloudsmith repos**](https://cloudsmith.io/~caddy/repos/)
|
||||||
|
|
||||||
If you wish to use the packaged support files (systemd services, bash completion and default configuration) with a custom Caddy build, instructions can be found [here](https://caddyserver.com/docs/build#package-support-files-for-custom-builds-for-debian-ubuntu-raspbian).
|
If you wish to use the packaged support files (systemd services, bash completion and default configuration) with a custom Caddy build, instructions can be [found here](https://caddyserver.com/docs/build#package-support-files-for-custom-builds-for-debianubunturaspbian).
|
||||||
|
|
||||||
|
|
||||||
## Fedora, RedHat, CentOS
|
## Fedora, RedHat, CentOS
|
||||||
|
|
||||||
|
This package comes with both of Caddy's [systemd service](/docs/running#linux-service) unit files, but does not enable them by default.
|
||||||
|
|
||||||
Fedora or RHEL/CentOS 8:
|
Fedora or RHEL/CentOS 8:
|
||||||
|
|
||||||
<pre><code class="cmd"><span class="bash">dnf install 'dnf-command(copr)'</span>
|
<pre><code class="cmd"><span class="bash">dnf install 'dnf-command(copr)'</span>
|
||||||
|
@ -79,8 +81,11 @@ RHEL/CentOS 7:
|
||||||
|
|
||||||
[**View the Caddy COPR**](https://copr.fedorainfracloud.org/coprs/g/caddy/caddy/)
|
[**View the Caddy COPR**](https://copr.fedorainfracloud.org/coprs/g/caddy/caddy/)
|
||||||
|
|
||||||
|
|
||||||
## Arch Linux, Manjaro, Parabola
|
## Arch Linux, Manjaro, Parabola
|
||||||
|
|
||||||
|
This package comes with both of Caddy's [systemd service](/docs/running#linux-service) unit files, but does not enable them by default.
|
||||||
|
|
||||||
<pre><code class="cmd"><span class="bash">pacman -Syu caddy</span></code></pre>
|
<pre><code class="cmd"><span class="bash">pacman -Syu caddy</span></code></pre>
|
||||||
|
|
||||||
[**View Caddy in the Arch Linux repositories**](https://archlinux.org/packages/community/x86_64/caddy/)
|
[**View Caddy in the Arch Linux repositories**](https://archlinux.org/packages/community/x86_64/caddy/)
|
||||||
|
@ -92,72 +97,12 @@ RHEL/CentOS 7:
|
||||||
|
|
||||||
[**View on Docker Hub**](https://hub.docker.com/_/caddy)
|
[**View on Docker Hub**](https://hub.docker.com/_/caddy)
|
||||||
|
|
||||||
|
|
||||||
## DigitalOcean
|
## DigitalOcean
|
||||||
|
|
||||||
[**Deploy a Caddy droplet on DigitalOcean**](https://marketplace.digitalocean.com/apps/caddy)
|
[**Deploy a Caddy droplet on DigitalOcean**](https://marketplace.digitalocean.com/apps/caddy)
|
||||||
|
|
||||||
## Linux service
|
The droplet is preconfigured to run Caddy as a [systemd service](/docs/running#linux-service) via being installed with the [`apt` repo](#debian-ubuntu-raspbian).
|
||||||
|
|
||||||
Manually install Caddy as a service on Linux with these instructions.
|
|
||||||
|
|
||||||
**Requirements:**
|
|
||||||
|
|
||||||
- `caddy` binary that you [downloaded](/download) or [built from source](/docs/build)
|
|
||||||
- `systemctl --version` 232 or newer
|
|
||||||
- `sudo` privileges
|
|
||||||
|
|
||||||
Move the caddy binary into your `$PATH`, for example:
|
|
||||||
<pre><code class="cmd bash">sudo mv caddy /usr/bin/</code></pre>
|
|
||||||
|
|
||||||
Test that it worked:
|
|
||||||
<pre><code class="cmd bash">caddy version</code></pre>
|
|
||||||
|
|
||||||
Create a group named `caddy`:
|
|
||||||
<pre><code class="cmd bash">sudo groupadd --system caddy</code></pre>
|
|
||||||
|
|
||||||
Create a user named `caddy`, with a writeable home folder:
|
|
||||||
<pre><code class="cmd bash">sudo useradd --system \
|
|
||||||
--gid caddy \
|
|
||||||
--create-home \
|
|
||||||
--home-dir /var/lib/caddy \
|
|
||||||
--shell /usr/sbin/nologin \
|
|
||||||
--comment "Caddy web server" \
|
|
||||||
caddy</code></pre>
|
|
||||||
|
|
||||||
If using a config file, be sure it is readable by the `caddy` user you just created.
|
|
||||||
|
|
||||||
Next, [choose a systemd service file](https://github.com/caddyserver/dist/blob/master/init) based on your use case:
|
|
||||||
|
|
||||||
- [**`caddy.service`**](https://github.com/caddyserver/dist/blob/master/init/caddy.service) if you configure Caddy with a file.
|
|
||||||
- [**`caddy-api.service`**](https://github.com/caddyserver/dist/blob/master/init/caddy-api.service) if you configure Caddy solely through its API.
|
|
||||||
|
|
||||||
They are very similar but have minor differences in the ExecStart and ExecReload commands to accommodate your workflow. Customize the file accordingly.
|
|
||||||
|
|
||||||
**Double-check the `ExecStart` and `ExecReload` directives.** Make sure the binary's location and command line arguments are correct for your installation! For example: if using a config file, change your `--config` path if it is different from our example.
|
|
||||||
|
|
||||||
The usual place to save the service file is: `/etc/systemd/system/caddy.service`
|
|
||||||
|
|
||||||
After saving your service file, you can start the service for the first time with the usual systemctl dance:
|
|
||||||
|
|
||||||
<pre><code class="cmd"><span class="bash">sudo systemctl daemon-reload</span>
|
|
||||||
<span class="bash">sudo systemctl enable caddy</span>
|
|
||||||
<span class="bash">sudo systemctl start caddy</span></code></pre>
|
|
||||||
|
|
||||||
Verify that it is running:
|
|
||||||
<pre><code class="cmd bash">systemctl status caddy</code></pre>
|
|
||||||
|
|
||||||
When running with our official service file, Caddy's output will be redirected to `journalctl`:
|
|
||||||
<pre><code class="cmd bash">journalctl -u caddy --no-pager | less</code></pre>
|
|
||||||
|
|
||||||
If using a config file, you can gracefully apply any changes:
|
|
||||||
<pre><code class="cmd bash">sudo systemctl reload caddy</code></pre>
|
|
||||||
|
|
||||||
You can stop the service with:
|
|
||||||
<pre><code class="cmd bash">sudo systemctl stop caddy</code></pre>
|
|
||||||
|
|
||||||
<aside class="advice">
|
|
||||||
Do not stop the service to change Caddy's configuration. Stopping the server will incur downtime. Use the reload command instead.
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
|
|
||||||
## Homebrew
|
## Homebrew
|
||||||
|
@ -211,3 +156,13 @@ _Note: This is a community-maintained installation method._
|
||||||
<pre><code class="cmd">scoop install caddy</code></pre>
|
<pre><code class="cmd">scoop install caddy</code></pre>
|
||||||
|
|
||||||
[**View the Scoop manifest**](https://github.com/ScoopInstaller/Main/blob/master/bucket/caddy.json)
|
[**View the Scoop manifest**](https://github.com/ScoopInstaller/Main/blob/master/bucket/caddy.json)
|
||||||
|
|
||||||
|
|
||||||
|
## Termux
|
||||||
|
|
||||||
|
_Note: This is a community-maintained installation method._
|
||||||
|
|
||||||
|
<pre><code class="cmd">pkg install caddy</code></pre>
|
||||||
|
|
||||||
|
[**View the Termux build.sh file**](https://github.com/termux/termux-packages/blob/master/packages/caddy/build.sh)
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,8 @@ Now compare an equivalent structured log message from Caddy, encoded as JSON and
|
||||||
"server_name": "example.com"
|
"server_name": "example.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"latency": 0.000014711,
|
"user_id": "",
|
||||||
|
"duration": 0.000014711,
|
||||||
"size": 2326,
|
"size": 2326,
|
||||||
"status": 200,
|
"status": 200,
|
||||||
"resp_headers": {
|
"resp_headers": {
|
||||||
|
|
|
@ -85,7 +85,7 @@ automatically by the Prometheus Go Client. They are prefixed with `go_*` and
|
||||||
Note that the `process_*` metrics are only collected on Linux and Windows.
|
Note that the `process_*` metrics are only collected on Linux and Windows.
|
||||||
|
|
||||||
See the documentation for the [Go Collector](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#NewGoCollector),
|
See the documentation for the [Go Collector](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#NewGoCollector),
|
||||||
[Process Colletor](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#NewProcessCollector),
|
[Process Collector](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#NewProcessCollector),
|
||||||
and [BuildInfo Collector](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#NewBuildInfoCollector).
|
and [BuildInfo Collector](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#NewBuildInfoCollector).
|
||||||
|
|
||||||
### Admin API metrics
|
### Admin API metrics
|
||||||
|
|
214
src/docs/markdown/running.md
Normal file
214
src/docs/markdown/running.md
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
---
|
||||||
|
title: Keep Caddy Running
|
||||||
|
---
|
||||||
|
|
||||||
|
# Keep Caddy Running
|
||||||
|
|
||||||
|
While Caddy can be run successfully by directly using its [Command Line Interface](/docs/command-line), there are numerous advantages to using a service manager to keep it running, such as ensuring it starts back up when the system boots, and to capture stdout/stderr logging.
|
||||||
|
|
||||||
|
|
||||||
|
- [Linux Service](#linux-service)
|
||||||
|
- [Unit Files](#unit-files)
|
||||||
|
- [Using the Service](#using-the-service)
|
||||||
|
- [Manual Installation](#manual-installation)
|
||||||
|
- [Overrides](#overrides)
|
||||||
|
- [Windows Service](#windows-service)
|
||||||
|
- [Docker Compose](#docker-compose)
|
||||||
|
|
||||||
|
|
||||||
|
## Linux Service
|
||||||
|
|
||||||
|
The recommended way to run Caddy on Linux distributions with systemd is with our official systemd unit files.
|
||||||
|
|
||||||
|
|
||||||
|
### Unit Files
|
||||||
|
|
||||||
|
We provide two different systemd unit files that you can choose between, depending on your usecase:
|
||||||
|
|
||||||
|
- [**`caddy.service`**](https://github.com/caddyserver/dist/blob/master/init/caddy.service) if you configure Caddy with a [Caddyfile](/docs/caddyfile). If you prefer to use a JSON config file, you may [override](#overrides) the `ExecStart` and `ExecReload` commands.
|
||||||
|
|
||||||
|
- [**`caddy-api.service`**](https://github.com/caddyserver/dist/blob/master/init/caddy-api.service) if you configure Caddy solely through its [API](/docs/api). This service uses the [`--resume`](/docs/command-line#caddy-run) option which will start Caddy using the `autosave.json` which is [persisted](/docs/json/admin/config/) by default.
|
||||||
|
|
||||||
|
They are very similar, but differ in the `ExecStart` and `ExecReload` commands to accommodate the workflows.
|
||||||
|
|
||||||
|
If you need to switch between the services, you should disable and stop the previous one before enabling and starting the other. For example, to switch from the `caddy` service to the `caddy-api` service:
|
||||||
|
<pre><code class="cmd"><span class="bash">sudo systemctl disable --now caddy</span>
|
||||||
|
<span class="bash">sudo systemctl enable --now caddy-api</span></code></pre>
|
||||||
|
|
||||||
|
|
||||||
|
### Using the Service
|
||||||
|
|
||||||
|
To verify that the service is running:
|
||||||
|
<pre><code class="cmd bash">systemctl status caddy</code></pre>
|
||||||
|
The status command will also show the location of the currently running service file.
|
||||||
|
|
||||||
|
When running with our official service file, Caddy's output will be redirected to `journalctl`. To read your full logs and to avoid lines being truncated:
|
||||||
|
<pre><code class="cmd bash">journalctl -u caddy --no-pager | less</code></pre>
|
||||||
|
|
||||||
|
If using a config file, you can gracefully reload Caddy after making any changes:
|
||||||
|
<pre><code class="cmd bash">sudo systemctl reload caddy</code></pre>
|
||||||
|
|
||||||
|
You can stop the service with:
|
||||||
|
<pre><code class="cmd bash">sudo systemctl stop caddy</code></pre>
|
||||||
|
|
||||||
|
<aside class="advice">
|
||||||
|
Do not stop the service to change Caddy's configuration. Stopping the server will incur downtime. Use the reload command instead.
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
|
||||||
|
### Manual Installation
|
||||||
|
|
||||||
|
Some [installation methods](/docs/install) automatically set up Caddy to run as a service. If you chose a method that did not, you may follow these instructions to do so:
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
|
||||||
|
- `caddy` binary that you [downloaded](/download) or [built from source](/docs/build)
|
||||||
|
- `systemctl --version` 232 or newer
|
||||||
|
- `sudo` privileges
|
||||||
|
|
||||||
|
Move the caddy binary into your `$PATH`, for example:
|
||||||
|
<pre><code class="cmd bash">sudo mv caddy /usr/bin/</code></pre>
|
||||||
|
|
||||||
|
Test that it worked:
|
||||||
|
<pre><code class="cmd bash">caddy version</code></pre>
|
||||||
|
|
||||||
|
Create a group named `caddy`:
|
||||||
|
<pre><code class="cmd bash">sudo groupadd --system caddy</code></pre>
|
||||||
|
|
||||||
|
Create a user named `caddy`, with a writeable home directory:
|
||||||
|
<pre><code class="cmd bash">sudo useradd --system \
|
||||||
|
--gid caddy \
|
||||||
|
--create-home \
|
||||||
|
--home-dir /var/lib/caddy \
|
||||||
|
--shell /usr/sbin/nologin \
|
||||||
|
--comment "Caddy web server" \
|
||||||
|
caddy</code></pre>
|
||||||
|
|
||||||
|
If using a config file, be sure it is readable by the `caddy` user you just created.
|
||||||
|
|
||||||
|
Next, [choose a systemd unit file](#unit-files) based on your use case.
|
||||||
|
|
||||||
|
**Double-check the `ExecStart` and `ExecReload` directives.** Make sure the binary's location and command line arguments are correct for your installation! For example: if using a config file, change your `--config` path if it is different from the defaults.
|
||||||
|
|
||||||
|
The usual place to save the service file is: `/etc/systemd/system/caddy.service`
|
||||||
|
|
||||||
|
After saving your service file, you can start the service for the first time with the usual systemctl dance:
|
||||||
|
|
||||||
|
<pre><code class="cmd"><span class="bash">sudo systemctl daemon-reload</span>
|
||||||
|
<span class="bash">sudo systemctl enable --now caddy</span></code></pre>
|
||||||
|
|
||||||
|
Verify that it is running:
|
||||||
|
<pre><code class="cmd bash">systemctl status caddy</code></pre>
|
||||||
|
|
||||||
|
Now you're ready to [use the service](#using-the-service)!
|
||||||
|
|
||||||
|
|
||||||
|
### Overrides
|
||||||
|
|
||||||
|
The best way to override aspects of the service files is with this command:
|
||||||
|
<pre><code class="cmd bash">sudo systemctl edit caddy</code></pre>
|
||||||
|
|
||||||
|
This will open a blank file with your default terminal text editor in which you can override or add directives to the unit definition.
|
||||||
|
|
||||||
|
For example, if you need to define environment variables for use in your config, you may do so like this:
|
||||||
|
```systemd
|
||||||
|
[Service]
|
||||||
|
Environment="CF_API_TOKEN=super-secret-cloudflare-tokenvalue"
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, for example if you need to change the config file from the default of the Caddyfile, to instead using a JSON file (note that `Exec*` directives [must be reset with empty strings](https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=) before setting a new value):
|
||||||
|
```systemd
|
||||||
|
[Service]
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/caddy.json
|
||||||
|
ExecReload=
|
||||||
|
ExecReload=/usr/bin/caddy reload --config /etc/caddy/caddy.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, save the file and exit the text editor, and restart the service for it to take effect:
|
||||||
|
<pre><code class="cmd bash">sudo systemctl restart caddy</code></pre>
|
||||||
|
|
||||||
|
|
||||||
|
## Windows service
|
||||||
|
|
||||||
|
Install Caddy as a service on Windows with these instructions.
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
|
||||||
|
- `caddy.exe` binary that you [downloaded](/download) or [built from source](/docs/build)
|
||||||
|
- Any `.exe` from the latest release of the
|
||||||
|
[WinSW](https://github.com/winsw/winsw/releases/latest) service wrapper (the below service config is written for v2.x releases)
|
||||||
|
|
||||||
|
Put all files into a service directory. In the following examples, we use `C:\caddy`.
|
||||||
|
|
||||||
|
Rename the `WinSW-x64.exe` file to `caddy-service.exe`.
|
||||||
|
|
||||||
|
Add a `caddy-service.xml` in the same directory:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<service>
|
||||||
|
<id>caddy</id>
|
||||||
|
<!-- Display name of the service -->
|
||||||
|
<name>Caddy Web Server (powered by WinSW)</name>
|
||||||
|
<!-- Service description -->
|
||||||
|
<description>Caddy Web Server (https://caddyserver.com/)</description>
|
||||||
|
<executable>%BASE%\caddy.exe</executable>
|
||||||
|
<arguments>run</arguments>
|
||||||
|
<log mode="roll-by-time">
|
||||||
|
<pattern>yyyy-MM-dd</pattern>
|
||||||
|
</log>
|
||||||
|
</service>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can now install the service using:
|
||||||
|
<pre><code class="cmd bash">caddy-service install</code></pre>
|
||||||
|
|
||||||
|
You might want to start the Windows Services Console to see if the service is runnnig correctly:
|
||||||
|
<pre><code class="cmd bash">services.msc</code></pre>
|
||||||
|
|
||||||
|
Be aware that Windows services cannot be reloaded, so you have to tell caddy directly to relaod:
|
||||||
|
<pre><code class="cmd bash">caddy reload</code></pre>
|
||||||
|
|
||||||
|
Restarting is possible via the normal Windows services commands, for example via the Task Manager's "Services" tab.
|
||||||
|
|
||||||
|
For customizing the service wrapper, see the [WinSW documentation](https://github.com/winsw/winsw/tree/master#usage)
|
||||||
|
|
||||||
|
|
||||||
|
## Docker Compose
|
||||||
|
|
||||||
|
The simplest way to get up and running with Docker is to use Docker Compose. _The below is only an excerpt, see the docs on [Docker Hub](https://hub.docker.com/_/caddy) for more details_.
|
||||||
|
|
||||||
|
First, create a file `docker-compose.yml` (or add this service to your existing file):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: "3.7"
|
||||||
|
|
||||||
|
services:
|
||||||
|
caddy:
|
||||||
|
image: caddy:<version>
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- $PWD/Caddyfile:/etc/caddy/Caddyfile
|
||||||
|
- $PWD/site:/srv
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure to fill in `<version>` with the latest version number, which you can find listed on [Docker Hub](https://hub.docker.com/_/caddy) under the "Tags" section.
|
||||||
|
|
||||||
|
Then, you can start the container:
|
||||||
|
<pre><code class="cmd bash">docker-compose up -d</code></pre>
|
||||||
|
|
||||||
|
To reload Caddy after making changes to your Caddyfile:
|
||||||
|
<pre><code class="cmd bash">docker-compose exec -w /etc/caddy caddy caddy reload</code></pre>
|
||||||
|
|
||||||
|
To see Caddy's logs:
|
||||||
|
<pre><code class="cmd bash">docker-compose logs caddy</code></pre>
|
||||||
|
|
|
@ -241,24 +241,9 @@ The recommended way to enable access logging is simply:
|
||||||
log
|
log
|
||||||
```
|
```
|
||||||
|
|
||||||
which emits structured logs to stderr. (You can also emit to a file or network socket; see docs.)
|
which emits structured logs to stderr. (You can also emit to a file or network socket; see the [`log`](/docs/caddyfile/directives/log) directive docs.)
|
||||||
|
|
||||||
Although we recommend everyone use [structured logging](/docs/logging), you can still write Common Log Format (CLF) to a file, if you must:
|
By default, logs will be in [structured](/docs/logging) JSON format. If you still need logs in Common Log Format (CLF) for legacy reasons, you may use the [`format-encoder`](https://github.com/caddyserver/format-encoder) plugin.
|
||||||
|
|
||||||
- **v1:**
|
|
||||||
```
|
|
||||||
log access.log
|
|
||||||
```
|
|
||||||
|
|
||||||
- **v2:**
|
|
||||||
```caddy-d
|
|
||||||
log {
|
|
||||||
output file access.log
|
|
||||||
format single_field common_log
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
But we recommend this only for transitioning while your legacy systems still require CLF.
|
|
||||||
|
|
||||||
|
|
||||||
### proxy
|
### proxy
|
||||||
|
@ -373,12 +358,9 @@ Most sites will not need this directive at all.
|
||||||
|
|
||||||
## Service files
|
## Service files
|
||||||
|
|
||||||
We recommend using [one of our official service files](https://github.com/caddyserver/dist/blob/master/init) for Caddy deployments.
|
We recommend using [one of our official systemd service files](/docs/running#linux-service) for Caddy deployments.
|
||||||
|
|
||||||
If you need a custom service file, base it off of ours. It has been carefully tuned to what it is for good reasons! Be sure to customize yours if needed.
|
|
||||||
|
|
||||||
See [install instructions](/docs/install#linux-service) for details.
|
|
||||||
|
|
||||||
|
If you need a custom service file, base it off of ours. They've been carefully tuned to what it is for good reasons! Be sure to customize yours if needed.
|
||||||
|
|
||||||
|
|
||||||
## Plugins
|
## Plugins
|
||||||
|
|
|
@ -23,8 +23,7 @@
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<b>Platform:</b>
|
<b>Platform:</b>
|
||||||
<select size="1" id="platform">
|
<select size="1" id="platform" selected="linux-amd64">
|
||||||
<option></option>
|
|
||||||
<option value="dragonfly-amd64">Dragonfly amd64</option>
|
<option value="dragonfly-amd64">Dragonfly amd64</option>
|
||||||
<option value="freebsd-amd64">FreeBSD amd64</option>
|
<option value="freebsd-amd64">FreeBSD amd64</option>
|
||||||
<option value="freebsd-arm-6">FreeBSD arm 6</option>
|
<option value="freebsd-arm-6">FreeBSD arm 6</option>
|
||||||
|
@ -51,7 +50,7 @@
|
||||||
<option value="windows-amd64">Windows amd64</option>
|
<option value="windows-amd64">Windows amd64</option>
|
||||||
<option value="windows-arm-6">Windows arm 6</option>
|
<option value="windows-arm-6">Windows arm 6</option>
|
||||||
<option value="windows-arm-7">Windows arm 7</option>
|
<option value="windows-arm-7">Windows arm 7</option>
|
||||||
<!-- <option value="windows-arm64">Windows arm64</option> TODO: Go 1.17 - https://github.com/golang/go/issues/36439 -->
|
<option value="windows-arm64">Windows arm64</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
<li><a href="/docs/logging">How Logging Works</a></li>
|
<li><a href="/docs/logging">How Logging Works</a></li>
|
||||||
<li><a href="/docs/metrics">Monitoring Caddy</a></li>
|
<li><a href="/docs/metrics">Monitoring Caddy</a></li>
|
||||||
<li><a href="/docs/architecture">Caddy Architecture</a></li>
|
<li><a href="/docs/architecture">Caddy Architecture</a></li>
|
||||||
|
<li><a href="/docs/running">Keep Caddy Running</a></li>
|
||||||
|
|
||||||
<li class="heading">Developers</li>
|
<li class="heading">Developers</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -34,19 +34,17 @@ $(function() {
|
||||||
// Add links to Caddyfile directive tokens in code blocks.
|
// Add links to Caddyfile directive tokens in code blocks.
|
||||||
// See include/docs-head.html for the whitelist bootstrapping logic
|
// See include/docs-head.html for the whitelist bootstrapping logic
|
||||||
$('pre.chroma .k')
|
$('pre.chroma .k')
|
||||||
.filter(function (k, item) {
|
.filter((k, item) =>
|
||||||
return window.CaddyfileDirectives.includes(item.innerText)
|
window.CaddyfileDirectives.includes(item.innerText)
|
||||||
|| item.innerText === '<directives...>';
|
|| item.innerText === '<directives...>'
|
||||||
})
|
)
|
||||||
.map(function(k, item) {
|
.map(function(k, item) {
|
||||||
let text = item.innerText;
|
let text = item.innerText;
|
||||||
let url = text === '<directives...>'
|
let url = text === '<directives...>'
|
||||||
? '/docs/caddyfile/directives'
|
? '/docs/caddyfile/directives'
|
||||||
: '/docs/caddyfile/directives/' + text;
|
: '/docs/caddyfile/directives/' + text;
|
||||||
$(item)
|
text = text.replace(/</g,'<').replace(/>/g,'>');
|
||||||
.html('<a href="' + url + '" style="color: inherit;" title="Directive"></a>')
|
$(item).html('<a href="' + url + '" style="color: inherit;" title="Directive">' + text + '</a>');
|
||||||
.find('a')
|
|
||||||
.text(text);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add links to [<matcher>] or named matcher tokens in code blocks.
|
// Add links to [<matcher>] or named matcher tokens in code blocks.
|
||||||
|
@ -54,33 +52,26 @@ $(function() {
|
||||||
// so we must use text() to change the link text.
|
// so we must use text() to change the link text.
|
||||||
$('pre.chroma .nd')
|
$('pre.chroma .nd')
|
||||||
.map(function(k, item) {
|
.map(function(k, item) {
|
||||||
let text = item.innerText;
|
let text = item.innerText.replace(/</g,'<').replace(/>/g,'>');
|
||||||
$(item)
|
$(item).html('<a href="/docs/caddyfile/matchers#syntax" style="color: inherit;" title="Matcher token">' + text + '</a>');
|
||||||
.html('<a href="/docs/caddyfile/matchers" style="color: inherit;" title="Matcher token"></a>')
|
|
||||||
.find('a')
|
|
||||||
.text(text);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// On the global options page only, we'll add links to the options to the anchor tags
|
|
||||||
if (window.location.pathname === '/docs/caddyfile/options') {
|
|
||||||
let headers = $('article h5').map(function (i, el) {
|
|
||||||
return el.id.replace(/-/g, "_");
|
|
||||||
}).toArray();
|
|
||||||
$('pre.chroma .k')
|
|
||||||
.filter(function (k, item) {
|
|
||||||
return headers.includes(item.innerText);
|
|
||||||
})
|
|
||||||
.map(function(k, item) {
|
|
||||||
let text = item.innerText;
|
|
||||||
let url = '#' + item.innerText.replace(/_/g, "-");
|
|
||||||
$(item)
|
|
||||||
.html('<a href="' + url + '" style="color: inherit;" title="Global option"></a>')
|
|
||||||
.find('a')
|
|
||||||
.text(text);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// addLinkaddLinksToSubdirectivessToAnchors finds all the ID anchors
|
||||||
|
// in the article, and turns any directive or subdirective span into
|
||||||
|
// links that have an ID on the page. This is opt-in for each page,
|
||||||
|
// because it's not necessary to run everywhere.
|
||||||
|
function addLinksToSubdirectives() {
|
||||||
|
let anchors = $('article *[id]').map((i, el) => el.id).toArray();
|
||||||
|
$('pre.chroma .k')
|
||||||
|
.filter((k, item) => anchors.includes(item.innerText))
|
||||||
|
.map(function(k, item) {
|
||||||
|
let text = item.innerText.replace(/</g,'<').replace(/>/g,'>');
|
||||||
|
let url = '#' + item.innerText;
|
||||||
|
$(item).html('<a href="' + url + '" style="color: inherit;" title="' + text + '">' + text + '</a>');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function stripScheme(url) {
|
function stripScheme(url) {
|
||||||
return url.substring(url.indexOf("://")+3);
|
return url.substring(url.indexOf("://")+3);
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,11 +169,11 @@ $(function() {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
// autoPlatform choooses the platform in the list that best
|
// autoPlatform chooses the platform in the list that best
|
||||||
// matches the user's browser, if it's available.
|
// matches the user's browser, if it's available.
|
||||||
function autoPlatform() {
|
function autoPlatform() {
|
||||||
// assume 32-bit linux, then change OS and architecture if justified
|
// assume 32-bit linux, then change OS and architecture if justified
|
||||||
var os = "linux", arch = "386", arm = "";
|
var os = "linux", arch = "amd64", arm = "";
|
||||||
|
|
||||||
// change os
|
// change os
|
||||||
if (/Macintosh/i.test(navigator.userAgent)) {
|
if (/Macintosh/i.test(navigator.userAgent)) {
|
||||||
|
@ -215,11 +215,15 @@ function autoPlatform() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDownloadLink() {
|
function getDownloadLink() {
|
||||||
|
// make sure we at least have a default,
|
||||||
|
// in the case that autoPlatform() failed
|
||||||
|
var platformString = $('#platform').val();
|
||||||
|
if (!platformString) {
|
||||||
|
platformString = "linux-amd64"
|
||||||
|
}
|
||||||
|
|
||||||
// get platform components
|
// get platform components
|
||||||
var platformParts = $('#platform').val().split("-");
|
var [os, arch, arm = ""] = platformString.split("-");
|
||||||
var os = platformParts[0];
|
|
||||||
var arch = platformParts[1];
|
|
||||||
var arm = platformParts.length > 2 ? platformParts[2] : "";
|
|
||||||
|
|
||||||
var qs = new URLSearchParams();
|
var qs = new URLSearchParams();
|
||||||
if (os) qs.set("os", os);
|
if (os) qs.set("os", os);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue