Caddy 2 Caddyfile Usage
Some Caddy v2 Caddyfile examples.
Global Options 1
2
3
4
5
6
7
8
9
10
{
# Turn on all debug log
debug
# Setup default sni
default_sni example.com
# Turn off admin port
admin off
# Turn on http3
experimental_http3
}
Multiple Domains 1
2
3
www.example.com test.example.com {
...
}
1
2
3
old.example.com other.example.com {
redir https://example.com {uri}
}
Error Handling 1
2
3
4
5
6
7
8
www.example.com {
root * /www/example.com
file_server
handle_errors {
rewrite * /{http.error.status_code}.html
file_server
}
}
Template Create your own myip
page.
/www/example.com/myip/index.html
Caddy will parse all files:
1
2
3
4
5
www.example.com {
root * /www/example.com
file_server
templates
}
Caddy will parse files in /www/example.com/myip/
:
1
2
3
4
5
www.example.com {
root * /www/example.com
file_server
templates /www/example.com/myip /
}
Caddy will only parse /www/example.com/myip/index.html
:
1
2
3
4
5
www.example.com {
root * /www/example.com
file_server
templates /www/example.com/myip/index.html
}
1
2
3
4
5
6
7
www.example.com {
root * /www/example.com
file_server
header Access-Control-Allow-Origin *
header Cache-Control max-age=3600
header /css /* Cache-Control max-age=604800
}
Snippet / Import Caddy v2.1+ allow common section to be factored out (snippet) and re-used by different sections.
Cache-Control 1
2
3
4
5
(cache_ctl) {
header /css /* Cache-Control max-age=3600
header /img/* Cache-Control max-age=3600
header /js/* Cache-Control max-age=3600
}
Force Https ACME 1
2
3
4
5
6
7
(acme_https) {
tls {
issuer acme {
disable_http_challenge
}
}
}
Log Log to standard out:
1
2
3
4
5
6
(log_stdout) {
log {
format json
output stdout
}
}
Auto name log file base on hostname:
1
2
3
4
5
6
7
8
(log_file) {
log {
format logfmt
output file /var/log/caddy /{host}.access.log {
roll_keep 7
}
}
}
Log setting is per site. See site option below.
Redirect Caddy < 2.2
1
2
3
4
5
6
7
8
(_redir) {
@{args.0 } {
not file /{path} /{path}/ /{path}index.html /{path}/index.html
not path_regexp r {args.1 }/. *
path_regexp r ^{args.0 }/?(?P<goto> .*)$
}
redir @{args.0 } {args.1 }/{re.r.goto}
}
Caddy >= 2.2
1
2
3
4
5
6
7
8
(_redir) {
@{args.0 } {
not file /{path} /{path}/
not path_regexp r {args.1 }/. *
path_regexp r ^{args.0 }/?(?P<goto> .*)$
}
redir @{args.0 } {args.1 }/{re.r.goto}
}
Usage:
1
2
3
4
5
int.jsiu.dev {
# import _redir <from> <to>
import _redir /\d{4 }/\d{2 }(/\d{2 })? /blog
import _redir /category /tags
}
<from>
and <to>
should always start with /
, but no trailing /
.
Site Option 1
2
3
4
5
6
7
8
9
10
11
(site_option) {
encode zstd gzip
file_server
handle_errors {
rewrite * /{http.error.status_code}.html
file_server
}
import acme_https
import log_file
root * /www /{host}
}
Use above in site sections:
1
2
3
4
5
6
7
8
9
example1.com {
import cache_ctl
import site_option
}
example2.com {
import cache_ctl
import site_option
}
Multiple domains:
1
2
3
4
example1.com example2.com {
import cache_ctl
import site_option
}
My IP This snippet allow creation of a text only “MY IP” page.
1
2
3
4
5
(myip) {
header {args.0 } Content-Type text/plain
respond {args.0 } "{{.RemoteIP}}"
templates {args.0 }
}
Following site use the snippet to create a “MY IP” page at /myip
and /myip/
.
1
2
3
4
5
example.com {
import myip /myip
import myip /myip /
import site_option
}
If you want to use a sub-domain for this purpose, then one line is enough.
1
2
3
myip.example.com {
import myip /
}
Favicon Provide a favicon.ico
to any site:
1
2
3
4
5
(favicon) {
file_server /favicon.ico {
root {args.0 }
}
}
Use as follow:
1
2
3
4
example.com {
import favicon /var/www/static
import site_option
}
Also check out example in CORS .
CORS Single 1
2
3
4
5
6
api.example.com {
@site2 header Origin https://w3.example.com
header @site2 Access-Control-Allow-Origin https://w3.example.com
file_server
root * /www/api.example.com
}
Multiple Caddy v2.1+
1
2
3
4
5
6
7
8
9
10
11
12
13
(cors) {
@{args.0 } header Origin {args.0 }
header @{args.0 } Access-Control-Allow-Origin {args.0 }
}
api.example.com {
root * /www/api.example.com
file_server
import cors https://example.com
import cors https://www.example.com
import cors https://another.example.com
}
Use regular expression to cover domain and sub-domains.
1
2
3
4
5
6
7
8
9
10
11
(cors_reg) {
@{args.0 } header_regexp Origin {args.0 }
header @{args.0 } Access-Control-Allow-Origin {http.request.header.origin}
}
api.example.com {
root * /www/api.example.com
file_server
import cors_reg https:// ([[:alnum:]-]+\.)*example.com
}
Reverse-Proxy When hosting service behind reverse-proxy, some service by default set Access-Control-Allow-Origin
to *
. To change that:
1
2
3
4
5
6
7
8
9
10
api.example.com {
import cors https://example.com
import cors https://www.example.com
import cors https://another.example.com
reverse_proxy http://backend.example.com {
# Remove Access-Control-Allow-Origin from backend response
header_down -Access-Control-Allow-Origin
}
}
With cors_reg
:
1
2
3
4
5
6
7
8
api.example.com {
import cors_reg https:// ([[:alnum:]-]+\.)*example.com
reverse_proxy http://backend.example.com {
# Remove Access-Control-Allow-Origin from backend response
header_down -Access-Control-Allow-Origin
}
}
John Siu Update: 2021-03-29
Please enable JavaScript to view the comments powered by Disqus. comments powered by