升级指南
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 的默认协议_始终_是 HTTPS(只要有主机名或 IP)。这与 Caddy 1 不同,Caddy 1 只有看起来像公网域名才默认用 HTTPS。现在,_每个_站点都用 HTTPS(除非你通过显式指定端口 :80
或 http://
禁用)。
IP 地址和 localhost 域名会由本地受信任的内嵌 CA签发证书。其他域名会用 ZeroSSL 或 Let's Encrypt。(这些都可配置。)
证书和 ACME 资源的存储结构已变。Caddy 2 可能会为你的网站重新获取证书;如果你有很多证书,可以手动迁移。详情见 #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/
这样的前缀,需要用/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。(你也可以输出到文件或网络 socket,详见 log
指令文档。)
默认日志为结构化 JSON 格式。如需兼容旧系统的 CLF 格式日志,可用 transform-encoder
插件。
proxy
v2 的等价指令是 reverse_proxy
。
子指令有变化,header_upstream
和 header_downstream
分别变为 header_up
和 header_down
;负载均衡相关子指令前缀为 lb_
。
One other significant difference is that the v2 proxy passes all incoming headers thru by default (including the Host
header) and sets the X-Forwarded-For
header. In other words, v1's "transparent" mode is basically the default in v2 (but if you need other headers like X-Real-IP you have to set those yourself). You can still override/customize the Host
header using the header_up
subdirective.
Websocket proxying "just works" in v2; there is no need to "enable" websockets like in v1.
The without
subdirective has been removed because rewrite hacks are no longer necessary in v2 thanks to improved matcher support.
- v1:
proxy / localhost:9005
- v2:
reverse_proxy localhost:9005
redir
Unchanged, except for a few details about the optional status code argument. Most configs won't need to make any changes.
- v1:
redir https://example.com{uri}
- v2:
redir https://example.com{uri}
rewrite
The semantics of request rewriting ("internal redirecting") has changed slightly. If you used a so-called "rewrite hack" in v1 as a way to match requests on something other than a simple path prefix, that is completely unnecessary in v2.
The new rewrite
directive is very simple but very powerful, as most of its complexity is handled by matchers in v2:
- v1:
rewrite {
if {>User-Agent} has mobile
to /mobile{uri}
}
- v2:
@mobile {
header User-Agent *mobile*
}
rewrite @mobile /mobile{uri}
Notice how we simply use Caddy 2's usual matcher tokens; it's no longer a special case for this directive.
Start by removing all rewrite hacks; turn them into named matchers instead. Evaluate each v1 rewrite
to see if it's really needed in v2. Hint: A v1 Caddyfile that uses rewrite
to add a path prefix and then proxy
with without
to remove that same prefix is a rewrite hack, and can be eliminated.
You may find the new route
and handle
directives useful for having greater control over advanced routing logic.
root
Unchanged, but if your root path starts with /
, you'll need to add a *
matcher token to distinguish it from a path matcher.
- v1:
root /var/www
- v2:
root * /var/www
Because it accepts a matcher in v2, this means you can also change the site root depending on the request.
Remember to add a file_server
directive if serving static files, since Caddy 2 does not assume this by default, whereas in v1 always had it enabled.
status
The v2 equivalent is respond
, which can also write a response body.
- v1:
status 404 /secrets/
- v2:
respond /secrets/* 404
templates
The overall syntax of the templates
directive is unchanged, but the actual template actions/functions are different and much improved. For example, templates are capable of including files, rendering markdown, making internal sub-requests, parsing front matter, and more!
See the docs for details about the new functions.
- v1:
templates
- v2:
templates
tls
The fundamentals of the tls
directive have not changed, for example specifying your own cert and key:
- v1:
tls cert.pem key.pem
- v2:
tls cert.pem key.pem
But Caddy's auto-HTTPS logic has changed, so be aware of that!
The cipher suite names have also changed.
A common configuration in Caddy 2 is to use tls internal
to have it serve a locally-trusted certificate for a dev hostname that isn't localhost
or an IP address.
Most sites will not need this directive at all.
Service files
We recommend using one of our official systemd service files for Caddy deployments.
If you need a custom service file, base it off of ours. They've been carefully tuned to what it is for good reasons! Be sure to customize yours if needed.
Plugins
Plugins written for v1 are not automatically compatible with v2. Many v1 plugins are not even needed in v2. On the other hand, v2 is way more easily extensible and flexible than v1!
If you want to write a plugin for Caddy 2, learn how to write a Caddy module.
Building Caddy 2 with plugins
Caddy 2 can be downloaded with plugins at the interactive download page. Alternatively, you can build Caddy yourself using xcaddy
and choose which plugins to include. xcaddy
automates the instructions in Caddy's main.go file.
Getting help
If you're struggling to get Caddy working, please take a look through our website for documentation first. Take time to try new things and understand what is going on - v2 is very different from v1 in a lot of ways (but it's also very familiar)!
If you still need assistance, please be a part of our community! You may find that helping others is the best way to help yourself, too.