升级指南
Caddy 2 是一个全新的代码库,从头重写,以改进 Caddy 1。Caddy 2 与 Caddy 1 不向后兼容。但别担心,对于大多数基础设置,变化并不大。本指南将帮助你尽可能轻松地完成迁移。
本指南不会深入介绍可用的新功能——顺带一提,它们确实很酷,你应该学习它们——这里的目标只是让你快速在 Caddy 2 上启动并运行。
高阶要点
- “Caddy 2” 仍然只叫作
caddy。我们有时会使用 “Caddy 2” 来澄清版本以减少迁移时的混淆。 - 大多数用户只需要替换他们的
caddy可执行文件和更新后的Caddyfile配置(在测试其可用性后)。 - 最好以不带有 Caddy 1 预设假设的心态来使用 Caddy 2。
- 你可能无法在 v2 中完美复刻某些非常小众的 v1 配置。通常这是有原因的。
- 命令行不再用于服务器配置。
- 环境变量不再用于配置。
- 给 Caddy 2 提供配置的主要方式是通过其API,但也可以使用
caddy命令。 - 你应该知道 Caddy 2 的原生配置语言是 JSON,Caddyfile 只是将配置转换为 JSON 的另一种配置适配器。极其定制/高级的用例可能需要直接使用 JSON,因为并非所有可能的配置都能用 Caddyfile 表达。
- Caddyfile 大体相同,但更强大;指令发生了变化。
步骤
- 通过我们的入门指南熟悉 Caddy 2。
- 如果你还没做第 1 步,请先做。认真的 —— 我们无法强调至少了解如何使用 Caddy 2 是多么重要。(而且这更有趣!)
- 使用下面的指南迁移你的
caddy命令。 - 使用下面的指南迁移你的 Caddyfile。
- 在本地或预发环境测试你的新配置。
- 测试,再测试,继续测试
- 部署并享受吧!
HTTPS 和端口
Caddy 的默认端口不再是 :2015。Caddy 2 的默认端口是 :443,如果未知主机名/IP,则为 :80。你始终可以在配置中自定义端口。
Caddy 2 的默认协议是在已知主机名或 IP 时始终使用 HTTPS。这与 Caddy 1 不同,Caddy 1 默认仅对公开可见的域名使用 HTTPS。现在,每个 站点都会使用 HTTPS(除非你通过显式指定端口 :80 或使用 http:// 来禁用它)。
IP 地址和 localhost 域名将由一个本地信任的内嵌 CA签发证书。所有其他域名将使用 ZeroSSL 或 Let's Encrypt。(这些都是可配置的。)
证书和 ACME 资源的存储结构已更改。Caddy 2 可能会为你的网站获取新证书;但如果你有大量证书,也可以手动迁移它们(如果程序没有为你迁移的话)。详情见 issue #2955 和 #3124。
命令行
caddy 命令现在是 caddy run。
所有命令行标志都不同了。把它们移除;所有服务器配置现在都存在于实际的配置文档中(通常是 Caddyfile 或 JSON)。你很可能能在 JSON 结构 或 Caddyfile 全局选项 中找到替代大多数 v1 命令行标志的配置方法。
像 caddy -conf ../Caddyfile 这样的命令将变为 caddy run --config ../Caddyfile。
和以前一样,如果你的 Caddyfile 在当前文件夹,Caddy 会自动查找并使用它;在这种情况下你无需使用 --config 标志。
信号大致相同,但不再支持 USR1 和 USR2。请使用 caddy reload 命令或API来加载新配置。
以前运行 caddy 而不带任何配置会启动一个简单的文件服务器。Caddy 2 的等价命令是 caddy file-server。
环境变量不再相关,除了 HOME(以及可选的任何你设置的 XDG_* 变量)。CADDYPATH 已被操作系统约定替代。
Caddyfile
V2 的 Caddyfile 与你已熟悉的非常相似。你需要做的主要事情是更改指令。
⚠️ 务必深入阅读新的指令! 尤其是如果你的配置比较复杂,有很多细微差别需要考虑。这些提示会让你大部分配置快速切换过来,但请务必阅读每个指令的完整文档,以便理解升级的影响。当然,在将配置投入生产之前,总是要彻底测试。
主要变化
-
如果你提供静态文件服务,你需要添加一个
file_server指令,因为 Caddy 2 默认不会启用静态文件服务。出于安全原因,Caddy 2 默认也不会嗅探 MIME;如果缺少 Content-Type,你可能需要使用 header 指令自行设置该头。 -
在 v1 中,你只能按请求路径来过滤(或“匹配”)指令。在 v2 中,请求匹配 更加强大。任何在 v2 中将中间件添加到 HTTP 处理链或以任何方式操纵 HTTP 请求/响应的指令,都可以使用这种新的匹配功能。阅读更多关于 v2 请求匹配器的内容。你需要了解它们才能理解 v2 Caddyfile。
-
虽然许多占位符 与以前相同,但也有许多已更改,并且现在有很多新占位符,包括Caddyfile 的简写占位符。
-
Caddy 2 的日志都是结构化的,默认格式为 JSON。所有日志级别都可以简单地发送到同一个日志以便处理(但如果需要你可以自定义)。
-
在 Caddy 1 中按路径前缀匹配请求的地方,Caddy 2 中的路径匹配现在默认是精确匹配。如果你想匹配像
/foo/这样的前缀,在 Caddy 2 中需要写成/foo/*。
下面我们列出了一些最常见的 v1 指令,并描述如何将它们转换以在 v2 Caddyfile 中使用。
⚠️ 仅因为此页中缺少某个 v1 指令并不意味着 v2 无法实现它! 有些 v1 指令不再需要、不能很好地转换,或在 v2 中以其他方式实现。对于某些高级定制,你可能需要降到 JSON 层面来完成。请浏览我们的文档以找到你需要的内容!
basicauth
HTTP 基本认证仍然使用 basic_auth 指令配置。然而,Caddy 2 的配置不接受明文密码。你必须对密码进行哈希,caddy hash-password 可以帮你完成这项工作。
- v1:
basicauth /secret/ Bob hiccup
- v2:
basic_auth /secret/* {
Bob JDJhJDEwJEVCNmdaNEg2Ti5iejRMYkF3MFZhZ3VtV3E1SzBWZEZ5Q3VWc0tzOEJwZE9TaFlZdEVkZDhX
}
browse
文件浏览现在通过 file_server 指令启用。
- v1:
browse /subfolder/
- v2:
file_server /subfolder/* browse
errors
自定义错误页可以通过 handle_errors 实现。
- v1:
errors {
404 404.html
500 500.html
}
- v2:
handle_errors {
rewrite * /{err.status_code}.html
file_server
}
ext
隐含文件扩展名可以用 try_files 实现。
- v1:
ext .html - v2:
try_files {path}.html {path}
fastcgi
假设你在提供 PHP 服务,v2 等价为 php_fastcgi。
- v1:
fastcgi / localhost:9005 php
- v2:
php_fastcgi localhost:9005
注意 v1 的 fastcgi 指令在内部做了很多工作,包括在磁盘上尝试文件、重写请求,甚至重定向。v2 的 php_fastcgi 指令也为你完成了这些事情,但文档给出了可以修改的展开形式,以便在需求不同的情况下调整。
v2 中不需要 php 预设,因为 php_fastcgi 默认假定使用 PHP。像 php_fastcgi 127.0.0.1:9000 php 这样的行会导致反向代理认为存在第二个名为 php 的后端,从而引起连接错误。
子指令在 v2 中有所不同 —— 对于 PHP,大多数情况下你可能不需要任何子指令。
gzip
现在使用一个单一指令 encode 来处理所有响应编码,包括多种压缩格式。
- v1:
gzip
- v2:
encode gzip
有趣的是:Caddy 2 还支持 zstd(不过目前没有浏览器支持)。
header
大体不变,但在 v2 中更强大,因为它可以做子字符串替换。
- v1:
header / Strict-Transport-Security max-age=31536000;
- v2:
header Strict-Transport-Security max-age=31536000;
log
启用访问日志;log 指令在 v2 中仍可使用,但所有日志默认都是结构化的、以 JSON 编码。
推荐的启用访问日志的方式很简单:
log
该配置会向 stderr 输出结构化日志。(你也可以输出到文件或网络套接字;参见log 指令文档。)
默认情况下,日志将采用结构化 的 JSON 格式。如果你仍然因兼容原因需要使用通用日志格式(CLF),可以使用 transform-encoder 插件。
proxy
v2 的对应为 reverse_proxy。
值得注意的子指令变化是 header_upstream 和 header_downstream 已分别变为 header_up 和 header_down;与负载均衡相关的子指令以 lb_ 前缀命名。
另一个重要差异是 v2 代理默认会透传所有传入头(包括 Host 头)并设置 X-Forwarded-For 头。换言之,v1 的 “transparent” 模式在 v2 中基本就是默认行为(但如果你需要其他头例如 X-Real-IP,你必须自己设置)。你仍然可以使用 header_up 子指令覆盖/自定义 Host 头。
WebSocket 代理在 v2 中“开箱即用”;不需要像 v1 那样“启用” websockets。
without 子指令已被移除,因为得益于更强的匹配器支持,v2 中不再需要rewrite 改造技巧。
- v1:
proxy / localhost:9005
- v2:
reverse_proxy localhost:9005
redir
未改变,除了一些关于可选状态码参数的细节。大多数配置无需做任何修改。
- v1:
redir https://example.com{uri} - v2:
redir https://example.com{uri}
rewrite
请求重写(“内部重定向”)的语义略有变化。如果你在 v1 中使用所谓的 “rewrite 改造技巧” 来作为按非简单路径前缀匹配请求的办法,在 v2 中这完全不必要。
新的 rewrite 指令 非常简单但很强大,因为大部分复杂性由 v2 中的匹配器 处理:
- v1:
rewrite {
if {>User-Agent} has mobile
to /mobile{uri}
}
- v2:
@mobile {
header User-Agent *mobile*
}
rewrite @mobile /mobile{uri}
注意我们只是使用 Caddy 2 常用的匹配器标记;对于该指令不再是特殊情况。
首先移除所有 rewrite 改造技巧;将它们改为命名匹配器。评估每个 v1 的 rewrite 看看在 v2 中是否真的需要。提示:如果 v1 的 Caddyfile 使用 rewrite 来添加路径前缀,然后用 proxy 的 without 来移除同一前缀,那就是一个 rewrite 改造技巧,可以被消除。
你可能会发现新的 route 和 handle 指令在对高级路由逻辑进行更精细控制时非常有用。
root
未改变,但如果你的 root 路径以 / 开头,你需要添加一个 * 匹配器标记以将其与路径匹配器 区分开来。
- v1:
root /var/www - v2:
root * /var/www
因为在 v2 中它接受一个匹配器,这意味着你也可以根据请求改变站点根目录。
如果提供静态文件服务,记得添加file_server 指令,因为 Caddy 2 不再默认启用静态文件服务,而 v1 则默认启用。
status
v2 的对应为 respond,它也能写回响应体。
- v1:
status 404 /secrets/
- v2:
respond /secrets/* 404
templates
templates 指令的总体语法保持不变,但实际的模板动作/函数已不同并大幅改进。例如,模板现在能够包含文件、渲染 Markdown、发起内部子请求、解析 front matter 等等!
查看文档 了解新函数的细节。
- v1:
templates - v2:
templates
tls
tls 指令的基本原理未改变,例如指定你自己的证书和私钥:
- v1:
tls cert.pem key.pem - v2:
tls cert.pem key.pem
但 Caddy 的自动 HTTPS 逻辑确实发生了变化,请注意!
密码套件名称也已更改。
在 Caddy 2 中,一个常见配置是使用 tls internal,让其为非 localhost 且不是 IP 地址的开发主机名提供本地信任的证书。
大多数站点根本不需要使用该指令。
服务文件
我们建议在 Caddy 部署中使用我们官方的 systemd 服务文件之一。
如果你需要自定义服务文件,请以我们的为基础。它们经过了精心调优,背后有充分的理由!如有需要,务必对你的文件进行定制。
插件
为 v1 编写的插件不会自动兼容 v2。许多 v1 插件在 v2 中甚至不再需要。另一方面,v2 比 v1 更容易扩展且更灵活!
如果你想为 Caddy 2 编写插件,学习如何编写 Caddy 模块。
使用插件构建 Caddy 2
可以在交互式下载页面下载带插件的 Caddy 2。或者,你也可以使用 xcaddy 自行构建 Caddy,并选择包含哪些插件。xcaddy 会自动化 Caddy 的 main.go 文件中的指令。
获取帮助
如果你在让 Caddy 工作时遇到困难,请先查看我们网站上的文档。花时间尝试新事物并理解发生了什么——v2 在很多方面与 v1 很不同(但也非常熟悉)!
如果你仍然需要帮助,请加入我们的社区!你可能会发现帮助别人也是帮助自己的最好方式。