Web Server - Caddy 2
Download and Install
Download Caddy 2 from the Caddy Download Page and put it in your PATH
. You can get Caddy for nearly any OS and architecture. Caddy’s download page is unique from other web servers: it lets you customize your build with plugins.
A. Debian,Ubuntu,Raspbian
Installing this package automatically starts and runs Caddy for you as a systemd service named caddy
using official caddy.service unit file.
Method One
you can install it from apt
command.
1 | sudo apt-get install -y debian-keyring debian-archive-keyring apt-transport-https |
Method Two
you can download it from Caddy Download, and then put it in PATH
(example:/usr/local/bin/
).
1 | :~$ curl -o ~/Downloads/caddy "https://caddyserver.com/api/download?os=linux&arch=amd64&p=github.com%2Fmholt%2Fcaddy-webdav&idempotency=79680512439698" |
B. Docker
1 | docker pull caddy |
Run Caddy as a service
Manually install Caddy as a service on Linux with these instructions.
- Requirements:
caddy
binary that you downloadedsystemctl --version
232 or newersudo
privileges
Move the caddy binary into your $PATH
and test that it worked, for example
1 | :~$ sudo mv caddy /usr/bin |
Create a group named caddy
:
1 | :~$ sudo groupadd --system caddy |
Create a user named caddy
, with a writeable home folder:
1 | sudo useradd --system \ |
Note: If using a config file, be sure it is readable by the caddy user you just created.
Next, create a systemd service file.
Github-Caddy.service
1 | :~$ sudo cat > /lib/systemd/system/caddy.service << EOF |
finally, use command caddy
.
1 | :~$ sudo systemctl start caddy |
When running with Caddy official service file, Caddy’s output will be redirected to journalctl
:
1 | :~$ sudo journalctl -u caddy --no-pager | less |
Example of Caddyfile
PHP
1 | # -----------Global options--------------- |
php_fastcgi
An opinionated directive that proxies requests to a PHP FastCGI server such as php-fpm.
1 | # Proxy all PHP requests to a FastCGI responder listening at 127.0.0.1:9000 |
WebDav
1 | # -----------Global options--------------- |
The module http.handlers.webdav
be needed here.
This modlue only supported read operation.
1 | :~$ caddy list-modules | grep webdav |
Caddyfile Docs
The Caddyfile is a convenient Caddy configuration format for humans. It is most people’s favorite way to use Caddy because it is easy to write, easy to understand, and expressive enough for most use cases.
Concepts
Caddy-Docs-Concepts
Structure
The Caddyfile’s structure can be described visually:
Key points:
- An optional global options block can be the very first thing in the file.
- Otherwise, the first line of the Caddyfile is always the address(es) of the site to serve.
- All directives and matchers must go in a site block. There is no global scope or inheritence across site blocks.
- If there is only one site block, its curly braces
{ }
are optional.
Global Options
Caddy-Docs-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.
The very top of your Caddyfile can be a global options block.
1 | { |
http_port : The port for the server to use for HTTP. For internal use only; does not change the HTTP port for clients.Default : 80https_port : The port for the server to use for HTTPS. For internal use only; does not change the HTTPS port for clients.Default : 443server : Customizes HTTP servers with settings that potentially span multiple sites and thus can’t be rightly configured in site blocks.protocol allow_h2c : enables H2C (“Cleartext HTTP/2” or “H2 over TCP”) support, which will serve HTTP/2 over plaintext TCP connections if a client support it. This setting applies only to unencrypted HTTP listeners.experimental_http3 : enables experimental draft HTTP/3 support. Note that HTTP/3 is not a finished spec and client support is extremely limited. This option will go away in the future.
Request Matchers
Request matchers can be used to filter (or classify) requests by specific criteria.
In the Caddyfile, a matcher token immediately following the directive can limit that directive’s scope. The matcher token can be one of these forms:
Wildcard matchers :* to match all requests (default).Path matchers :/path start with a forward slash to match a request path.Named matchers :@name to specify a named matcher.
Wildcard matchers
The wildcard (or “catch-all”) matcher *
matches all requests, and is only needed if a matcher token is required.
1 | # Set the site root to /var/www/mysite for all requests |
Path matchers
Because matching by path is so common, a single path matcher can be inlined, like so:
1 | redir /old.html /new.html |
Path matcher tokens /
.
Path matching is an exact match by default; you must append a *
for a fast prefix match. Note that /foo*
will match /foo
and /foo/
as well as /foobar
; you might actually want /foo/*
instead.
Named matchers
Defining a matcher with a unique name gives you more flexibility, allowing you to combine any available matchers into a set:
1 | # multi matchers |
For example:
1 | @websockets { |
This proxies
Like directives,
A named matcher definition constitutes a matcher set.
Standard matchers
- expression
- file
- header
- header_regexp
- host
- method
- not
- path
- path_regexp
- protocol
- query
- remote_ip
header
1 | header <field> [<value>] |
By request header fields.
<field>
is the name of the HTTP header field to check.- If prefixed with
!
, the field must not exist to match (omit value arg). <value>
is the value the field must have to match.- If prefixed with
*
, it performs a fast suffix match. - If suffixed with
*
, it performs a fast prefix match. - If enclosed by
*
, it performs a fast substring match. - Otherwise, it is a fast exact match.
Example One
Match requests with the Connection
header containing Upgrade
and server
header is Caddy
.
1 | @foo { |
Example Two
Match requests with the Foo
header containing bar
OR baz
.
1 | @foo { |
Example Three
Match requests that do not have the Foo
header field at all
1 | @not_foo { |
method
1 | method <verbs...> |
By the method (verb) of the HTTP request. Verbs should be uppercase, like POST. Can match one or many methods.
1 | # Match requests with the GET method. |
not
1 | # OR |
Examples One
Match requests with paths that do NOT begin with /css/
OR /js/
.
1 | not path /css/* /js/* |
Example Two
Match requests WITH NEITHER:
- an
/api/
path prefix, NOR - the
POST
request method
1 | not path /api/* |
Example Three
Match requests WITHOUT BOTH
- an
/api/
path prefix, AND - the
POST
request method
1 | not { |
path
1 | path <paths...> |
By request path, meaning the path component of the request’s URI. Path matches are exact, but wildcards * may be used:
- At the end, for a prefix match (
/prefix/*
) - At the beginning, for a suffix match (
*.suffix
) - On both sides, for a substring match (
*/contains/*
) - In the middle, for a globular match (
/accounts/*/info
)
Directives
The following directives come standard with Caddy, and can be used in the HTTP Caddyfile:
Directive | Description |
---|---|
acme_server | An embedded ACME server |
basicauth | Enforces HTTP Basic Authentication |
bind | Customize the server’s socket address |
encode | Encodes (usually compresses) responses |
file_server | Serve files from disk |
handle | A mutually-exclusive group of directives |
handle_errors | Defines routes for handling errors |
handle_path | Like handle, but strips path prefix |
header | Sets or removes response headers |
import | Include snippets or files |
log | Enables access/request logging |
map | Maps an input value to one or more outputs |
metrics | Configures the Prometheus metrics exposition endpoint |
php_fastcgi | Serve PHP sites over FastCGI |
push | Push content to the client using HTTP/2 server push |
redir | Issues an HTTP redirect to the client |
request_body | Manipulates request body |
request_header | Manipulates request headers |
respond | Writes a hard-coded response to the client |
reverse_proxy | A powerful and extensible reverse proxy |
rewrite | Rewrites the request internally |
root | Set the path to the site root |
route | A group of directives treated literally as single unit |
templates | Execute templates on the response |
tls | Customize TLS settings |
try_files | Rewrite that depends on file existence |
uri | Manipulate the URI |
Directive order
Many directives manipulate the HTTP handler chain. The order in which those directives are evaluated matters, so a default ordering is hard-coded into Caddy:
1 | map |
You can override/customize this ordering by using the order
global option or the route
directive.
log
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).
1 | log { |
output
: configures a where to write the logs to.Default : stderrstderr
: Standard error (console, default).stdout
: Standard output (console).discard
: No output.file
: A file. By default, log files are rotated (“rolled”) to prevent disk space exhaustion.net
: A network socket.format
: describes how to encode, or format, the logs.Default : console if stdout is detected to be a terminal, json otherwise.console
: The console encoder formats the log entry for human readability while preserving some structure.json
: Formats each log entry as a JSON object.single_field
: Writes only a single field from the structure log entry. Useful if one of the fields has all the information you need.filter
: Wraps another encoder module, allowing per-field filtering.delete
: Marks a field to be skipped from being encoded.ip_mask
: Masks IP addresses in the field using a CIDR mask.level
: is the minimum entry level to log.Default : INFO
Example
1 | # Use common log format |
Basicauth
basicauth, Enables HTTP Basic Authentication, which can be used to protect directories and files with a username and hashed password. Note that basic auth is not secure over plain HTTP.
Caddy configuration does not accept plaintext passwords; we MUST hash them before putting them into the configuration. The
1 | :~$ caddy hash-password |
Example:
1 | haven200.com { |
encode
Encodes responses using the configured encoding(s). A typical use for encoding is compression.
1 | haven200.com { |
file_server
A static file server. It works by appending the request’s URI path to the site’s root path. By default, it enforces canonical URIs; if necessary, requests to directories will be redirected to have a trailing forward slash, and requests to files will be redirected to strip the trailing slash.
Most often, the file_server directive is paired with the root directive to set file root for the whole site.
1 | file_server [<matcher>] [browse] { |
browse
enables file listings for requests to directories that do not have an index file.root
sets the path to the site root for just this file server instance, overriding any other.Default :{http.vars.root}
or the current working directory.Note: This subdirective only changes the root for this directive. For other directives (like try_files or templates) to know the same site root, use the root directive, not this subdirective.hide
is a list of files or folders to hide; if requested, the file server will pretend they do not exist. Accepts placeholders and glob patterns. Note that these are file system paths, NOT request paths.index
is a list of filenames to look for as index files.Default :index.html
index.txt
<template_file>
is an optional custom template file to use for directory listings.
Example One
The file_server directive is usually paired with the root directive to set the root path from which to serve files:
1 | haven200.com { |
Example Two
A static file server out of the /var/www
directory With file listings enabled, and hide all .git
folders and their contents
1 | haven200.com { |
header
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, in which case the header operations are automatically deferred until the time they are being written to the client.
1 | header [<matcher>] [[+|-|?]<field> [<value>|<find>] [<replace>]] { |
<field>
is the name of the header field. By default, will overwrite any existing field of the same name. Prefix with+
to add the field instead of replace, or prefix with-
to remove the field.<value>
is the header field value, if adding or setting a field.<default_value>
is the header field value that will be set only if the header does not already exist.<find>
is the substring or regular expression to search for.<replace>
is the replacement value; required if performing a search-and-replace.defer
will force the header operations to be deferred until the response is written out to the client. This is automatically enabled if any of the header fields are being deleted.
Example
1 | # Set a custom header field on all requests |
root
Sets the root
path of the site, used by various matchers and directives that access the file system. If unset, the default site root is the current working directory.
Specifically, this directive sets the {http.vars.root}
placeholder.
This directive does not automatically enable serving static files, so it is often used in conjunction with the [file_server directive][toc_haven200_file_server] or the [php_fastcgi directive][toc_haven200_php_fastcgi].
1 | # Set the site root to /home/user/public_html for all requests |
php_fastcgi
An opinionated directive that proxies requests to a PHP FastCGI server such as php-fpm.
Caddy’s reverse_proxy is capable of serving any FastCGI application, but this directive is tailored specifically for PHP apps. This directive is actually just a convenient way to use a longer, more common configuration (below).
1 | php_fastcgi [<matcher>] <php-fpm_gateways...> { |
<php-fpm_gateways...>
are the addresses of the FastCGI servers.root
sets the root folder to the site.Default :root
directive.split
sets the substrings for splitting the URI into two parts. The first matching substring will be used to split the “path info” from the path. The first piece is suffixed with the matching substring and will be assumed as the actual resource (CGI script) name. The second piece will be set to PATH_INFO for the CGI script to use.Default :.php
env
sets an extra environment variable to the given value. Can be specified more than once for multiple environment variables.index
specifies the filename to treat as the directory index file. This affects the file matcher in the expanded form.Default :index.php
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.Default : no timeout.read_timeout
is how long to wait when reading from the FastCGI server. Accepts duration values.Default : no timeout.write_timeout
is how long to wait when sending to the FastCGI server. Accepts duration values.Default : no timeout.
Expanded form
The php_fastcgi
directive is the same as the following configuration:
1 | route { |
Most modern PHP apps work well with this preset. If yours does not, feel free to borrow from this and customize it as needed instead of using the php_fastcgi
shortcut.
Examples
1 | #Proxy all PHP requests to a FastCGI responder listening at 127.0.0.1:9000: |
rewrite
Rewrites the request internally. A rewrite changes some or all of the request URI.
The rewrite
directive implies the intent to accept the request, but with modifications. It is mutually exclusive to other rewrite directives in the same block, so it is safe to define rewrites that would otherwise cascade into each other;
Because rewrite essentially performs an internal redirect, the Caddyfile adapter will not fold any subsequent, adjacent handlers into the same route if their matchers happen to be exactly the same. This allows the matchers of the next handlers to be deferred until after the rewrite. In other words, a matcher that matches a request before the rewrite might not match the same request after the rewrite. If you want your rewrite to share a route with other handlers, use the route or handle directives.
1 | rewrite [<matcher>] <to> |
- is the URI to set on the request. Only designated parts will be replaced. The URI path is any substring that comes before
?
. If?
is omitted, then the whole token is considered to be the path.
Examples
1 | # Rewrite all requests to foo.html, leaving any query string unchanged: |
Preference:
- caddy v1
- Caddy-website
- Caddy-docs