caddy配置
使用提示:
- 全局配置块必须位于 Caddyfile 的最顶部
- 全局配置块只能有一个
- 使用
caddy adapt命令验证配置,查看JSON配置 - 使用
caddy reload热重载配置 - 使用
caddy fmt --overwrite /etc/caddy/Caddyfile格式化配置文件 - 使用
caddy validate --config /etc/caddy/Caddyfile校验配置文件 - 生产环境建议设置 email、日志和合理的超时
使用*/etc/caddy/Caddyfile*管理
1.静态文件服务器
example.com {
root * /var/www
file_server
}
2.反向代理
- 代理所有请求
example.com {
reverse_proxy localhost:5000
}
- 代理以
/api/开头的请求,并为其他所有内容提供静态文件:
example.com {
root * /var/www
file_server
# 等价 example.com/api/aaa/bbb --> localhost:5000/api/aaa/bbb
reverse_proxy /api/* localhost:5000
}
- 路径匹配
handle和handle_path
example.com {
root * /var/www
file_server
# 等价 example.com/api/aaa/bbb --> localhost:5000/api/aaa/bbb
# 等价 reverse_proxy /api/* localhost:5000
handle /api/* {
reverse_proxy localhost:5000
}
# 等价 example.com/v1/aaa/bbb --> localhost:5000/aaa/bbb
handle_path /v1/* {
reverse_proxy localhost:5000
}
}
3.重定向到www.子域名
- 添加子域名www.
example.com {
redir https://www.example.com{uri}
}
www.example.com {
}
- 去掉子域名
www.example.com {
redir https://example.com{uri}
}
example.com {
}
4.尾随斜杠
你通常不需要自己进行配置;该file_server指令将通过 HTTP 重定向自动添加或删除请求中的尾部斜杠,具体取决于请求的资源是目录还是文件。
但是,如果需要,你仍然可以在配置中强制使用斜杠。有两种方法可以做到:内部或外部。
a.内部
这使用rewrite指令。Caddy将在内部重写URI以添加或删除尾部斜杠:
example.com
rewrite /add /add/
rewrite /remove/ /remove
使用重写,带有和不带有斜杠的请求将是相同的。
b.外部
这使用redir指令。Caddy 将要求浏览器更改 URI 以添加或删除尾部斜杠:
example.com
redir /add /add/
redir /remove/ /remove
使用重定向,客户端将不得不重新发出请求,为资源强制执行一个可接受的URI。
5.通配符证书
- 如果你需要使用相同的通配符证书为多个子域提供服务,处理它们的最佳方法是使用如下所示的Caddyfile,利用
handle指令和[host]匹配器:
*.example.com {
tls {
dns <provider_name> [<params...>]
}
@foo host foo.example.com
handle @foo {
respond "Foo!"
}
@bar host bar.example.com
handle @bar {
respond "Bar!"
}
# Fallback for otherwise unhandled domains
handle {
abort
}
}
阿里云泛域名配置示例,需要有插件dns.providers.alidns,通过指令caddy list-modules | grep dns查看
example.com, *.example.com {
tls {
# 使用阿里云插件
dns alidns {
access_key_id {env.ALICLOUD_ACCESS_KEY_ID}
access_key_secret {env.ALICLOUD_ACCESS_KEY_SECRET}
}
}
@hhh host hhh.example.com
handle @hhh {
root * /var/www
file_server
handle_path /apps/* {
reverse_proxy 127.0.0.1:8000
}
}
handle {
respond 404
}
}
腾讯云泛域名配置示例,需要有插件dns.providers.tencentcloud,通过指令caddy list-modules | grep dns查看
{
# ==================== 全局配置块 ====================
email example@qq.com
# acme_ca https://acme-v02.api.letsencrypt.org/directory
# 使用腾讯云插件
acme_dns tencentcloud {
secret_id {env.TENCENTCLOUD_SECRET_ID}
secret_key {env.TENCENTCLOUD_SECRET_KEY}
}
# 全局访问日志(可选,可按需关闭)
log {
format console
}
# log {
# output file /var/log/access.log
# format console
# }
}
example.com, *.example.com {
@root host example.com
@api host api.example.com
handle @root {
respond "example.com"
}
handle @api {
reverse_proxy localhost:3000
}
}
注意: 两种写法实际可以互相转化,阿里云写在了局部,腾讯云写在了全局,只是需要注意插件名称不一致,以及参数名称不一致
6.单页面应用(SPAs)
当一个网页进行自己的路由时,服务器可能会收到大量的请求,这些请求并不存在于服务器端,但只要提供单一的索引文件,这些请求就可以在客户端呈现。这样架构的Web应用程序被称为SPA,或单页应用程序。
其主要思想是让服务器“尝试文件”来查看请求的文件在服务器端是否存在,如果不存在,则返回到一个索引文件,客户端在其中进行路由(通常使用客户端JavaScript):try_files {path} /index.html
最基本的SPA配置通常是这样的:
example.com
root * /path/to/site
try_files {path} /index.html
file_server
# 等价于
example.com {
root * /path/to/site
try_files {path} /index.html
file_server
}
如果你的SPA与API或其他仅在服务器端使用的端点相结合,你会想要使用handle块来专门处理它们:
example.com
handle /api/* {
reverse_proxy backend:8000
}
handle {
root * /path/to/site
try_files {path} /index.html
file_server
}
7.负载均衡
- 最简点的轮询,默认策略是 random + least_conn 随机+最少连接数
example.com {
reverse_proxy localhost:8080 localhost:8081 localhost:8082
}
- 指定策略(轮询,随机,最少连接数,权重)
example.com {
reverse_proxy {
to localhost:8080 localhost:8081 localhost:8082
# 轮询
lb_policy round_robin
# 随机
# lb_policy random
# 最少连接数
# lb_policy least_conn
}
}
example1.com{
reverse_proxy {
to localhost:8080 localhost:8081 localhost:8082
# 权重 5 2 1
lb_policy weighted_round_robin 5 2 1
}
}
- 健康检查
example.com {
reverse_proxy {
to localhost:8080 localhost:8081 localhost:8082
# 轮询
lb_policy round_robin
# 健康检查 (每 10 秒检测,失败ip后续将从连接池中移除,直到后续成功了,再添加到连接池中)
health_uri /health
health_interval 10s
health_timeout 3s
}
}
8.设置基础认证(basic_auth)
- 通过用户名:
admin密码:不是明文,而是 bcrypt 哈希访问
example.com {
basic_auth {
# xxx 加密后的密码字符串 $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxx
admin xxx
}
reverse_proxy localhost:5000
}
- 通过caddy生成加密密码字符串
# 输出结果:$2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxx
caddy hash-password --plaintext "明文密码"
# 通过docker部署
docker exec -it <container_name> /bin/sh caddy hash-password --plaintext "123456"
- 只保护某个路径
/admin/*
example.com {
handle /admin/* {
basic_auth {
# xxx 加密后的密码字符串 $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxx
admin xxx
}
root * /var/www
file_server
}
reverse_proxy localhost:5000
}
全局配置块(位于最开头)
最多只能有一个,而且必须是Caddyfile的第一个块。
# ====================================================================
# Caddy 全局选项配置文件 - 详细注释版
# ====================================================================
# 这是 Caddy 的全局配置块,必须位于 Caddyfile 的最顶部
# 全局配置块只能有一个,且必须是第一个块
# ====================================================================
{
# ================================================================
# 常规选项 (General Options)
# ================================================================
# debug
# 启用调试模式,将日志级别设置为 DEBUG
# - 用于故障排查,会输出大量详细信息
# - 生产环境中会产生大量日志,不建议长期启用
# - 在社区寻求帮助前建议先启用此选项
debug
# http_port <port>
# 服务器用于 HTTP 的端口(默认:80)
# - 仅供 Caddy 内部使用,不会改变客户端访问的端口
# - 主要用于自动 HTTPS 重定向等内部逻辑
# 示例:http_port 8080
http_port <port>
# https_port <port>
# 服务器用于 HTTPS 的端口(默认:443)
# - 仅供 Caddy 内部使用,不会改变客户端访问的端口
# - 用于确定 TLS 监听端口
# 示例:https_port 8443
https_port <port>
# order <dir1> first|last|[before|after <dir2>]
# 定义 HTTP 处理指令的执行顺序
# - HTTP 处理器按链式顺序执行,正确的顺序很重要
# - 标准指令有预定义顺序,但第三方模块需要手动指定
# - 响应流是向上处理的(从后往前),而不是向下
# 示例:order replace after encode # 让 replace-response 在 encode 之后执行
order <dir1> first|last|[before|after <dir2>]
# storage <module_name> { ... }
# 配置 Caddy 的存储机制(默认:file_system)
# - 用于存储证书、密钥等持久化数据
# - 多实例部署时需要使用共享存储(如 Redis、Consul 等)
# - 确保所有实例使用相同的证书和密钥
# 示例:
# storage file_system /var/lib/caddy
# storage redis {
# host localhost:6379
# }
storage <module_name> {
<options...>
}
# storage_clean_interval <duration>
# 存储清理间隔(默认:24h)
# - 定期扫描存储以删除过期资源(如过期证书)
# - 对大型部署建议设置更长间隔,减少存储读取压力
# - 首次启动时总会执行清理
# 示例:storage_clean_interval 48h
storage_clean_interval <duration>
# admin off|<addr> { ... }
# 配置管理 API 端点(默认:localhost:2019)
# - 设置为 off 则完全禁用管理端点
# - 禁用后无法在不重启的情况下更改配置
# - origins:允许连接的远程地址白名单
# - enforce_origin:强制验证 Origin 请求头
# 示例:
# admin off # 禁用管理 API
# admin 127.0.0.1:2019 # 仅本地访问
# admin :2019 { # 允许远程访问
# origins https://admin.example.com
# enforce_origin
# }
admin off|<addr> {
origins <origins...> # 允许的来源列表
enforce_origin # 启用 Origin 头验证
}
# log [name] { ... }
# 配置日志记录器
# - 不指定名称则配置默认日志器
# - 可多次使用以配置不同的日志器
# - output:日志输出位置(stdout、stderr、文件等)
# - format:日志格式(console、json 等)
# - level:最低日志级别(DEBUG、INFO、WARN、ERROR)
# - include:包含特定命名空间
# - exclude:排除特定命名空间
# 示例:
# log {
# output file /var/log/caddy/access.log
# format json
# level INFO
# }
log [name] {
output <writer_module> ... # 输出模块(file、net、stdout等)
format <encoder_module> ... # 编码模块(json、console等)
level <level> # 日志级别
include <namespaces...> # 包含的命名空间
exclude <namespaces...> # 排除的命名空间
}
# grace_period <duration>
# 配置重载时的优雅关闭时间(默认:无限制)
# - 配置重载期间,旧服务器会等待此时间让请求完成
# - 超时后会强制终止以释放资源
# - 建议设置合理值以避免长时间挂起的请求阻塞重载
# 示例:grace_period 10s
grace_period <duration>
# ================================================================
# TLS 选项 (TLS Options)
# ================================================================
# auto_https off|disable_redirects|ignore_loaded_certs
# 配置自动 HTTPS 行为
# - off:完全禁用自动 HTTPS
# - disable_redirects:仅禁用 HTTP 到 HTTPS 的重定向
# - ignore_loaded_certs:即使手动加载了证书也自动获取新证书
# 默认情况下自动 HTTPS 是启用的
auto_https off|disable_redirects|ignore_loaded_certs
# email <yours>
# 您的电子邮件地址
# - 用于创建 ACME 账户(Let's Encrypt 等)
# - 证书出现问题时 CA 会发送通知
# - 强烈建议设置
# 示例:email admin@example.com
email <yours>
# default_sni <name>
# 当客户端不发送 SNI 时的默认 TLS 服务器名称
# - SNI(Server Name Indication)用于在单个 IP 上托管多个 TLS 站点
# - 某些老旧客户端不支持 SNI
# 示例:default_sni example.com
default_sni <name>
# local_certs
# 使所有证书默认在本地颁发(内部 CA)
# - 不使用公共 CA(如 Let's Encrypt)
# - 适用于开发和测试环境
# - 需要信任本地 CA 根证书
local_certs
# skip_install_trust
# 跳过将本地 CA 根证书安装到系统信任库
# - 适用于容器化环境或无法修改系统信任库的情况
# - 使用 local_certs 时可能需要手动信任证书
skip_install_trust
# acme_ca <directory_url>
# 指定 ACME CA 的目录 URL
# - 默认使用 ZeroSSL 和 Let's Encrypt 的生产端点
# - 测试时建议使用 Let's Encrypt 的暂存环境
# 示例:
# acme_ca https://acme-staging-v02.api.letsencrypt.org/directory # Let's Encrypt 暂存
# acme_ca https://acme-v02.api.letsencrypt.org/directory # Let's Encrypt 生产
acme_ca <directory_url>
# acme_ca_root <pem_file>
# 指定 ACME CA 的受信任根证书(PEM 格式)
# - 当 CA 根证书不在系统信任库中时使用
# - 用于私有 CA 或自定义 ACME 服务器
# 示例:acme_ca_root /path/to/ca-root.pem
acme_ca_root <pem_file>
# acme_eab <key_id> <mac_key>
# 配置外部账户绑定(External Account Binding)
# - 某些 CA 需要 EAB 来关联现有账户
# - key_id 和 mac_key 由 CA 提供
# 示例:acme_eab kid_xxxxx hmac_key_xxxxx
acme_eab <key_id> <mac_key>
# acme_dns <provider> ...
# 配置 ACME DNS 质询提供商
# - 用于 DNS-01 质询验证域名所有权
# - 支持各种 DNS 提供商(Cloudflare、Route53 等)
# - 通配符证书必须使用 DNS 质询
# 示例:
# acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
# acme_dns route53 {
# access_key_id {env.AWS_ACCESS_KEY_ID}
# secret_access_key {env.AWS_SECRET_ACCESS_KEY}
# }
acme_dns <provider> ...
# on_demand_tls { ... }
# 配置按需 TLS(On-Demand TLS)
# - 仅配置但不启用,需要在站点配置中启用
# - ask:询问端点是否允许为某个域名获取证书
# - interval 和 burst:限流配置,防止滥用
# - 生产环境强烈建议配置以防止滥用
# 示例:
# on_demand_tls {
# ask https://api.example.com/check-domain
# interval 2m
# burst 5
# }
on_demand_tls {
ask <endpoint> # 验证端点,返回 200 则允许
interval <duration> # 限流时间窗口
burst <n> # 时间窗口内允许的最大操作数
}
# key_type ed25519|p256|p384|rsa2048|rsa4096
# 指定生成 TLS 证书的密钥类型(默认:根据 CA 要求)
# - ed25519:最快、最小、最安全(推荐,但某些老旧客户端不支持)
# - p256/p384:ECDSA,较小、较快
# - rsa2048/rsa4096:RSA,兼容性最好但较大、较慢
# 示例:key_type ed25519
key_type ed25519|p256|p384|rsa2048|rsa4096
# cert_issuer <name> ...
# 定义 TLS 证书颁发者
# - 可指定多个颁发者,按定义顺序尝试
# - 支持 ACME、内部 CA、ZeroSSL 等
# 示例:
# cert_issuer acme {
# dir https://acme-v02.api.letsencrypt.org/directory
# }
# cert_issuer internal
cert_issuer <name> ...
# ocsp_stapling off
# 禁用 OCSP 装订(默认启用)
# - OCSP 用于检查证书吊销状态
# - 防火墙阻止 OCSP 响应器时可禁用
# - 禁用可能影响某些客户端的安全检查
ocsp_stapling off
# preferred_chains [smallest] { ... }
# 当 CA 提供多个证书链时,指定首选链
# - smallest:选择字节数最少的链
# - root_common_name:根据根证书的通用名称选择
# - any_common_name:根据链中任意颁发者的通用名称选择
# 示例:
# preferred_chains smallest
# preferred_chains {
# root_common_name "ISRG Root X1" # Let's Encrypt 的短链
# }
preferred_chains [smallest] {
root_common_name <common_names...> # 根证书通用名称列表
any_common_name <common_names...> # 任意颁发者通用名称列表
}
# ================================================================
# 服务器选项 (Server Options)
# ================================================================
# 配置跨越多个站点的 HTTP 服务器设置
# 可多次指定,使用不同的 listener_address 为每个服务器单独配置
# 省略 listener_address 则应用于所有剩余服务器
# servers [<listener_address>] { ... }
# 配置 HTTP 服务器
# - listener_address:监听地址(如 :443、:80、192.168.1.1:8080)
# - 可针对不同端口配置不同选项
# 示例:
# servers :443 {
# protocol { experimental_http3 }
# }
# servers :80 {
# protocol { allow_h2c }
# }
servers [<listener_address>] {
# listener_wrappers { ... }
# 配置监听器包装器,可修改底层监听器行为
# - 按指定顺序应用
# - tls 包装器标记 TLS 握手位置
# - 常用于添加代理协议支持等
# 示例:
# listener_wrappers {
# proxy_protocol {
# timeout 2s
# allow 192.168.1.0/24
# }
# tls
# }
listener_wrappers {
<listener_wrappers...>
}
# timeouts { ... }
# 配置各种超时设置
timeouts {
# read_body <duration>
# 从客户端读取请求体的超时时间(默认:无超时)
# - 设置短超时可防止慢速攻击
# - 但也可能影响合法的慢速上传
# 示例:read_body 10s
read_body <duration>
# read_header <duration>
# 从客户端读取请求头的超时时间(默认:无超时)
# - 防止慢速请求头攻击
# 示例:read_header 5s
read_header <duration>
# write <duration>
# 向客户端写入响应的超时时间(默认:无超时)
# - 提供大文件时设置过短可能影响慢速客户端
# 示例:write 30s
write <duration>
# idle <duration>
# Keep-Alive 连接的空闲超时(默认:5m)
# - 等待下一个请求的最长时间
# - 帮助避免资源耗尽
# 示例:idle 2m
idle <duration>
}
# max_header_size <size>
# HTTP 请求头的最大解析大小
# - 支持人类可读格式(如 1MB、10KB)
# - 防止过大请求头消耗内存
# 示例:max_header_size 1MB
max_header_size <size>
# protocol { ... }
# 配置 HTTP 协议选项
# ⚠️ 注意:此选项自 2022-08 起已弃用
protocol {
# allow_h2c
# 启用 H2C(HTTP/2 明文,无 TLS 的 HTTP/2)
# - 仅适用于未加密的 HTTP 监听器
# - 客户端支持极少,谨慎使用
# - 与大多数其他服务器选项不兼容
# ⚠️ 实验性功能,可能更改或删除
allow_h2c
# experimental_http3
# 启用实验性 HTTP/3 支持(基于 QUIC)
# - HTTP/3 规范尚未完全稳定
# - 客户端支持有限
# - 此选项将来会消失
# ⚠️ 不受兼容性承诺约束
experimental_http3
# strict_sni_host
# 要求请求的 Host 头与 TLS SNI 匹配
# - 使用 TLS 客户端身份验证时通常需要
# - 增强安全性,防止 Host 头攻击
strict_sni_host
}
}
}
# ====================================================================
# 配置文件结束
#
# 使用提示:
# 1. 全局配置块必须位于 Caddyfile 的最顶部
# 2. 全局配置块只能有一个
# 3. 使用 `caddy adapt` 命令验证配置,查看JSON配置
# 4. 使用 `caddy reload` 热重载配置
# 5. 使用 `caddy fmt --overwrite /etc/caddy/Caddyfile` 格式化配置文件
# 6. 使用 `caddy validate --config /etc/caddy/Caddyfile` 校验配置文件
# 7. 生产环境建议设置 email、日志和合理的超时
# ====================================================================