v2中文文档
项目

Caddyfile概念

本文档将帮助你详细了解HTTP Caddyfile。

  1. 结构
  2. 地址
  3. 匹配器
  4. 占位符
  5. 片段
  6. 注释
  7. 环境变量
  8. 全局选项

结构

下面的图片可以直观地描述Caddyfile的结构:

Caddyfile的结构

关键点:

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

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

打开和关闭一个是用花括号完成的:

... {
	...
}
  • 打开的花括号{必须位于行尾。
  • 大括号}必须独占一行。

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

localhost

reverse_proxy /api/* localhost:9001
file_server

相当于:

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

当你只有一个站点块时;这是一个偏好问题。

要使用相同的Caddyfile配置多个站点,你必须在每个站点周围使用花括号来分隔它们的配置:

example1.com {
	root * /www/example.com
	file_server
}

example2.com {
	reverse_proxy localhost:9000
}

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

指令

指令是自定义网站服务方式的关键字。例如,完整的文件服务器配置可能如下所示:

localhost

file_server

或反向代理:

localhost

reverse_proxy localhost:9000

在这些示例中,file_serverreverse_proxy是指令。指令是站点块中一行的第一个单词。

在第二个示例中,localhost:9000是一个参数,因为它出现在指令之后的同一行。

请注意,当调整 Caddyfile 时,指令会根据特定的默认指令顺序进行排序。

子指令可以出现在指令块中:

localhost

reverse_proxy localhost:9000 localhost:9001 {
	lb_policy first
}

这里,lb_policyreverse_proxy的子指令(它用于设置后端之间使用的负载平衡策略)。

标记和引号

Caddyfile在被解析之前被词法解析成标记。空格在Caddyfile中很重要,因为标记就是由它进行分隔。

通常,指令需要一定数量的参数。如果单个参数有一个带有空格的值,它会被作为两个单独的标记进行词法分析:

directive abc def

这可能会出现问题并返回错误或意外行为。

如果abc def应该是单个参数的值,则需要使用引号:

directive "abc def"

如果你也需要在带引号的标记中使用引号,则可以转义引号:

directive "\"abc def\""

在带引号的标记内,所有其他字符都按字面意思处理,包括空格、制表符和换行符。

你还可以使用反引号`来引用标记:

directive `"foo bar"`

当标记包含引号文字时,反引号字符串很方便,例如JSON文本。

地址

地址总是出现在站点块的顶部,并且通常出现在Caddyfile中的第一行。

这些是有效地址的示例:

  • 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

请注意逗号如何表示地址的延续。

地址必须是唯一的;你不能多次指定同一个地址。

匹配器

默认情况下,注入HTTP处理程序的指令适用于所有请求(除非另有说明)。

请求匹配器可用于按给定标准对请求进行分类。这个概念源于底层的JSON结构,知道如何在Caddyfile中使用它们很重要。使用匹配器,你可以准确指定某个指令适用于哪些请求。

对于支持匹配器的指令,指令后的第一个参数是匹配器标记。这里有些例子:

root *           /var/www  # matcher token: *
root /index.html /var/www  # matcher token: /index.html
root @post       /var/www  # matcher token: @post

完全省略匹配器标记,则可以匹配所有的请求;例如,如果下一个参数看起来不像路径匹配器,则不需要给出*

阅读有关请求匹配器的页面,了解更多信息。

占位符

你可以在Caddyfile中使用任何Caddy占位符,但为方便起见,你还可以使用一些等效的速记符:

简写 替换
{dir} {http.request.uri.path.dir}
{file} {http.request.uri.path.file}
{header.*} {http.request.header.*}
{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}
{uri} {http.request.uri}
{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}

片段

你可以定义称为片段的特殊块,方法是给它们一个用括号括起来的名称:

(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"
}

注释

注释从行首的#开始并一直持续到行尾:

# Comments can start a line
directive  # or go at the end

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

环境变量

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

{$SITE_ADDRESS}

这种形式的环境变量在解析开始之前被替换,因此它们可以扩展为空值、部分标记、完整标记,甚至是多个标记和行。

当未找到环境变量时,可以指定默认值,方法是使用:变量名和默认值之间的分隔符:

{$DOMAIN:localhost}

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

全局选项

Caddyfile可以选择以没有键的特殊块开始,称为全局选项块

{
	...
}

如果存在,它必须是配置中的第一个块。

它用于设置全局适用的选项,或不适用于任何特定站点。在里面,只能设置全局选项;你不能在其中使用常规站点指令。

点击了解有关全局选项块的更多信息。