Caddy 从入门到精通 / 10 - 高级主题 / Advanced Topics
高级主题 / Advanced Topics
本章覆盖 Caddy 在生产环境中的高级使用场景:集群、性能调优、插件开发、监控、安全加固等。
This chapter covers advanced Caddy usage in production: clustering, performance tuning, plugin development, monitoring, and security hardening.
🟢 基础 / Basics — 性能调优入门 / Performance Basics
Caddy 的默认性能
Caddy 开箱即用的性能已经很好,通常不需要像 Nginx 那样大量调优。但了解基本配置仍然重要。
工作线程数
Caddy 使用 Go 的 goroutine 模型,不需要手动设置 worker 数量。Go runtime 会自动管理:
# 查看 GOMAXPROCS(默认 = CPU 核数)
docker exec caddy env | grep GOMAXPROCS
如需限制:
environment:
- GOMAXPROCS=4
连接限制
{
# 限制最大连接数(JSON API 层面)
}
example.com {
reverse_proxy localhost:3000 {
transport http {
max_idle_conns 100
max_idle_conns_per_host 10
idle_conn_timeout 90s
}
}
}
日志对性能的影响
同步日志写入会成为瓶颈。建议使用异步日志或减少日志粒度:
{
log default {
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 5
}
# 只记录关键字段
format filter {
wrap json
fields {
request>remote_ip ip_mask {
ipv4 24
ipv6 32
}
request>uri query {
replace session_id REDACTED
}
}
}
}
}
🟡 进阶 / Intermediate
集群模式 / Clustering
Caddy 本身不是原生集群软件,但可以通过共享存储实现多实例协同:
证书共享
多台 Caddy 实例共享同一个 ACME 状态,避免重复申请证书:
方案一:NFS / GlusterFS 共享 /data
方案二:Redis / Consul 后端存储(需插件)
方案三:rsync 定期同步
NFS 共享示例:
# 所有 Caddy 实例挂载同一个 NFS
services:
caddy1:
volumes:
- /nfs/caddy/data:/data
caddy2:
volumes:
- /nfs/caddy/data:/data
⚠️ 注意并发锁:多个实例同时续期证书可能产生竞争。Caddy 内部有文件锁机制,在 NFS 上需要支持 fcntl 锁。
配置同步
# 主节点修改后推送到所有节点
for host in caddy2 caddy3; do
scp Caddyfile root@${host}:/etc/caddy/Caddyfile
ssh root@${host} "caddy reload --config /etc/caddy/Caddyfile"
done
或使用 etcd / Consul 做配置中心:
[配置中心 (etcd)]
│
├── caddy1 watches key
├── caddy2 watches key
└── caddy3 watches key
Prometheus 监控集成
Caddy 内置 metrics 支持(需要编译时包含):
xcaddy build --with github.com/mholt/caddy-events-prometheus
{
admin off
}
:2019 {
metrics /metrics
}
example.com {
reverse_proxy localhost:3000
}
关键 metrics:
caddy_http_requests_total— 请求计数caddy_http_request_duration_seconds— 请求延迟caddy_http_response_status_count— 状态码统计
Grafana Dashboard:ID: 19127
日志接入 ELK / Loki
JSON 格式 → Filebeat → Elasticsearch:
{
log {
format json
output file /var/log/caddy/access.log
}
}
# filebeat.yml
filebeat.inputs:
- type: log
paths:
- /var/log/caddy/access.log
json.keys_under_root: true
output.elasticsearch:
hosts: ["http://elasticsearch:9200"]
JSON 格式 → Promtail → Loki:
# promtail-config.yml
scrape_configs:
- job_name: caddy
static_configs:
- targets: [localhost]
labels:
job: caddy
__path__: /var/log/caddy/access.log
pipeline_stages:
- json:
expressions:
status: status
method: request>method
- labels:
status:
method:
安全加固清单
{
# 禁用管理 API(生产环境推荐)
admin off
}
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=()"
Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
-Server
-X-Powered-By
}
# 限制请求体大小
request_body {
max_size 10MB
}
# 隐藏文件拒绝
@hidden path */.*
respond @hidden 403
reverse_proxy localhost:3000
}
🔴 高级 / Advanced
插件开发 / Plugin Development
Caddy 插件就是 Go module,只需实现特定接口并注册:
package myhandler
import (
"net/http"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
func init() {
caddy.RegisterModule(MyHandler{})
}
type MyHandler struct {
Message string `json:"message,omitempty"`
}
func (MyHandler) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "http.handlers.myhandler",
New: func() caddy.Module { return new(MyHandler) },
}
}
// UnmarshalCaddyfile 实现 Caddyfile 解析
func (h *MyHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
if !d.Args(&h.Message) {
return d.ArgErr()
}
}
return nil
}
func (h MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
w.Write([]byte(h.Message))
return nil
}
// 接口断言
var _ caddyhttp.MiddlewareHandler = (*MyHandler)(nil)
使用 xcaddy 编译:
xcaddy build --with github.com/you/caddy-myhandler=./myhandler
Caddyfile 使用:
example.com {
myhandler "Hello from custom plugin!"
}
插件类型一览
| 接口 | 用途 |
|---|---|
caddyhttp.MiddlewareHandler | HTTP 中间件 |
caddyhttp.Handler | HTTP 处理器 |
caddy.Validator | 配置验证 |
caddy.Provisioner | 初始化逻辑 |
caddy.Cleaner | 清理逻辑 |
caddyfile.Unmarshaler | Caddyfile 解析 |
certmagic.Issuer | 自定义证书签发 |
certmagic.Storage | 自定义证书存储 |
自定义存储后端(Redis 存储证书)
package redisstorage
import (
"github.com/caddyserver/certmagic"
)
type RedisStorage struct {
Addr string `json:"addr"`
Password string `json:"password"`
DB int `json:"db"`
}
func (s *RedisStorage) Store(ctx context.Context, key string, value []byte) error {
// 存储到 Redis
}
func (s *RedisStorage) Load(ctx context.Context, key string) ([]byte, error) {
// 从 Redis 读取
}
// ... 实现其他 certmagic.Storage 接口方法
这样多台 Caddy 实例可以共享同一套证书存储,完美解决集群问题。
调试技巧
开启 debug 日志:
{
debug
}
查看完整 JSON 配置:
curl http://localhost:2019/config/ | jq .
追踪 TLS 握手:
caddy run --config Caddyfile 2>&1 | grep -i tls
使用 pprof 性能分析:
{
admin localhost:2019
}
# CPU profile
go tool pprof http://localhost:2019/debug/pprof/profile?seconds=30
# Heap profile
go tool pprof http://localhost:2019/debug/pprof/heap
从 Nginx 迁移 / Migration from Nginx
| Nginx | Caddy |
|---|---|
server {} | example.com {} |
listen 80 | (自动处理) |
server_name | 站点块名 |
root | root * /path |
location / {} | handle / {} |
proxy_pass | reverse_proxy |
ssl_certificate | (自动处理) |
try_files | try_files |
rewrite | rewrite 或 uri |
gzip on | encode gzip |
error_page | handle_errors |
if (!-f $request_filename) | @not_file not file |
高流量场景参考配置
{
# 关闭管理 API
admin off
# 日志优化
log {
format json {
time_format "2006-01-02T15:04:05Z07:00"
}
output file /var/log/caddy/access.log {
roll_size 200mb
roll_keep 5
}
}
}
example.com {
# 安全头
header {
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
-Server
}
# 压缩
encode gzip zstd
# 静态资源长缓存
@static path *.css *.js *.png *.jpg *.gif *.svg *.woff2 *.ico
header @static Cache-Control "public, max-age=31536000, immutable"
# API 代理
@api path /api/*
handle @api {
reverse_proxy localhost:8080 {
lb_policy least_conn
health_path /healthz
health_interval 10s
transport http {
dial_timeout 3s
response_header_timeout 30s
max_idle_conns 200
}
flush_interval -1
}
}
# SPA fallback
handle {
root * /var/www/dist
try_files {path} /index.html
file_server {
precompressed gzip br
}
}
# 错误页面
handle_errors {
root * /var/www/errors
rewrite * /{http.error.status_code}.html
file_server
}
}
小结 / Summary
| 层级 | 内容 |
|---|---|
| 🟢 基础 | GOMAXPROCS、连接限制、日志性能 |
| 🟡 进阶 | 集群证书共享、Prometheus 监控、ELK/Loki 日志、安全加固 |
| 🔴 高级 | 插件开发、自定义存储后端、pprof 调试、Nginx 迁移、高流量配置 |
附录:常用命令速查 / Command Cheat Sheet
# 运行
caddy run # 前台运行
caddy start # 后台运行
caddy stop # 停止后台进程
caddy reload # 重载配置
caddy validate --config Caddyfile # 验证配置
caddy adapt --pretty --config Caddyfile # Caddyfile → JSON
# 信息
caddy version # 版本
caddy list-modules # 列出所有模块
caddy list-modules --packages # 带包名
# 密码
caddy hash-password --plaintext "xxx" # 生成 bcrypt 哈希
# API
curl http://localhost:2019/config/ # 获取当前配置
curl http://localhost:2019/config/ | jq . # 格式化输出