文档
一个 项目

升级指南

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 基本相同,但更强大;指令有变化。

步骤

  1. 通过我们的入门教程熟悉 Caddy 2。
  2. 如果还没做第 1 步,请务必先做。真的——我们再强调一遍,至少要会用 Caddy 2。(其实更有趣!)
  3. 用下文的指南迁移你的 caddy 命令。
  4. 用下文的指南迁移你的 Caddyfile。
  5. 在本地或预发布环境测试新配置。
  6. 测试、测试、再测试
  7. 部署并享受吧!

HTTPS 与端口

Caddy 的默认端口不再是 :2015。Caddy 2 的默认端口是 :443,如果没有主机名/IP,则为 :80。你可以随时在配置中自定义端口。

Caddy 2 的默认协议_始终_是 HTTPS(只要有主机名或 IP)。这与 Caddy 1 不同,Caddy 1 只有看起来像公网域名才默认用 HTTPS。现在,_每个_站点都用 HTTPS(除非你通过显式指定端口 :80http:// 禁用)。

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(但目前没有浏览器支持)。

基本没变,但 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_upstreamheader_downstream 分别变为 header_upheader_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.