TL;DR
Caddy 是一个基于 Go 的现代 Web 服务器,通过 Let's Encrypt 提供零配置自动 HTTPS。它是 Nginx 和 Apache 的替代品,配置语法(Caddyfile)极其简单。Caddy 自动处理 TLS 证书的获取、续期和 OCSP 装订。支持反向代理、负载均衡、静态文件服务、HTTP/3 和通过管理 API 进行动态配置。在 2026 年的大多数 Web 服务场景中,Caddy 以生产级可靠性提供了最佳开发者体验。
Key Takeaways
- Caddy 自动从 Let's Encrypt 获取和续期 HTTPS 证书 — 无需 certbot、无需 cron、无需手动续期
- Caddyfile 语法比 Nginx/Apache 配置简单得多:基本反向代理只需 3 行
- Caddy 原生支持 HTTP/3 (QUIC)、按需 TLS、通配符证书和 ACME 协议
- Caddy 管理 API 允许不重启或重载即可实时更改配置
- Caddy 非常适合作为 Docker 反向代理,为容器化微服务提供自动 HTTPS
- 从 Nginx 迁移到 Caddy 通常可减少 60-80% 的配置复杂度
Caddy 是一个用 Go 编写的开源 Web 服务器,作为 Nginx 和 Apache 的现代替代方案获得了广泛关注。其最突出的特性是自动 HTTPS:Caddy 无需任何配置即可从 Let's Encrypt(或 ZeroSSL)获取和续期 TLS 证书。在 2026 年,Caddy 为数百万站点提供服务,已成为想要生产级 Web 服务而不需要复杂传统服务器配置的开发者的首选。本指南涵盖从基础设置到高级生产部署模式的所有内容。
什么是 Caddy 以及为什么它很重要
Caddy 是一个强大的、可扩展的 Web 服务器平台。它由 Matt Holt 于 2015 年创建,已发展成为成熟的生产级服务器。Caddy v2 是一次完全重写,引入了模块化架构、JSON 配置系统和 Caddyfile 适配器。
Caddy 的独特之处在于其安全默认的理念。HTTPS 默认自动开启。HTTP 请求自动重定向到 HTTPS。OCSP 装订已启用。强制使用现代 TLS 版本。这意味着零配置的全新 Caddy 安装已经比大多数手动配置的 Nginx 或 Apache 更安全。
- 通过 Let's Encrypt 和 ZeroSSL 零配置自动 HTTPS
- 用 Go 编写 — 单一静态二进制文件,无依赖,跨平台
- Caddyfile:比 Nginx 或 Apache 简单得多的人类可读配置
- 默认启用原生 HTTP/3 (QUIC) 支持
- 管理 API 实现无停机实时配置更改
- 可扩展的模块系统 — 无需 fork 即可添加功能
- 优雅重载、自动证书管理和 OCSP 装订
Caddy vs Nginx vs Apache vs Traefik
每个 Web 服务器都有适合不同用例的优势。此对比帮助您为项目选择合适的服务器。
| 特性 | Caddy | Nginx | Apache | Traefik |
|---|---|---|---|---|
| 自动 HTTPS | 内置(零配置) | 手动(certbot) | 手动(certbot) | 内置(需配置) |
| 配置语法 | Caddyfile(简单) | nginx.conf(复杂) | httpd.conf + .htaccess | YAML/TOML/标签 |
| 原始性能 | 非常好 | 优秀 | 良好 | 良好 |
| 内存使用 | 低 (~20MB) | 非常低 (~5MB) | 高 (~50-200MB) | 低 (~30MB) |
| HTTP/3 支持 | 原生(默认开启) | 实验性 | 不支持 | 实验性 |
| Docker 集成 | 良好 | 手动配置 | 手动配置 | 优秀(原生) |
| 插件系统 | Go 模块 | C 模块(编译) | 动态模块 | Go 插件 |
| 学习曲线 | 简单 | 中等 | 中等-困难 | 中等 |
| 编写语言 | Go | C | C | Go |
| 许可证 | Apache 2.0 | BSD 2-Clause | Apache 2.0 | MIT |
安装
Caddy 以单一静态二进制文件分发,无需运行时依赖。
包管理器
# Debian / Ubuntu
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
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
# Fedora / RHEL
dnf copr enable @caddy/caddy && dnf install caddy
# macOS
brew install caddy
# Windows
choco install caddyDocker
# Pull official Caddy image
docker pull caddy:latest
# Run with Caddyfile
docker run -d --name caddy \
-p 80:80 -p 443:443 -p 443:443/udp \
-v $PWD/Caddyfile:/etc/caddy/Caddyfile \
-v caddy_data:/data \
-v caddy_config:/config \
caddy:latest直接下载二进制文件
# Download from GitHub releases
curl -OL https://github.com/caddyserver/caddy/releases/latest/download/caddy_2.9.1_linux_amd64.tar.gz
tar xzf caddy_2.9.1_linux_amd64.tar.gz
sudo mv caddy /usr/bin/caddy
sudo chmod +x /usr/bin/caddy
# Verify installation
caddy version使用 xcaddy 从源码构建
# Install xcaddy (Caddy build tool)
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
# Build Caddy with custom plugins
xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/mholt/caddy-ratelimit \
--with github.com/caddyserver/transform-encoderCaddyfile 基础
Caddyfile 是 Caddy 的人类友好配置格式,即使对于复杂设置也易于读写。
自动 HTTPS(默认行为)
在 Caddyfile 中指定域名时,Caddy 自动从 Let's Encrypt 获取 TLS 证书、将 HTTP 重定向到 HTTPS 并启用 OCSP 装订。无需额外配置。
# Minimal Caddyfile — automatic HTTPS!
# Just specify your domain and Caddy does the rest
example.com {
respond "Hello, world!"
}
# What Caddy does automatically:
# 1. Obtains TLS certificate from Let's Encrypt
# 2. Redirects http://example.com → https://example.com
# 3. Enables OCSP stapling
# 4. Enforces modern TLS (1.2+)
# 5. Renews certificate before expiry静态文件服务器
# Serve static files with compression and caching
example.com {
root * /var/www/html
encode gzip zstd
file_server
# Cache static assets for 1 year
@static path *.css *.js *.png *.jpg *.svg *.woff2
header @static Cache-Control "public, max-age=31536000, immutable"
# Cache HTML for 1 hour
@html path *.html
header @html Cache-Control "public, max-age=3600"
}重定向
# Redirect www to non-www
www.example.com {
redir https://example.com{uri} permanent
}
# Redirect old paths
example.com {
redir /old-page /new-page permanent
redir /blog/old-slug /blog/new-slug 301
}反向代理配置
Caddy 是优秀的反向代理,支持单后端、负载均衡、健康检查、WebSocket 代理和请求头操作。
单后端
# Simple reverse proxy — 3 lines!
app.example.com {
reverse_proxy localhost:3000
}
# With header manipulation
api.example.com {
reverse_proxy localhost:8080 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
header_down -Server
}
}负载均衡
# Load balancing across multiple backends
app.example.com {
reverse_proxy {
to localhost:3001
to localhost:3002
to localhost:3003
lb_policy round_robin
# Other policies: random, first, ip_hash,
# uri_hash, least_conn, header
}
}健康检查
# Active health checks
app.example.com {
reverse_proxy {
to localhost:3001
to localhost:3002
health_uri /health
health_interval 10s
health_timeout 5s
health_status 200
# Passive health checks (circuit breaker)
fail_duration 30s
max_fails 3
unhealthy_latency 500ms
}
}WebSocket 代理
# WebSocket proxying — Caddy handles upgrade automatically
ws.example.com {
reverse_proxy localhost:8080
# That's it! Caddy detects WebSocket upgrades
# and handles them transparently.
}
# With path-based routing
example.com {
reverse_proxy /ws/* localhost:8080
reverse_proxy /api/* localhost:3000
file_server
}Nginx 等效对比
以下是相同反向代理配置在 Caddy 和 Nginx 中的对比。
# CADDY — Reverse proxy with HTTPS (3 lines)
app.example.com {
reverse_proxy localhost:3000
}
# NGINX equivalent (~25 lines + certbot + cron)
# server { listen 80; server_name app.example.com;
# return 301 https://$server_name$request_uri; }
# server { listen 443 ssl http2;
# server_name app.example.com;
# ssl_certificate /etc/letsencrypt/live/.../fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/.../privkey.pem;
# location / {
# proxy_pass http://localhost:3000;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# }
# } + certbot setup + renewal cron job自动 HTTPS 深入解析
Caddy 的自动 HTTPS 是其最引人注目的特性,它自动处理整个 TLS 生命周期。
- 使用 ACME 协议从 Let's Encrypt(或 ZeroSSL)获取证书
- 证书到期前自动续期(默认:到期前 30 天)
- 自动将 HTTP 重定向到 HTTPS
- 启用 OCSP 装订以加快 TLS 握手
- 支持 ACME DNS 挑战以获取通配符证书
- 按需 TLS:在 TLS 握手时获取证书,适用于动态域名
通配符证书
Caddy 通过 DNS 挑战支持通配符证书。您需要为您的域名注册商安装 DNS 提供商插件。
# Wildcard certificate with Cloudflare DNS
# Build Caddy with: xcaddy build --with github.com/caddy-dns/cloudflare
*.example.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
@app host app.example.com
handle @app {
reverse_proxy localhost:3000
}
@api host api.example.com
handle @api {
reverse_proxy localhost:8080
}
handle {
respond "Unknown subdomain" 404
}
}按需 TLS
按需 TLS 在 TLS 握手期间获取证书。这对于客户域名事先未知的 SaaS 平台很有用。
# On-demand TLS for SaaS custom domains
{
on_demand_tls {
ask http://localhost:5555/check-domain
interval 5m
burst 10
}
}
https:// {
tls {
on_demand
}
reverse_proxy localhost:3000
}Docker 部署
Caddy 在 Docker 环境中表现出色。以下是常见的部署模式。
基本 Docker 设置
# Dockerfile for custom Caddy
FROM caddy:2-builder AS builder
RUN xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/mholt/caddy-ratelimit
FROM caddy:2
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
COPY Caddyfile /etc/caddy/CaddyfileDocker Compose 多服务
# docker-compose.yml — Multi-service with Caddy
services:
caddy:
image: caddy:latest
restart: unless-stopped
ports: ["80:80", "443:443", "443:443/udp"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
networks: [web]
app:
build: ./app
expose: ["3000"]
networks: [web]
api:
build: ./api
expose: ["8080"]
networks: [web, backend]
db:
image: postgres:16-alpine
volumes: [pgdata:/var/lib/postgresql/data]
networks: [backend]
volumes: { caddy_data: {}, pgdata: {} }
networks: { web: {}, backend: {} }
# Caddyfile for the compose setup
app.example.com { reverse_proxy app:3000 }
api.example.com { reverse_proxy api:8080 }PHP 和 WordPress 与 Caddy
Caddy 通过 php_fastcgi 指令提供一流的 PHP 支持,处理路径拆分、索引文件解析和 FastCGI 通信。
基本 PHP 设置
# Basic PHP with Caddy
example.com {
root * /var/www/html
encode gzip
php_fastcgi unix//run/php/php8.3-fpm.sock
file_server
}WordPress 配置
# WordPress with Caddy — complete config
example.com {
root * /var/www/wordpress
encode gzip
# PHP processing
php_fastcgi unix//run/php/php8.3-fpm.sock
# Static file serving
file_server
# Block access to sensitive files
@blocked path /xmlrpc.php /wp-config.php
respond @blocked 403
# Cache static assets
@static path *.css *.js *.png *.jpg *.gif *.ico *.svg *.woff2
header @static Cache-Control "public, max-age=31536000"
# Security headers
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Referrer-Policy strict-origin-when-cross-origin
-Server
}
}SPA 托管(React、Vue、Next.js)
Caddy 通过 try_files 指令优雅地处理单页应用的客户端路由回退。
# React / Vue SPA hosting
app.example.com {
root * /var/www/app/dist
encode gzip zstd
# SPA client-side routing fallback
try_files {path} /index.html
file_server
# Proxy API requests to backend
reverse_proxy /api/* localhost:8080
# Cache static assets aggressively
@static path *.js *.css *.png *.svg *.woff2
header @static Cache-Control "public, max-age=31536000, immutable"
}
# Next.js / Nuxt.js (SSR mode)
ssr.example.com {
reverse_proxy localhost:3000
}Caddy 作为 API 网关
Caddy 可以作为 API 网关,根据路径前缀将请求路由到不同的后端服务,并支持速率限制和 CORS 头。
# Caddy as API Gateway
api.example.com {
# CORS headers
header Access-Control-Allow-Origin "https://app.example.com"
header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
header Access-Control-Allow-Headers "Authorization, Content-Type"
# Route to different microservices
reverse_proxy /users/* user-service:3001
reverse_proxy /orders/* order-service:3002
reverse_proxy /payments/* payment-service:3003
reverse_proxy /notifications/* notification-service:3004
# Health check endpoint
respond /health 200
}HTTP/3 和 QUIC 支持
Caddy 原生支持 HTTP/3 (QUIC) 并默认启用。HTTP/3 使用 UDP 而非 TCP,提供更快的连接建立、在有损网络上更好的性能,并消除队头阻塞。无需额外配置。
# HTTP/3 is enabled by default in Caddy!
# Make sure to expose UDP port 443:
# docker run -p 443:443/udp ...
# To explicitly disable HTTP/3:
{
servers {
protocols h1 h2
# Omitting h3 disables QUIC
}
}
# Response headers will include:
# Alt-Svc: h3=":443"; ma=2592000Caddy JSON 配置 vs Caddyfile
Caddy 有两个配置接口:Caddyfile(人类友好)和 JSON(机器友好)。Caddyfile 实际上是一个转换为 JSON 的适配器。JSON 配置提供对每个 Caddy 功能的完全控制。
# Convert Caddyfile to JSON (see what Caddy generates internally)
caddy adapt --config Caddyfile --pretty
# JSON config gives full control — ideal for programmatic configs
# { "apps": { "http": { "servers": { "srv0": {
# "listen": [":443"],
# "routes": [{ "match": [{"host": ["app.example.com"]}],
# "handle": [{"handler": "reverse_proxy",
# "upstreams": [{"dial": "localhost:3000"}]}] }]
# }}}}}Caddy 管理 API
Caddy 在 localhost:2019 上暴露 REST API 用于实时配置管理。可以加载、修改和检查配置而无需重启服务器。
# Caddy Admin API (localhost:2019)
# Load new JSON config
curl localhost:2019/load -H "Content-Type: application/json" -d @caddy.json
# Load Caddyfile via adapter
curl localhost:2019/load -H "Content-Type: text/caddyfile" --data-binary @Caddyfile
# Get current config
curl localhost:2019/config/
# Graceful reload from CLI
caddy reload --config /etc/caddy/Caddyfile速率限制和安全头
Caddy 提供内置安全功能,并可通过速率限制模块扩展。
# Security headers and rate limiting
example.com {
header {
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy strict-origin-when-cross-origin
Permissions-Policy "camera=(), microphone=(), geolocation=()"
-Server
}
# Basic authentication
basicauth /admin/* {
admin $2a$14$hashed_password_here
}
# IP allowlist
@blocked not remote_ip 10.0.0.0/8
respond @blocked /internal/* 403
reverse_proxy localhost:3000
}日志和指标
Caddy 默认生成结构化 JSON 日志,易于用 jq、Loki 或 Elasticsearch 解析。还通过模块支持 Prometheus 指标。
# Structured JSON logging with rotation
example.com {
log {
output file /var/log/caddy/access.log {
roll_size 100MiB
roll_keep 10
}
format json
}
reverse_proxy localhost:3000
}
# Prometheus metrics: built-in at :2019/metrics性能调优
Caddy 开箱即用性能良好,但可以针对高流量场景进行调优。
- 使用 encode gzip zstd 启用静态文件压缩
- 使用带 precompressed 的 file_server 提供预压缩文件
- 通过 GOMAXPROCS 环境变量调整工作线程数
- 启用 HTTP/3 以在移动和有损网络上获得更好性能
- 使用 header 缓存指令处理静态资源
- 适当配置连接保活超时
# Performance-optimized Caddyfile
example.com {
root * /var/www/html
# Enable compression (gzip + zstd)
encode zstd gzip
# Serve pre-compressed files if available
file_server {
precompressed zstd gzip br
}
# Aggressive caching for static assets
@immutable path *.js *.css *.woff2 *.png *.jpg *.svg
header @immutable {
Cache-Control "public, max-age=31536000, immutable"
Vary Accept-Encoding
}
# Keep-alive settings
# (Caddy defaults are good for most cases)
}Caddy 模块和插件
Caddy 拥有丰富的插件生态。插件是扩展 Caddy 功能的 Go 模块。使用 xcaddy 构建包含所需插件的自定义 Caddy 二进制文件。
# Popular Caddy modules (install with xcaddy)
xcaddy build \
--with github.com/caddy-dns/cloudflare \ # DNS challenge (Cloudflare)
--with github.com/caddy-dns/route53 \ # DNS challenge (AWS)
--with github.com/mholt/caddy-ratelimit \ # Rate limiting
--with github.com/caddyserver/cache-handler # HTTP caching
# Prometheus metrics — built-in since v2.7 (no plugin needed)
# List installed modules
caddy list-modules从 Nginx 迁移到 Caddy
从 Nginx 迁移到 Caddy 通常会大大简化配置。以下是常见的 Nginx 模式及其 Caddy 等效配置。
# Migration cheat sheet: Nginx → Caddy
#
# server { listen 443 ssl; server_name X; } → X { }
# location / { proxy_pass http://...; } → reverse_proxy localhost:3000
# location ~ \.php$ { fastcgi_pass ...; } → php_fastcgi unix//run/php/php8.3-fpm.sock
# try_files $uri $uri/ /index.html → try_files {path} /index.html
# rewrite ^/old$ /new permanent → redir /old /new permanent
# add_header X-Frame-Options DENY → header X-Frame-Options DENY
# ssl_certificate + certbot + cron → (automatic — nothing needed)
# gzip on; gzip_types ... → encode gzip zstd生产部署最佳实践
- 将 Caddy 作为 systemd 服务运行以实现自动重启和日志
- 人工管理配置用 Caddyfile,自动化用 JSON
- 将 Caddy 数据目录 (/data) 存储在持久存储上以保存证书
- 设置访问和错误日志轮转
- 使用 Prometheus 指标监控证书到期
- 管理 API 端点仅在 localhost 上使用(默认)
- 保持 Caddy 更新 — 安全补丁定期发布
- 应用前用 caddy validate 测试配置更改
# Install as systemd service (package managers do this automatically)
sudo systemctl enable --now caddy
# Validate config before applying
caddy validate --config /etc/caddy/Caddyfile
# Graceful reload (no downtime)
sudo systemctl reload caddy
# Check status and logs
sudo systemctl status caddy
journalctl -u caddy --no-pager -f常见问题和故障排除
- 证书未获取:检查端口 80 和 443 是否可从互联网访问。Caddy 需要这些端口进行 ACME HTTP 挑战。
- 端口 80/443 权限被拒绝:在 Linux 上运行 setcap 或使用 systemd socket 激活。
- 证书过多:Let's Encrypt 有速率限制。测试时使用 staging 环境。
- 配置不重载:使用 caddy reload 而不是重启。先检查 caddy validate。
- 反向代理 502 错误:验证后端是否运行并可访问。
- WebSocket 不工作:Caddy 自动处理 WebSocket 升级。检查后端是否需要特定头。
- 内存使用高:检查是否有过度日志记录。内存使用随活动连接和证书数量而增长。
- 证书签发慢:DNS 传播对于 DNS 挑战可能较慢。尽可能使用 HTTP 挑战。
常见问题解答
Caddy 是否可以用于生产环境?
是的。Caddy v2 自 2020 年起已可用于生产,被数千家公司使用。它处理自动 HTTPS、优雅重载,并经过了广泛的实战测试。
Caddy 与 Nginx 的性能对比如何?
对于大多数实际工作负载,Caddy 和 Nginx 性能相当。Nginx 在原始静态文件吞吐量上略有优势,但差异通常小于 10%,与后端处理时间相比可以忽略。
Caddy 能替代 Nginx 作为反向代理吗?
完全可以。Caddy 作为反向代理表现出色,支持自动 HTTPS、负载均衡、健康检查和 WebSocket。配置比 Nginx 简单得多。
Caddy 支持通配符证书吗?
支持。Caddy 通过 ACME DNS 挑战支持通配符证书。需要为您的注册商安装 DNS 提供商插件。
Caddy 如何处理证书续期?
Caddy 在证书到期前 30 天自动续期。如果续期失败,会以指数退避重试并记录警告。
可以将 Caddy 与 Docker 和 Kubernetes 一起使用吗?
可以。Caddy 有官方 Docker 镜像,在容器环境中表现良好。Docker Compose 模式中 Caddy 作为多服务入口点非常流行。
Caddy 是免费开源的吗?
是的。Caddy 使用 Apache 2.0 许可证,完全免费使用,包括商业用途。没有付费层或企业版。
如何从 Nginx 迁移到 Caddy?
首先将 nginx.conf 翻译为 Caddyfile。大多数 Nginx 指令都有直接的 Caddy 等效项但语法更简单。移除所有 SSL/TLS 配置。用 caddy validate 测试后切换 DNS。