Caddyfile是一种方便用户使用的 Caddy 配置格式。这是大多数人最喜欢使用 Caddy 的方式,因为它易于编写、易于理解,且能满足绝大部分的使用场景。本文主要介绍 Caddyfile 的相关概念。
1、Caddyfile 结构
- 可选的全局选项块必须放在文件的头部
- 否则, Caddyfile 的首行总是要提供服务的网站地址。
- 所有指令和匹配器都必须放在站点块中。跨站点块没有全局范围或继承。
- 如果只有一个站点块,则其花括号
{ }
是可选的。
一个 Caddyfile 至少包含一个或多个站点块,这些块总是以站点的一个或多个地址开始。出现在地址之前的任何指令都会使扰乱解析器。
1.1、块
块用花括号来表示:
... { ...}
- { 必须位于行尾
- } 必须独占一行
当只有一个站点块时,花括号(和缩进)是可选的;这是为了方便快速定义单个站点,如:
localhost:8080reverse_proxy /api/* localhost:9001
相当于:
localhost:8080 { reverse_proxy /api/* localhost:9001}
如果一个请求匹配多个站点块,则选择具有最具体匹配地址的站点块。请求不会级联到其他站点块。
1.2、指令
指令是自定义网站服务方式的关键字。指令是站点块中一行的第一个单词。如下,reverse_proxy 为指令:
localhost:8080reverse_proxy localhost:9000
子指令可以出现在指令块中,如下,lb_policy 是 reverse_proxy 的子指令:
localhost:8080reverse_proxy localhost:9000 localhost:9001 { lb_policy first}
1.3、标记和引号
Caddyfile 在被解析之前会被词法解析成标记。空格在 Caddyfile 中很重要,因为标记就是由它进行分隔。通常,指令需要一定数量的参数,参数中如果有空格,需要使用引号引起来:
directive "abc def"
如果参数中包含引号,可以使用转义或反引号:
directive "\"abc def\""directive `"foo bar"`
2、地址
地址总是出现在站点块的顶部,以下是有效地址的:
localhostexample.com:443http://example.comlocalhost:8080127.0.0.1[::1]:2015example.com/foo/**.example.comhttp://
从地址中,Caddy 可以潜在地推断出你站点的方案、主机、端口和路径。
如果你指定主机名,则只会处理具有匹配 Host 标头的请求。换句话说,如果站点地址是 localhost,那么 Caddy 将不会匹配到 127.0.0.1 的请求。
可以使用通配符(*),但仅代表主机名的一个标签。例如,*.example.com 匹配 foo.example.com,但不匹配 foo.bar.example.com,* 匹配 localhost,但不匹配 example.com。
如果多个站点共享相同的定义,你可以将所有站点一起列出:
localhost:8080, example.com, www.example.com
或者
localhost:8080,example.com,www.example.com
逗号表示地址的延续。地址必须是唯一的;你不能多次指定同一个地址。
3、匹配器
默认情况下,注入 HTTP 处理程序的指令适用于所有请求。
请求匹配器可用于按给定标准对请求进行分类。使用匹配器,你可以准确指定某个指令适用于哪些请求。
对于支持匹配器的指令,指令后的第一个参数是匹配器标记。如:
root * /var/www # matcher token: *root /index.html /var/www # matcher token: /index.htmlroot @post /var/www # matcher token: @post
完全省略匹配器标记,则可以匹配所有的请求;例如,如果下一个参数看起来不像路径匹配器,则不需要给出 *。
4、占位符
可以在 Caddyfile 中使用 Caddy 占位符,占位符说明如下:
简写 | 完整写法 | 说明 |
---|---|---|
{cookie.*} | {http.request.cookie.*} | 某个 cookie 信息 |
{dir} | {http.request.uri.path.dir} | 请求路径目录,对于请求/a/b/c.html,值为:/a/b |
{err.*} | {http.error.*} | |
{file_match.*} | {http.matchers.file.*} | |
{file.base} | {http.request.uri.path.file.base} | 请求路径文件基础部分,对于请求/a/b/c.html,值为:c |
{file.ext} | {http.request.uri.path.file.ext} | 请求路径文件后缀,对于请求/a/b/c.html,值为:.html |
{file} | {http.request.uri.path.file} | 请求路径文件,对于请求/a/b/c.html,值为:c.html |
{header.*} | {http.request.header.*} | 某个请求头信息,如:{header.User-Agent} |
{host} | {http.request.host} | 请求主机 |
{labels.*} | {http.request.host.labels.*} | |
{hostport} | {http.request.hostport} | 请求主机及端口 |
{port} | {http.request.port} | 请求端口 |
{method} | {http.request.method} | 请求方法 |
{path} | {http.request.uri.path} | 请求路径 |
{path.*} | {http.request.uri.path.*} | |
{query} | {http.request.uri.query} | 请求参数 |
{query.*} | {http.request.uri.query.*} | 某个请求参数 |
{re.*.*} | {http.regexp.*.*} | |
{remote} | {http.request.remote} | 客户端地址 |
{remote_host} | {http.request.remote.host} | 客户端主机 |
{remote_port} | {http.request.remote.port} | 客户端端口 |
{scheme} | {http.request.scheme} | 请求协议 |
{tls_cipher} | {http.request.tls.cipher_suite} | |
{tls_version} | {http.request.tls.version} | |
{tls_client_fingerprint} | {http.request.tls.client.fingerprint} | |
{tls_client_issuer} | {http.request.tls.client.issuer} | |
{tls_client_serial} | {http.request.tls.client.serial} | |
{tls_client_subject} | {http.request.tls.client.subject} | |
{tls_client_certificate_pem} | {http.request.tls.client.certificate_pem} | |
{tls_client_certificate_der_base64} | {http.request.tls.client.certificate_der_base64} | |
{upstream_hostport} | {http.reverse_proxy.upstream.hostport} | |
{uri} | {http.request.uri} | 请求路径及请求参数 |
{vars.*} | {http.vars.*} |
5、片段
你可以定义称为片段的特殊块,如:
(redirect) { @http { protocol http } redir @http https://{host}{uri}}
然后你可以在任何你需要的地方重复使用它:
import redirect
import 指令还可用于在其位置包含其他文件。作为一种特殊情况,它几乎可以出现在 Caddyfile 中的任何位置。
可以将参数传递给导入的配置并像这样使用它们:
(snippet) { respond "Yahaha! You found {args.0}!"}a.example.com { import snippet "Example A"}b.example.com { import snippet "Example B"}
6、注释
注释从行首的 # 开始并一直持续到行尾:
# Comments can start a linedirective # or go at the end
# 不能出现在标记的中间(即它必须以空格开头或出现在行首)。这允许在 URI 或其他值中使用它而不需要引号。
7、环境变量
如果你的配置依赖于环境变量,你可以在 Caddyfile 中使用它们:
{$SITE_ADDRESS}
这种形式的环境变量在解析开始之前被替换,因此它们可以扩展为空值、部分标记、完整标记,甚至是多个标记和行。当未找到环境变量时,可以指定默认值,方法是使用:变量名和默认值之间的分隔符:
{$DOMAIN:localhost}
如果你想将环境变量的替换推迟到运行时,你可以使用标准 {env.*} 占位符。
8、全局选项
Caddyfile 是没有键的特殊块,称为全局选项块:
{ ...}
如果存在,它必须是配置中的第一个块。
它用于设置全局适用的选项;在里面,只能设置全局选项,不能使用常规站点指令。
参考:https://caddy2.dengxiaolong.com/docs/caddyfile