Caddy 入门实战(3)--Caddyfile 介绍

发布时间 2023-08-20 10:28:04作者: 且行且码

Caddyfile 是一种方便用户使用的 Caddy 配置格式。这是大多数人最喜欢使用 Caddy 的方式,因为它易于编写、易于理解,且能满足绝大部分的使用场景。本文主要介绍 Caddyfile 的相关概念。

1、Caddyfile 结构

  • 可选的全局选项块必须放在文件的头部
  • 否则, Caddyfile 的首行总是要提供服务的网站地址。
  • 所有指令和匹配器都必须放在站点块中。跨站点块没有全局范围或继承。
  • 如果只有一个站点块,则其花括号{ }是可选的。

一个 Caddyfile 至少包含一个或多个站点块,这些块总是以站点的一个或多个地址开始。出现在地址之前的任何指令都会使扰乱解析器。

1.1、块

块用花括号来表示:

... {
    ...
}
  • { 必须位于行尾
  • } 必须独占一行

当只有一个站点块时,花括号(和缩进)是可选的;这是为了方便快速定义单个站点,如:

localhost:8080
reverse_proxy /api/* localhost:9001

相当于:

localhost:8080 {
    reverse_proxy /api/* localhost:9001
}

如果一个请求匹配多个站点块,则选择具有最具体匹配地址的站点块。请求不会级联到其他站点块。

1.2、指令

指令是自定义网站服务方式的关键字。指令是站点块中一行的第一个单词。如下,reverse_proxy 为指令:

localhost:8080
reverse_proxy localhost:9000

 子指令可以出现在指令块中,如下,lb_policy 是 reverse_proxy 的子指令:

localhost:8080
reverse_proxy localhost:9000 localhost:9001 {
    lb_policy first
}

1.3、标记和引号

Caddyfile 在被解析之前会被词法解析成标记。空格在 Caddyfile 中很重要,因为标记就是由它进行分隔。通常,指令需要一定数量的参数,参数中如果有空格,需要使用引号引起来:

directive "abc def"

如果参数中包含引号,可以使用转义或反引号:

directive "\"abc def\""

directive `"foo bar"`

2、地址

地址总是出现在站点块的顶部,以下是有效地址的:

localhost
example.com
:443
http://example.com
localhost:8080
127.0.0.1
[::1]:2015
example.com/foo/*
*.example.com
http://

从地址中,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.html
root @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 line
directive  # or go at the end

# 不能出现在标记的中间(即它必须以空格开头或出现在行首)。这允许在 URI 或其他值中使用它而不需要引号。

7、环境变量

如果你的配置依赖于环境变量,你可以在 Caddyfile 中使用它们:

{$SITE_ADDRESS}

这种形式的环境变量在解析开始之前被替换,因此它们可以扩展为空值、部分标记、完整标记,甚至是多个标记和行。当未找到环境变量时,可以指定默认值,方法是使用:变量名和默认值之间的分隔符:

{$DOMAIN:localhost}

如果你想将环境变量的替换推迟到运行时,你可以使用标准 {env.*} 占位符。

8、全局选项

Caddyfile 是没有键的特殊块,称为全局选项块:

{
    ...
}

如果存在,它必须是配置中的第一个块。
它用于设置全局适用的选项;在里面,只能设置全局选项,不能使用常规站点指令。

 

 

参考:https://caddy2.dengxiaolong.com/docs/caddyfile