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