Caddyfile 结构图解
Caddyfile 由全局选项块、可复用片段和站点块组成,通过匹配器与指令处理请求。
{ email you@yours.com acme_ca https://acme-staging-v02.api.letsencrypt.org/directory } (snippet) { # this is a reusable snippet } example.com { @post { method POST } reverse_proxy @post localhost:9001 localhost:9002 { lb_policy first } file_server /static import snippet } www.example.com { redir https://example.com{uri} import snippet }
Global options block
Snippet
Site block
Matcher definition
Option name
Option value
Comment
Site address
Directive
Matcher token
Argument
Subdirective
同时监听 80 和 443
Caddy 默认在启用自动 HTTPS 时就会监听 80 和 443。80 用于 ACME 挑战并自动重定向到 HTTPS。
# 默认行为:只需写域名,Caddy 自动监听 80 和 443 example.com { root * /var/www/html file_server }
手动显式配置两个端口:
# 80 端口:强制跳转 HTTPS :80 { redir https://{host}{uri} permanent } # 443 端口:正常提供服务,自动申请证书 example.com { root * /var/www/html file_server }
端口被占用? 可在全局块中修改默认端口:
http_port 8080 和 https_port 8443。
HTTP Basic Authentication
先用 caddy hash-password 生成 bcrypt 哈希,再在站点块中配置。
# 生成密码哈希 $ caddy hash-password --plaintext '你的密码' $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
example.com { basic_auth { admin $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx guest $2a$14$yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy } root * /var/www/html file_server }
版本差异:Caddy v2.8+ 使用
basic_auth,v2.0 ~ v2.7 使用 basicauth(无下划线)。
指定路径反向代理 + Basic Auth
用 handle 块把认证和反代限定在特定路径下,其他路径不受影响。
example.com { # 只处理 /api/* 路径 handle /api/* { basic_auth { admin $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } reverse_proxy localhost:9000 } # 其他路径走静态文件 handle { root * /var/www/html file_server } }
如果上游不希望看到 /api 前缀,改用 handle_path:
handle_path /api/* { basic_auth { admin $2a$14$xxxxxxxx... } reverse_proxy localhost:9000 }
/api/users 会被代理到上游的 /users,前缀被自动剥离。
多个路径共用同一反代配置
用命名匹配器一次性匹配多个路径,避免重复写多个 handle 块。
example.com { # 一个匹配器同时匹配多个路径 @backend path /api/* /v1/* /v2/* handle @backend { basic_auth { admin $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } reverse_proxy localhost:9000 } # 兜底:其他路径 handle { root * /var/www/html file_server } }
如果多个路径需要去前缀,且前缀不同,可以用 snippet 复用公共配置:
(protected_proxy) { basic_auth { admin $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } reverse_proxy localhost:9000 } example.com { handle_path /api/* { import protected_proxy } handle_path /v1/* { import protected_proxy } handle { file_server } }
无公网 IP:DNS-01 挑战
没有公网 IP 时,HTTP-01 挑战无法工作,改用 DNS-01 挑战即可正常签发证书。
# 1. 构建带 DNS 插件的 Caddy(以 Cloudflare 为例)
$ xcaddy build --with github.com/caddy-dns/cloudflare
{ email your-email@example.com acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN} } example.com { root * /var/www/html file_server }
也可以只在单个站点启用:
example.com { tls { dns cloudflare {env.CLOUDFLARE_API_TOKEN} } reverse_proxy localhost:8080 }
API Token 权限:Cloudflare 需要
Zone / Zone / Read 和 Zone / DNS / Edit。其他 DNS 提供商见 github.com/orgs/caddy-dns/repositories。
常用命令速查
修改配置后先验证语法,再平滑重载服务。
| 命令 | 说明 |
|---|---|
caddy validate --config /etc/caddy/Caddyfile |
校验配置文件语法 |
caddy adapt --config ./Caddyfile --pretty |
转换为 JSON 配置查看最终效果 |
caddy fmt --overwrite /etc/caddy/Caddyfile |
格式化 Caddyfile |
caddy hash-password --plaintext '密码' |
生成 Basic Auth 密码哈希 |
caddy run |
前台运行(调试用) |
caddy start |
后台运行 |
sudo systemctl reload caddy |
平滑重载(不中断连接) |
sudo systemctl status caddy |
查看运行状态 |
sudo ss -tlnp | grep caddy |
查看监听端口 |
推荐工作流:
caddy validate → systemctl reload caddy → systemctl status caddy