Caddy泛域名配置与自动化证书管理实践 📅 2026/8/17 2:08:48 1. Caddy 泛域名配置的核心思路第一次在 Caddy 里配置泛域名时我被它简洁的语法震惊了。相比 Nginx 复杂的正则表达式匹配Caddy 只需要一个简单的*.example.com就能捕获所有子域名请求。这种设计哲学贯穿 Caddy 的整个配置体系 - 用最少的配置做最多的事。泛域名配置的核心在于两个部分通配符证书的获取和请求路由的分发。Caddy 通过 ACME 协议自动从 Lets Encrypt 获取泛域名证书整个过程完全自动化。而在路由分发方面handle块就像交通警察根据不同的子域名将请求引导到对应的后端服务。重要提示使用泛域名证书前请确保你的 DNS 解析已经将*.example.com解析到服务器 IP否则证书申请会失败。2. 基础环境准备2.1 Caddy 安装与基本配置我推荐使用官方提供的安装脚本这是最可靠的方式sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install caddy安装完成后检查版本确保是最新的caddy version2.2 DNS 解析设置在域名服务商处你需要添加两条记录主域名 A 记录example.com - 服务器IP泛域名 A 记录*.example.com - 服务器IP我常用 Cloudflare 来管理 DNS它的传播速度很快。添加记录后可以用 dig 命令测试是否生效dig short test.example.com dig short anything.example.com3. 泛域名证书自动获取3.1 Caddyfile 基础配置创建一个最简单的 Caddyfile 来测试证书获取*.example.com { tls { dns cloudflare {env.CLOUDFLARE_API_TOKEN} } }这里有几个关键点*.example.com表示匹配所有子域名tls块配置证书获取方式dns挑战使用 Cloudflare API 进行验证注意将 {env.CLOUDFLARE_API_TOKEN} 替换为你的实际 API Token并确保该 Token 有足够的 DNS 编辑权限。3.2 证书申请实战启动 Caddy 服务export CLOUDFLARE_API_TOKENyour_token_here caddy start --config ./Caddyfile观察日志确认证书获取情况journalctl -u caddy -f你应该会看到类似这样的日志obtaining certificate for *.example.com waiting on DNS propagation for *.example.com successfully completed challenge for *.example.com4. 请求路由与 handle 块详解4.1 基础路由结构一个完整的泛域名路由配置通常长这样*.example.com { # 全局中间件和设置 encode gzip api host api.example.com handle api { reverse_proxy localhost:3000 } app host app.example.com handle app { root * /var/www/app file_server } handle { reverse_proxy localhost:8080 } }这个配置实现了api.example.com- 3000 端口的 API 服务app.example.com- 静态文件服务其他所有子域名 - 8080 端口的默认服务4.2 handle 块的高级用法handle 块可以嵌套使用实现更复杂的路由逻辑*.example.com { blog { host blog.example.com path /posts/* } handle blog { reverse_proxy localhost:2368 } blog-admin { host blog.example.com path /admin/* } handle blog-admin { reverse_proxy localhost:2369 { header_up Authorization {http.request.header.Authorization} } } }这个配置将blog.example.com/posts/*路由到 Ghost 的前端blog.example.com/admin/*路由到 Ghost 的后台并且为后台路由添加了认证头传递5. 生产环境最佳实践5.1 性能优化配置经过多次压力测试我总结出这些优化参数*.example.com { # 连接优化 reverse_proxy localhost:3000 { transport http { dial_timeout 10s keepalive 30s } lb_policy least_conn } # 缓存策略 header Cache-Control public, max-age3600 # 压缩设置 encode zstd gzip }5.2 安全加固措施安全配置不容忽视*.example.com { # 安全头 header { X-XSS-Protection 1; modeblock X-Frame-Options SAMEORIGIN Content-Security-Policy default-src self } # 请求限制 brute path /login handle brute { rate_limit 10r/1m 100r/1h { key {http.request.remote.host} } reverse_proxy localhost:3000 } }6. 常见问题排查6.1 证书申请失败问题现象日志显示 DNS challenge failed排查步骤检查 DNS 解析是否生效确认 API Token 权限足够测试 DNS 传播dig trace _acme-challenge.example.com TXT6.2 路由不生效问题现象请求没有被正确路由到后端排查方法检查 Caddy 调试日志caddy validate --config ./Caddyfile --adapter caddyfile确认 handle 块的匹配条件是否正确测试路由匹配curl -H Host: test.example.com http://localhost7. 进阶技巧与扩展7.1 动态子域名处理对于需要动态创建子域名的场景可以使用 Caddy 的handle_path*.example.com { handle_path /subdomain/* { uri strip_prefix /subdomain rewrite * /{path} dynamic host {http.request.host} reverse_proxy http://{http.request.host}.internal:8080 } }这个配置允许通过/subdomain/xxx访问xxx.example.com的内容。7.2 多租户支持使用 Caddy 的模板功能实现多租户*.example.com { tenant host ~^(?Ptenant[a-z0-9-])\.example\.com$ handle tenant { reverse_proxy http://{http.request.host}:8080 { notFound status 404 handle_response notFound { rewrite * /{tenant}/404.html file_server } } } }这个配置会自动将tenant1.example.com路由到对应的租户服务。