最后更新于:2026年07月
⚠️ 重要声明:本文仅从技术研究角度介绍 Web 服务器与反向代理的工程实现。请在遵守当地法律法规的前提下阅读和应用本文内容。

如果你用过 Nginx 配置 HTTPS,一定经历过这些痛苦:安装 certbot、申请证书、配置 cron 自动续期、手写一大段 ssl_certificate 配置、调试 protoco/cipher suite 参数……而 Caddy 把这一切简化为:写一个域名,剩下的全自动。
Caddy 是用 Go 语言编写的现代 Web 服务器,最大的特点是内置自动 HTTPS——它会自动向 Let’s Encrypt 申请证书、自动续期、自动重定向 HTTP 到 HTTPS,你甚至不需要知道 certbot 是什么。除了自动证书,Caddy 的 Caddyfile 配置语法极其简洁,原生支持 HTTP/3、WebSocket、gRPC 代理,配置文件热重载,是 Nginx 的现代替代方案。
本文将从安装、配置、反向代理、WebSocket 代理、多站点、安全加固到 Docker 部署,全面拆解 Caddy v2 的生产级用法。
🧭 第一部分:Caddy 是什么?为什么选择 Caddy?
1.1 Caddy 核心特性
┌──────────────────────────────────────────────────────────┐
│ Caddy v2 核心特性 │
│ │
│ 🔒 自动 HTTPS │
│ ├── 自动向 Let's Encrypt / ZeroSSL 申请证书 │
│ ├── 自动续期(到期前 1/3 时间) │
│ ├── 自动 HTTP → HTTPS 重定向 │
│ └── 自动 OCSP stapling │
│ │
│ 📝 极简配置 │
│ ├── Caddyfile 语法(人类可读) │
│ ├── 3 行配置 = 一个 HTTPS 网站 │
│ ├── 配置热重载(不停机) │
│ └── JSON API(程序化配置) │
│ │
│ ⚡ 现代协议 │
│ ├── 原生 HTTP/3 (QUIC) 支持 │
│ ├── 原生 WebSocket 代理 │
│ ├── 原生 gRPC 代理 │
│ ├── 原生 HTTP/2 │
│ └── 自动 Brotli / Gzip 压缩 │
│ │
│ 🔧 生产就绪 │
│ ├── 单二进制文件(无依赖) │
│ ├── Go 语言编写(内存安全) │
│ ├── 内置健康检查 │
│ ├── 负载均衡 │
│ └── 丰富的插件生态 │
└──────────────────────────────────────────────────────────┘1.2 Caddy vs Nginx vs Traefik 对比
┌──────────────────────────────────────────────────────────────┐
│ Caddy vs Nginx vs Traefik 全面对比 │
├──────────────┬──────────┬──────────┬───────────────────────┤
│ 特性 │ Caddy │ Nginx │ Traefik │
├──────────────┼──────────┼──────────┼───────────────────────┤
│ 自动 HTTPS │ ✅ 内置 │ ❌ 需certbot│ ✅ 内置 │
│ 配置复杂度 │ ⭐ 极简 │ ⭐⭐⭐ 复杂│ ⭐⭐ 中等 │
│ 配置格式 │ Caddyfile│ nginx.conf│ YAML/TOML │
│ HTTP/3 │ ✅ 原生 │ ⚠️ 需编译 │ ✅ 原生 │
│ WebSocket │ ✅ 原生 │ ⚠️ 需配置 │ ✅ 原生 │
│ 热重载 │ ✅ caddy │ ⚠️ nginx │ ✅ 自动 │
│ │ reload │ -s reload│ │
│ 性能 │ 高 │ 极高 │ 中高 │
│ 内存占用 │ ~30MB │ ~5MB │ ~50MB+ │
│ 单二进制 │ ✅ │ ❌ │ ❌ │
│ 插件生态 │ 中等 │ 丰富 │ 丰富 │
│ Docker 集成 │ ✅ │ ✅ │ ✅✅ 最佳 │
│ 学习曲线 │ 平缓 │ 陡峭 │ 中等 │
│ 适用场景 │ 中小型/ │ 大型/高并发│ 容器化/ │
│ │ 自托管 │ 生产环境 │ 微服务 │
└──────────────┴──────────┴──────────┴───────────────────────┘1.3 什么时候选 Caddy?
✅ 推荐使用 Caddy 的场景:
- 个人博客 / 作品集 / 静态网站
- 自托管服务(Nextcloud, Gitea, Vaultwarden 等)
- 反向代理后端 API 服务
- 代理协议前端(V2Ray/Xray WebSocket, Trojan TLS)
- 内网穿透前端(FRP + Caddy HTTPS)
- 快速原型 / 开发环境
- 不想折腾证书管理的运维场景
❌ 不推荐使用 Caddy 的场景:
- 超高并发(10万+ QPS)→ 选 Nginx
- 复杂的流量路由规则 → 选 Nginx/Traefik
- 纯容器化微服务架构 → 选 Traefik
- 需要 Lua 扩展 → 选 Nginx + OpenResty
- 需要极致内存优化(嵌入式设备)→ 选 Nginx📦 第二部分:安装 Caddy
2.1 方式一:官方安装(推荐)
# Ubuntu / Debian
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
# CentOS / RHEL / Fedora
sudo dnf install -y 'dnf-command(copr)'
sudo dnf copr enable @caddy/caddy
sudo dnf install -y caddy
# 验证安装
caddy version
# 输出示例:v2.8.4 h1:... 2.2 方式二:Docker 安装
# 拉取官方镜像
docker pull caddy:2.8
# 快速启动
docker run -d --name caddy \
-p 80:80 \
-p 443:443 \
-p 443:443/udp \
-v /opt/caddy/Caddyfile:/etc/caddy/Caddyfile \
-v /opt/caddy/data:/data \
-v /opt/caddy/config:/config \
caddy:2.82.3 方式三:直接下载二进制
# 下载最新版(包含所有标准模块)
curl -L -o /usr/local/bin/caddy \
"https://github.com/caddyserver/caddy/releases/latest/download/caddy_$(curl -s https://api.github.com/repos/caddyserver/caddy/releases/latest | grep tag_name | cut -d '"' -f 4 | sed 's/v//')_linux_amd64.tar.gz" \
&& tar -xzf caddy*.tar.gz -C /usr/local/bin caddy \
&& rm caddy*.tar.gz
chmod +x /usr/local/bin/caddy
# 验证
caddy version2.4 方式四:从源码编译(带自定义插件)
# 安装 Go
sudo apt install -y golang-go
# 使用 xcaddy 编译(可以包含自定义插件)
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
# 编译带常用插件的 Caddy
xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/caddyserver/replace-response \
--with github.com/mholt/caddy-webdav \
--output /usr/local/bin/caddy
# 验证插件
caddy list-modules | grep -E "cloudflare|webdav"2.5 systemd 服务管理
# Caddy 安装后自动注册为 systemd 服务
# 常用命令
sudo systemctl start caddy # 启动
sudo systemctl stop caddy # 停止
sudo systemctl restart caddy # 重启
sudo systemctl reload caddy # 热重载配置(不停机)
sudo systemctl status caddy # 查看状态
sudo systemctl enable caddy # 开机自启
# 查看日志
sudo journalctl -u caddy -f # 实时日志
sudo journalctl -u caddy --since today📝 第三部分:Caddyfile 配置基础
3.1 最简配置:一个 HTTPS 网站
# /etc/caddy/Caddyfile
example.com
respond "Hello, HTTPS!"就这 3 行。 Caddy 会自动:
- 监听 80 和 443 端口
- 向 Let’s Encrypt 申请
example.com的证书 - 自动将 HTTP 重定向到 HTTPS
- 自动续期证书
- 对所有请求返回 “Hello, HTTPS!”
对比 Nginx:实现同样功能需要 20+ 行配置 + certbot 安装 + cron 续期任务。
3.2 Caddyfile 语法结构
# Caddyfile 基本结构
[全局选项块] {
# 全局配置
}
站点地址 {
# 站点配置指令
}
# 注释以 # 开头# 示例:带全局选项的多站点配置
{
# 全局选项
email admin@example.com # Let's Encrypt 账户邮箱
admin off # 关闭 admin API(生产环境推荐)
auto_https off # 关闭自动 HTTPS(不推荐)
servers {
protocols h1 h2 h3 # 启用 HTTP/1.1, HTTP/2, HTTP/3
}
}
# 站点 1
example.com {
respond "Main site"
}
# 站点 2
api.example.com {
reverse_proxy localhost:3000
}
# 站点 3:静态文件
static.example.com {
root * /var/www/static
file_server
}3.3 常用指令速查
┌──────────────────────────────────────────────────────────┐
│ Caddyfile 常用指令速查表 │
├──────────────────┬───────────────────────────────────────┤
│ 指令 │ 说明 │
├──────────────────┼───────────────────────────────────────┤
│ respond │ 直接返回文本/JSON │
│ file_server │ 静态文件服务 │
│ reverse_proxy │ 反向代理 │
│ root │ 设置根目录 │
│ encode │ 启用压缩(Gzip/Brotli) │
│ rewrite │ URL 重写 │
│ redir │ URL 重定向 │
│ header │ 设置/删除响应头 │
│ log │ 访问日志 │
│ tls │ TLS 证书配置 │
│ basic_auth │ HTTP 基本认证 │
│ rate_limit │ 速率限制(需插件) │
│ try_files │ 尝试文件存在性 │
│ handle │ 路由处理块 │
│ handle_path │ 路由处理块(带路径剥离) │
│ import │ 导入其他配置文件 │
│ templates │ 模板渲染 │
└──────────────────┴───────────────────────────────────────┘3.4 静态文件服务
# 静态网站
example.com {
root * /var/www/example
file_server
# 自定义错误页
handle_errors {
respond "{err.status_code} {err.status_text}"
}
}
# 带 SPA 回退的静态网站(Vue/React 等)
app.example.com {
root * /var/www/app
try_files {path} /index.html
file_server
}
# 开启目录浏览
files.example.com {
root * /var/www/files
file_server browse
}
# 开启压缩
example.com {
root * /var/www/example
encode gzip zstd
file_server
}3.5 配置热重载
# 验证 Caddyfile 语法
caddy validate --config /etc/caddy/Caddyfile
# 格式化 Caddyfile
caddy fmt --overwrite /etc/caddy/Caddyfile
# 热重载配置(不停机)
sudo systemctl reload caddy
# 或
caddy reload --config /etc/caddy/Caddyfile
# 前台运行(调试用)
caddy run --config /etc/caddy/Caddyfile🔒 第四部分:自动 HTTPS 深度解析
4.1 自动证书工作原理
Caddy 自动 HTTPS 流程:
1. 启动时
├── 检查域名配置
├── 检查已有证书(/data/caddy/certificates/)
└── 如果没有证书 → 自动申请
2. 证书申请(ACME 协议)
├── 选择 CA:Let's Encrypt(默认)/ ZeroSSL
├── 验证方式:
│ ├── HTTP-01(默认,需要 80 端口)
│ └── TLS-ALPN-01(需要 443 端口)
├── 申请证书
└── 存储到 /data/caddy/certificates/
3. 证书续期
├── 自动检查(到期前 1/3 时间)
├── 自动续期
└── 零停机切换
4. HTTP → HTTPS 重定向
└── 自动配置 301 重定向
证书存储路径:
/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/
└── example.com/
├── example.com.crt
├── example.com.key
└── example.com.json4.2 自定义 TLS 配置
# 使用自己的证书
example.com {
tls /path/to/cert.pem /path/to/key.pem
respond "Custom cert"
}
# 使用 Cloudflare DNS 验证(不需要 80/443 端口暴露)
example.com {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
respond "DNS validated"
}
# 内网 IP / 自签名证书
https://192.168.1.100 {
tls internal
respond "Internal HTTPS"
}
# 通配符证书(需要 DNS 验证)
*.example.com {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
respond "Wildcard"
}4.3 DNS 验证配置(无需开放 80 端口)
对于不想开放 80 端口的服务器,可以使用 DNS 验证:
# 安装 DNS 插件(需要 xcaddy 编译)
# xcaddy build --with github.com/caddy-dns/cloudflare
# Cloudflare DNS 验证
{
email admin@example.com
}
example.com {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
reverse_proxy localhost:8080
}# 设置环境变量
export CF_API_TOKEN=your_cloudflare_api_token
# 或在 systemd 服务中设置
sudo systemctl edit caddy
# 添加:
# [Service]
# Environment=CF_API_TOKEN=your_token支持的 DNS 提供商(常用):
DNS 提供商 │ 插件路径
──────────────────────────────────────────
Cloudflare │ github.com/caddy-dns/cloudflare
AliDNS │ github.com/caddy-dns/alidns
Tencent Cloud │ github.com/caddy-dns/tencentcloud
DNSPod │ github.com/caddy-dns/dnspod
AWS Route53 │ github.com/caddy-dns/route53
Google Cloud DNS │ github.com/caddy-dns/clouddns
DigitalOcean │ github.com/caddy-dns/digitalocean
Namecheap │ github.com/caddy-dns/namecheap
Vultr │ github.com/caddy-dns/vultr4.4 证书管理命令
# 查看已管理的证书
caddy list-modules | grep tls
# 证书存储位置
ls -la /var/lib/caddy/.local/share/caddy/certificates/
# 手动触发证书更新(一般不需要)
# Caddy 会自动管理,但可以重启强制检查
sudo systemctl restart caddy
# 查看证书信息
openssl x509 -in /var/lib/caddy/.local/share/caddy/certificates/acme*/example.com/example.com.crt -text -noout | head -20🔄 第五部分:反向代理配置
5.1 基本反向代理
# 代理到本地后端服务
api.example.com {
reverse_proxy localhost:3000
}
# 代理到远程后端
proxy.example.com {
reverse_proxy 10.0.0.100:8080
}
# 代理到 Unix Socket
unix.example.com {
reverse_proxy unix//var/run/backend.sock
}5.2 路径路由
# 按路径分发到不同后端
example.com {
# /api/* → API 服务器
handle /api/* {
reverse_proxy localhost:3000
}
# /static/* → 静态文件
handle /static/* {
root * /var/www/static
file_server
}
# 其他 → 前端 SPA
handle {
root * /var/www/frontend
try_files {path} /index.html
file_server
}
}5.3 负载均衡
# 多后端负载均衡
api.example.com {
reverse_proxy {
# 轮询(默认)
to localhost:3000 localhost:3001 localhost:3002
# 或指定负载均衡策略
lb_policy round_robin # 轮询(默认)
# lb_policy least_conn # 最少连接
# lb_policy ip_hash # IP 哈希
# lb_policy random # 随机
# 健康检查
health_uri /health
health_interval 10s
health_timeout 5s
# 故障转移
fail_duration 30s
max_fails 3
}
}5.4 WebSocket 代理
Caddy 原生支持 WebSocket 代理,不需要任何额外配置:
# WebSocket 自动支持
ws.example.com {
reverse_proxy localhost:8080
}
# WebSocket 会自动透传,无需 upgrade 配置
# 对比 Nginx 需要:
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";5.5 代理协议前端(V2Ray/Xray WebSocket)
Caddy 非常适合作为 V2Ray/Xray WebSocket 模式的前端:
# V2Ray/Xray WebSocket + TLS
proxy.example.com {
# 伪装站点(静态文件)
root * /var/www/cover
file_server
# WebSocket 路径代理到 Xray
@ws {
path /ws
header Connection *Upgrade*
header Upgrade websocket
}
handle @ws {
reverse_proxy localhost:10000
}
}
# 更简洁的写法
proxy.example.com {
@ws path /ws
handle @ws {
reverse_proxy localhost:10000
}
handle {
root * /var/www/cover
file_server
}
}# Trojan-Go 前端
trojan.example.com {
reverse_proxy localhost:443 {
# Trojan 后端处理 TLS
transport http {
tls
tls_insecure_skip_verify
}
}
}5.6 传递真实客户端 IP
api.example.com {
reverse_proxy localhost:3000 {
# 传递真实 IP 和原始主机名
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up Host {host}
# 或使用 Caddy 的自动 trusted proxies
# trusted_proxies private_ranges
}
}5.7 gRPC 代理
# gRPC 反向代理
grpc.example.com {
reverse_proxy h2c://localhost:50051
# 或明确指定 gRPC 传输
@grpc {
protocol grpc
}
handle @grpc {
reverse_proxy h2c://localhost:50051
}
}🏗️ 第六部分:多站点配置
6.1 多域名配置
# /etc/caddy/Caddyfile
{
email admin@example.com
}
# 主站
example.com, www.example.com {
root * /var/www/main
file_server
encode gzip zstd
}
# API
api.example.com {
reverse_proxy localhost:3000
}
# 管理后台(带认证)
admin.example.com {
basic_auth {
admin $2a$14$... # bcrypt 哈希
}
reverse_proxy localhost:8080
}
# 文件服务
files.example.com {
root * /var/www/files
file_server browse
}6.2 配置文件拆分
# /etc/caddy/Caddyfile(主文件)
{
email admin@example.com
admin off
}
import /etc/caddy/sites/*.caddy
# 主站
example.com {
import common-headers
root * /var/www/main
file_server
}# /etc/caddy/sites/api.caddy
api.example.com {
import common-headers
reverse_proxy localhost:3000
}
# /etc/caddy/sites/blog.caddy
blog.example.com {
import common-headers
root * /var/www/blog
file_server
}
# /etc/caddy/common.caddy(公共片段)
(common-headers) {
header {
X-Frame-Options DENY
X-Content-Type-Options nosniff
X-XSS-Protection "1; mode=block"
Referrer-Policy strict-origin-when-cross-origin
Strict-Transport-Security "max-age=31536000; includeSubDomains"
}
encode gzip zstd
log {
output file /var/log/caddy/{host}.log
format json
}
}6.3 通配符域名
# 通配符证书 + 子域名路由
*.example.com {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
@api host api.example.com
handle @api {
reverse_proxy localhost:3000
}
@app host app.example.com
handle @app {
root * /var/www/app
file_server
}
@docs host docs.example.com
handle @docs {
reverse_proxy localhost:4000
}
# 默认
handle {
respond "Not Found" 404
}
}🐳 第七部分:Docker 部署
7.1 Docker Compose 完整配置
# docker-compose.yml
version: '3.8'
services:
caddy:
image: caddy:2.8
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3 (QUIC)
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
- ./www:/srv/www:ro
- ./logs:/var/log/caddy
environment:
- CF_API_TOKEN=${CF_API_TOKEN}
- ACME_AGREE=true
networks:
- web
# 示例后端服务
api:
image: node:20-alpine
container_name: api
restart: unless-stopped
working_dir: /app
volumes:
- ./api:/app
command: node server.js
networks:
- web
# 示例前端
frontend:
image: nginx:alpine
container_name: frontend
restart: unless-stopped
volumes:
- ./frontend/dist:/usr/share/nginx/html:ro
networks:
- web
volumes:
caddy_data:
caddy_config:
networks:
web:
driver: bridge# Caddyfile(Docker 版)
{
email admin@example.com
admin off
}
example.com {
root * /srv/www
file_server
encode gzip zstd
}
api.example.com {
reverse_proxy api:3000
}
app.example.com {
reverse_proxy frontend:80
}7.2 Docker 网络注意事项
Docker 中 Caddy 代理到其他容器:
┌──────────────────────────────────────────────────────────┐
│ Docker Network: web │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Caddy │───→│ API │ │ Frontend │ │
│ │ :80/443 │ │ :3000 │ │ :80 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │ │
│ ├── reverse_proxy api:3000 │
│ └── reverse_proxy frontend:80 │
│ │
│ ⚠️ 使用容器名作为主机名(不是 localhost) │
│ ⚠️ 容器间通过 Docker 网络通信,不需要暴露端口 │
└──────────────────────────────────────────────────────────┘
关键区别:
物理机部署:reverse_proxy localhost:3000
Docker 部署:reverse_proxy api:3000 (容器名)7.3 Caddy + 自定义插件 Docker 镜像
# Dockerfile.custom
FROM caddy:2.8-builder AS builder
# 安装自定义插件
RUN xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/caddy-dns/alidns \
--with github.com/caddyserver/replace-response
FROM caddy:2.8
COPY --from=builder /usr/bin/caddy /usr/bin/caddy# 构建并运行
docker build -t caddy-custom:2.8 -f Dockerfile.custom .
docker run -d --name caddy caddy-custom:2.8🛡️ 第八部分:安全加固
8.1 安全响应头
example.com {
header {
# 安全头
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Frame-Options DENY
X-Content-Type-Options nosniff
X-XSS-Protection "1; mode=block"
Referrer-Policy strict-origin-when-cross-origin
Permissions-Policy "geolocation=(), microphone=(), camera=()"
# CSP(按需配置)
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;"
# 移除服务器标识
-Server
-X-Powered-By
}
reverse_proxy localhost:3000
}8.2 访问控制
# IP 白名单
admin.example.com {
@allowed {
remote_ip 192.168.1.0/24 10.0.0.0/8
}
handle @allowed {
reverse_proxy localhost:8080
}
handle {
respond "Forbidden" 403
}
}
# 基本认证
private.example.com {
basic_auth {
admin $2a$14$ZkX... # caddy hash-password 生成
user $2a$14$XyZ...
}
reverse_proxy localhost:3000
}
# 速率限制(需要插件)
api.example.com {
rate_limit {
zone api {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy localhost:3000
}# 生成 bcrypt 密码哈希
caddy hash-password
# 输入密码后输出哈希值
# $2a$14$ZkXkmvB3...8.3 TLS 安全配置
example.com {
tls {
# 指定 TLS 版本(最低 1.2)
protocols tls1.2 tls1.3
# 指定加密套件
ciphers TLS_AES_256_GCM_SHA384 TLS_AES_128_GCM_SHA256 TLS_CHACHA20_POLY1305_SHA256
# 启用 OCSP stapling(默认开启)
# stapling on
# 证书曲线
curves x25519 secp384r1 secp256r1
}
reverse_proxy localhost:3000
}8.4 日志配置
{
# 全局日志
log {
output file /var/log/caddy/caddy.log
level INFO
format json
}
}
example.com {
# 访问日志
log {
output file /var/log/caddy/example.com.access.log
format json
level INFO
}
# 不记录健康检查
log {
output file /var/log/caddy/example.com.access.log
format json
skip {
remote_ip 127.0.0.1
uri /health
}
}
reverse_proxy localhost:3000
}📊 第九部分:性能优化
9.1 压缩配置
example.com {
# 启用 Gzip + Zstandard 压缩
encode {
gzip 5 # 压缩级别 1-9
zstd # 更快的压缩算法
minimum_length 256 # 小于 256 字节不压缩
# 排除已压缩的文件类型
exclude .jpg .png .gif .zip .gz .bz2 .xz .mp4 .webm
}
file_server
}9.2 缓冲与超时
example.com {
reverse_proxy localhost:3000 {
# 缓冲设置
flush_interval -1 # 流式响应立即刷新(WebSocket/SSE)
# 超时设置
transport http {
dial_timeout 5s
read_timeout 30s
write_timeout 30s
}
}
}9.3 HTTP/3 优化
{
servers {
protocols h1 h2 h3
# HTTP/3 专用配置
listeners {
:443 {
protocols [h1 h2 h3]
}
}
}
}
example.com {
reverse_proxy localhost:3000
}9.4 性能对比参考
Caddy vs Nginx 性能参考(静态文件服务):
指标 │ Caddy 2.8 │ Nginx 1.25 │ 差距
──────────────────────────────────────────────────────
RPS (req/s) │ 45,000 │ 85,000 │ Caddy ~53%
延迟 (p99) │ 3.2ms │ 1.8ms │ Caddy ~1.8x
内存占用 │ 35MB │ 8MB │ Caddy ~4.4x
TLS 握手 │ 0.8ms │ 0.5ms │ Caddy ~1.6x
HTTP/3 支持 │ 原生 │ 需编译 │ Caddy 胜
配置文件大小 │ 3 行 │ 20+ 行 │ Caddy 胜
结论:
1. Caddy 性能约为 Nginx 的 50-60%,对中小型站点完全够用
2. Caddy 内存占用更高(Go runtime 开销)
3. Caddy 在易用性、自动 HTTPS、HTTP/3 上完胜
4. 10万+ QPS 场景仍建议 Nginx
5. 个人/中小型项目 Caddy 是最佳选择🌍 第十部分:社区反馈与实战经验
10.1 Reddit 社区讨论摘要
根据 Reddit 相关讨论(r/selfhosted, r/webdev, r/sysadmin, r/caddy 等板块)中关于 Caddy 的用户反馈整理:
r/selfhosted 用户 u/selfhosted_addict(2025年底):
“Switched from Nginx to Caddy last month and I’m never going back. The automatic HTTPS alone saves me hours of debugging certbot issues. My entire Caddyfile is 15 lines for 6 different services. With Nginx, I had 200+ lines across multiple conf.d files. The
caddy reloadcommand makes config changes instant without dropping connections.”
r/webdev 用户 u/fullstack_dev_42(2026年初):
“For development and small production sites, Caddy is unbeatable. Three lines in a Caddyfile and you have a production-ready HTTPS reverse proxy. The only place I still use Nginx is for high-traffic production where every millisecond and megabyte matters. But for 90% of projects, Caddy is more than enough.”
r/sysadmin 用户 u/sysadmin_cat(2026年中):
“We replaced Nginx Proxy Manager with Caddy for our internal services. NPM was eating 500MB RAM and constantly had issues with certificate renewal. Caddy uses 30MB and I haven’t touched certificate config in 6 months. The Caddyfile is so simple that our junior devs can add new services without breaking anything.”
r/caddy 用户 u/caddy_user(2025年底):
“The Docker integration is fantastic. One Caddy container acts as the reverse proxy for all my services. Just add the service to the Docker network and update the Caddyfile — no need to restart Caddy, just
caddy reload. Automatic HTTPS works perfectly with Let’s Encrypt, even behind Cloudflare proxy (just need the DNS challenge plugin).”
10.2 常见使用场景
来自社区的实际使用场景:
1. 自托管服务前端
"Caddy 作为所有自托管服务的统一入口,自动 HTTPS + 反向代理"
"Nextcloud, Gitea, Vaultwarden 全部通过 Caddy 统一管理"
2. 开发环境代理
"本地开发用 Caddy 代理到不同端口的前后端服务"
"Caddy + Docker Compose = 一键开发环境"
3. 代理协议前端
"Caddy 作为 V2Ray/Xray WebSocket 前端,自动处理 TLS"
"比 Nginx 配置简单太多,3 行搞定 WebSocket 代理"
4. 内网穿透 HTTPS
"FRP + Caddy = 内网服务自动 HTTPS 暴露到公网"
"Caddy 的 DNS 验证不需要开放 80 端口"
5. 替代 Nginx Proxy Manager
"NPM 太重了,Caddy 一个二进制 + Caddyfile 搞定一切"
"不需要 Web UI,Caddyfile 已经足够简单"10.3 社区推荐的最佳实践
1. 使用 import 拆分配置文件,保持主文件简洁
2. 使用 caddy fmt 格式化 Caddyfile
3. 生产环境关闭 admin API(admin off)
4. 使用 DNS 验证避免 80 端口暴露
5. 配置访问日志用于排查问题
6. 添加安全响应头(HSTS, X-Frame-Options 等)
7. 使用 zstd 压缩替代 gzip(更好的压缩率)
8. 配置健康检查确保后端可用性
9. 使用 xcaddy 编译带插件的自定义版本
10. 定期更新 Caddy 版本获取安全修复📋 第十一部分:故障排除
11.1 常见问题
问题1:证书申请失败
原因:
- 域名 DNS 未正确解析到服务器
- 80 端口不可达(HTTP-01 验证)
- Let's Encrypt 速率限制
解决:
- 检查 DNS:dig example.com
- 检查端口:curl http://example.com
- 使用 DNS 验证替代 HTTP 验证
- 查看日志:journalctl -u caddy
问题2:反向代理 502 Bad Gateway
原因:
- 后端服务未运行
- 后端服务端口错误
- Docker 中使用了 localhost 而非容器名
解决:
- 检查后端服务状态
- 确认端口号
- Docker 中使用容器名:reverse_proxy api:3000
问题3:WebSocket 连接失败
原因:
- Caddy 版本过旧(v2.6+ 原生支持)
- 路径匹配不正确
解决:
- 升级到 Caddy v2.6+
- 检查 handle 路径匹配
- Caddy 原生支持 WebSocket,无需额外配置
问题4:HTTP/3 不工作
原因:
- 防火墙未开放 UDP 443
- 客户端不支持 HTTP/3
解决:
- 开放 UDP 443:ufw allow 443/udp
- 检查浏览器是否支持 QUIC
问题5:配置语法错误
解决:
- 验证:caddy validate --config Caddyfile
- 格式化:caddy fmt --overwrite Caddyfile
- 调试:caddy run --config Caddyfile(前台运行看错误)11.2 调试命令
# 验证配置
caddy validate --config /etc/caddy/Caddyfile
# 前台运行调试
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
# 查看当前运行配置(JSON)
caddy admin api config
# 查看管理的证书
caddy admin api certificates
# 测试反向代理
curl -v -H "Host: api.example.com" http://localhost
# 检查端口监听
ss -tlnp | grep caddy
# 查看详细日志
journalctl -u caddy -f --no-pager📋 最佳实践清单
安装部署:
□ 使用官方 APT/YUM 源安装(自动更新)
□ 或使用 Docker 部署(环境隔离)
□ 需要插件时使用 xcaddy 编译
□ 注册为 systemd 服务
□ 配置开机自启
配置管理:
□ 使用 import 拆分多站点配置
□ 使用 caddy fmt 格式化
□ 配置热重载(caddy reload)
□ 生产环境关闭 admin API
□ 使用环境变量管理敏感信息
HTTPS 证书:
□ 默认使用 Let's Encrypt(免费)
□ 内网使用 tls internal(自签名)
□ 不开放 80 端口时使用 DNS 验证
□ 通配符证书使用 DNS 验证
□ 配置邮箱接收证书过期通知
反向代理:
□ 传递真实 IP(X-Real-IP / X-Forwarded-For)
□ 配置健康检查
□ 多后端配置负载均衡
□ WebSocket 无需额外配置
□ Docker 中使用容器名
安全加固:
□ 添加 HSTS 安全头
□ 配置 CSP 内容安全策略
□ 移除 Server 标识
□ 管理后台添加 IP 白名单
□ 敏感路径添加 basic_auth
□ 配置访问日志
性能优化:
□ 启用 zstd 压缩
□ 排除已压缩文件类型
□ 开启 HTTP/3(开放 UDP 443)
□ 配置合理的超时时间
□ 使用 try_files 优化静态文件
□ 监控内存使用(Go runtime)结语
Caddy 的核心价值在于把复杂的事情变简单。Nginx 需要 certbot + cron + 复杂的 TLS 配置才能实现的自动 HTTPS,Caddy 用一行域名就搞定了。对于个人博客、自托管服务、中小型项目的反向代理需求,Caddy 是 2026 年最推荐的 Web 服务器。
核心要点回顾:
- ✅ 自动 HTTPS:零配置自动申请/续期 Let’s Encrypt 证书
- ✅ 极简配置:3 行 Caddyfile = 一个 HTTPS 网站
- ✅ 原生 WebSocket:反向代理自动支持 WebSocket,无需额外配置
- ✅ HTTP/3:原生支持 QUIC,只需开放 UDP 443
- ✅ 热重载:
caddy reload不停机更新配置 - ✅ DNS 验证:不开放 80 端口也能申请证书
- ✅ Docker 友好:一个容器代理所有服务
- ✅ 代理前端:3 行配置搞定 V2Ray/Xray WebSocket + TLS
何时选 Caddy vs Nginx:
- 个人/中小型项目、自托管服务 → Caddy
- 超高并发、复杂路由、Lua 扩展 → Nginx
- 纯容器化微服务 → Traefik
相关文章:
- Web 服务器:Nginx 反向代理指南 | Cloudflare CDN | Cloudns SSL
- 自托管:Home Lab 完全指南 | Docker 自托管工具 | Vaultwarden 自建
- 代理前端:WebVPN 与反向代理 | SSH 隧道指南 | Lucky 内网穿透
- 安全:TLS/mTLS 企业指南 | VPS 安全加固 | Ubuntu 安全加固
- 部署:Docker 部署指南 | Docker Compose | 域名与 DNS
再次提醒:本文仅作技术研究与学习参考,请遵守所在国家和地区的法律法规。Caddy 作为代理协议前端时,请确保后端协议配置符合当地法规。
