2114 字
11 分钟
Caddy 最佳实践与演进史

从历史看 Caddy 的野心#

  • 2015 年:Matt Holt 发布 Caddy 1.0 Beta,定位“自动 HTTPS 的现代 Web 服务器”。彼时主流仍是 Nginx/Apache 人工申领证书,Caddy 首次将 Let’s Encrypt ACME 流程写入默认行为,HTTP/2 默认开启。
  • 2016 年:引入 Caddyfile 配置语法,被称为“Go 版 Nginx”。社区围绕插件(proxy, markdown, git 等)快速扩展。
  • 2017 年:Caddy 0.10 起将多租户、TLS On-Demand、自动 HTTP->HTTPS 重定向等能力放入核心。官方尝试商业化授权,引发争议后在 2018 年改为 Apache-2.0 + 商业增值模式(Certified Caddy)。
  • 2020 年:Caddy 2 GA,底层完全重写为模块化框架(多称“xcaddy 生态”),引入 Admin API、JSON 配置、无锁热加载。官方成立 Light Code Labs,提供企业支持。
  • 2022 年以后:默认支持 HTTP/3、自动 OCSP Stapling、Zero-downtime Reload;与 Kubernetes、Docker、Nomad、Consul 等集成插件生态完善。

对比 Nginx 从“高性能 Web 服务器”进化而来,Caddy 一开始便围绕“安全默认值、自动化”设计,目标是成为现代分发层的“操作系统”。

为什么在 2025 年仍然推荐 Caddy#

  1. 自动 HTTPS & TLS 生命周期托管:证书申请、续期、失效检测、OCSP Stapling 全自动。对多域名、Wildcard、On-Demand TLS(多租户 SaaS)极其友好。
  2. 默认安全:HTTP/2/HTTP/3、Strict-Transport-Security、自动重定向、合理的 Cipher Suite 默认值,大幅降低安全配置错误的风险。
  3. 配置友好Caddyfile 上手快,caddy fmt 保持一致性;热加载无需重启。需要时可转换为 JSON,通过 Admin API 动态修改,适合“声明式 + 程序化”双模式。
  4. 模块化架构:任何功能(服务器、路由、TLS、日志、存储、认证)都是插件,可用 xcaddy 定制镜像。灵活程度远超 Nginx/Envoy 传统模块。
  5. Go 实现,资源占用轻:二进制单文件,无外部依赖,容器镜像可做到 < 50MB。相比 Java 生态(如 Spring Gateway)启动速度快几倍。
  6. 原生 HTTP/3 & QUIC:不依赖 OpenSSL,直接使用 Go 标准库 QUIC 实现;对移动端、弱网场景优化明显。
  7. 强大的反向代理能力:支持请求匹配(主机、路径、Header、Query)、重写、负载均衡、熔断、健康检查、缓存、CORS、速率限制。
  8. 企业级扩展:商业版提供集中式证书管理、SAML/LDAP 认证、Metrics/Tracing 集成;社区版亦支持 OpenTelemetry、Prometheus。

核心架构解剖#

Caddy (Process)
├── Admin API (REST/Unix Socket)
├── Modules (caddyserver.com/docs/modules/)
│   ├── HTTP Server (caddyhttp)
│   │   ├── Routes, Matchers, Handlers
│   │   └── Reverse Proxy (caddyhttp/reverseproxy)
│   ├── TLS (caddytls)
│   ├── Logging (caddy.logging)
│   ├── Storage (certificate store: file system, Consul, etcd…)
│   └── Apps (HTTP、TLS、PKI、DNS 等)
└── Config Manager
    ├── Caddyfile
    ├── JSON (REST PUT/POST)
    └── Autoload (watch config changes)
  • 模块化设计:Caddy 2 一切皆模块,HTTP Server 是 apps.http 模块之一。加载配置后通过 dependency graph 构建 pipeline。
  • Admin API:默认监听 :2019(或 Unix socket),支持 POST /load, POST /config/apps/http/servers/srv0/routes 动态更新。
  • 证书存储:默认 ~/.local/share/caddy, 可切换为 S3、Consul、Redis 等远程存储,使多副本共享证书。
  • 热重载:变更配置时先启动新实例,通过引用计数停掉旧实例,无需中断现有连接。

快速上手:安装与基础配置#

安装方式#

# Linux 官方脚本(含 systemd 服务)
curl -sfL https://get.caddyserver.com | bash -s personal

# Homebrew
brew install caddy

# Docker
docker run -p 80:80 -p 443:443 \
  -v $PWD/Caddyfile:/etc/caddy/Caddyfile \
  caddy:2-alpine

# 自定义模块
xcaddy build v2.8.4 \
  --with github.com/caddy-dns/cloudflare \
  --with github.com/mholt/caddy-dynamicdns

Ubuntu 环境部署示例#

官方推荐通过 Cloudsmith 仓库安装,以便跟随稳定版更新:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo tee /usr/share/keyrings/caddy-stable-archive-keyring.gpg > /dev/null
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 以 caddy 系统用户运行并注册为 systemd 服务:

sudo systemctl status caddy
sudo systemctl enable --now caddy

反向代理 Node.js(端口 3000)示例:

  1. 编辑 /etc/caddy/Caddyfile

    example.com {
      reverse_proxy 127.0.0.1:3000
      encode zstd gzip
      header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
      }
    }
    
  2. 确认 DNS A/AAAA 记录指向服务器,放行 80/443 端口(如使用 UFW:sudo ufw allow 80,443/tcp)。

  3. 使用内置格式化与配置校验:

    sudo caddy fmt --overwrite /etc/caddy/Caddyfile
    sudo caddy validate --config /etc/caddy/Caddyfile
    
  4. 热重载并查看日志:

    sudo systemctl reload caddy
    journalctl -u caddy -f
    

首次访问 https://example.com 即可看到自动颁发的 Let’s Encrypt 证书,后续续期与 OCSP 由 Caddy 自行处理。若需要自定义证书目录,可在 /etc/caddy/Caddyfile 顶部使用全局段 storage file_system { root /var/lib/caddy } 或挂载远程存储。

Hello Reverse Proxy#

Caddyfile:

example.com {
  reverse_proxy 127.0.0.1:3000
}

执行:

caddy run --config Caddyfile --watch

打开浏览器访问 https://example.com 即自动申请证书并转发请求。

进阶配置精要#

多域名站点 + 自动重定向#

{
  email admin@example.com
  auto_https disable_redirects # 自定义重定向
}

example.com, www.example.com {
  @httpScheme protocol http
  handle @httpScheme {
    redir https://{host}{uri} permanent
  }

  encode zstd gzip

  reverse_proxy {
    to app1:8080 app2:8080
    lb_policy least_conn
    health_interval 20s
    health_timeout 5s
  }

  log {
    output file /var/log/caddy/example.log {
      roll_size 20MB
      roll_keep 7
    }
    format json
  }
}

动态配置(Admin API)#

curl -X POST http://localhost:2019/load -H "Content-Type: application/json" -d @config.json

配置片段(JSON):

{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [":443"],
          "routes": [
            {
              "match": [{ "host": ["api.example.com"] }],
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "upstreams": [{ "dial": "api:9000" }]
                }
              ]
            }
          ]
        }
      }
    }
  }
}

TLS 自动化选项#

*.tenant.example.com {
  tls {
    on_demand            # 客户首次访问时动态申请证书
    issuer acme {
      email tls@example.com
      dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }
    renew_before 720h    # 提前 30 天续期
  }

  reverse_proxy {host}.backend.internal:8443
}

On-Demand TLS 需配合访问控制(例如 tls.on_demand ask https://tenant-registry/api/check)避免被恶意滥用。

HTTP/3 与 QUIC 调优#

  • 默认开启 HTTP/3;如需关闭:auto_https disable_certs + servers { protocols { enable h3 disable h1 h2 } }
  • 对移动端可增加 header Response add Alt-Svc "h3=\":443\"; ma=86400"

缓存与边缘处理#

https://assets.example.com {
  root * /var/www/assets
  file_server

  header {
    Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Cache-Control "public, max-age=31536000, immutable"
  }

  handle_path /api/* {
    reverse_proxy backend:8080
    header_up X-Forwarded-Proto {scheme}
    header_up X-Request-Id {http.request.id}
  }
}

与 Nginx / Traefik / Envoy 的对比#

特性CaddyNginxTraefikEnvoy
自动 HTTPS✅ 默认❌ 需 Certbot✅ Provider❌ 外部实现
配置体验Caddyfile/JSON/RESTnginx.confTOML/YAML/CRDYAML/ADS
动态配置Admin API需 reloadProvider/动态发现xDS
HTTP/3 支持内建稳定实验 (依赖 quic patch)实验
模块扩展Go 模块 xcaddy编译模块插件自定义 Filter
性能优秀 (Go, 多核友好)极佳 (C 基础)极佳 (C++)
学习曲线
适用场景Web 前端、SaaS、多租户老牌反向代理云原生 ingress微服务服务网格

Caddy 不追求取代所有场景,但在希望“快速上线、安全默认、自动化证书”的团队中胜率很高。

生产实践建议#

  • 版本管理:固定到 caddy:2.x.y,关注 Release Notes
  • 配置托管:将 Caddyfile 与 JSON 配置放入 Git,使用 caddy fmt + Pre-commit 保持规范。
  • 日志与监控
    • log { format json } 便于 ELK/ClickHouse 分析。
    • 启用 metrics 模块,或集成 Prometheus Exporter。
    • 利用 admin metrics 暴露运行指标。
  • 证书持久化:在容器部署时挂载 /data,或使用远程存储模块避免容器重建导致重新申请证书。
  • 安全
    • 限制 Admin API 仅监听 Unix socket 或内网地址。
    • 对 on-demand TLS 设置 ask 校验接口。
    • 加固 auto_https disable_redirects 场景中的手动重定向链,防止开放端口被利用。
  • 高可用:多实例部署时共享证书存储,或通过 caddy.cluster.consul 模块同步状态。
  • 性能调优
    • 合理设置 reverse_proxymax_requestsmax_conns
    • 在高并发场景打开 buffers 和响应压缩。
    • 使用 layer4 模块处理 TCP/UDP(数据库代理)。

典型落地场景#

  1. 个人/团队博客:一套 Caddyfile 管理多个站点,Let’s Encrypt 自动续期免维护。
  2. SaaS 多租户域名:On-Demand TLS + DNS Provider 模块 + 动态 upstream。
  3. 微服务网关:配合 Consul/Etcd 服务发现模块、JWT 验证、速率限制。
  4. 静态资源/CDN 边缘节点:结合 Rclone/S3 同步,利用 HTTP/3 提升移动端体验。
  5. DevOps 内部工具:通过 trusted_proxies、Basic Auth/OAuth 插件保护内部管理端。

学习路线与工具#

  • caddy helpcaddy list-modules:快速了解已安装模块。
  • caddy fmt:格式化 Caddyfile。
  • caddy adapt --config Caddyfile --adapter caddyfile --pretty:将 Caddyfile 转换为 JSON,便于自动化。
  • xcaddy 构建带自定义模块的二进制。
  • 官方文档 + Caddy Community Forum
  • 深入阅读 Matt Holt 的博客与演讲,如 “Caddy 2: The Ultimate Modern Web Server”。

结语#

十年间,Caddy 从“自动 HTTPS 小众服务器”成长为成熟的边缘分发平台。它在默认安全、配置体验、动态化方面的设计理念,与现代应用架构的诉求高度契合。对追求“少折腾、快上线、易维护”的团队而言,Caddy 不只是 Nginx 的替代品,更是一次重新思考反向代理和 TLS 生命周期管理的机会。

掌握本文提到的历史视角、优势与实战经验,你可以更有底气地在项目中引入 Caddy,并构建稳定可靠的应用交付层。

Caddy 最佳实践与演进史
https://bangwu.top/posts/caddy/
作者
棒无
发布于
2025-11-05
许可协议
CC BY-NC-SA 4.0