Caddy 使用指南
Caddy 是一款用 Go 语言编写的现代 Web 服务器,以配置极其简单和自动化 HTTPS为核心特色。与 Nginx 或 Apache 相比,Caddy 最大的优势在于默认开启 HTTPS,它会自动从 Let’s Encrypt 申请并续签 SSL/TLS 证书,让网站一键拥有“小绿锁”。
一、安装与基本管理
1.1 各平台安装方式
方式一:使用 APT 包管理器(推荐 Ubuntu/Debian)
# 添加 Caddy 官方仓库curl-1sLf'https://dl.cloudsmith.io/public/caddy/stable/gpg.key'|sudogpg--dearmor-o/usr/share/keyrings/caddy-stable-archive-keyring.gpgcurl-1sLf'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt'|sudotee/etc/apt/sources.list.d/caddy-stable.listsudoaptupdatesudoaptinstallcaddy方式二:使用 YUM/DNF 包管理器(推荐 CentOS/RHEL)
# CentOS 7sudoyuminstallyum-plugin-coprsudoyum coprenable@caddy/caddysudoyuminstallcaddy# CentOS 8 / RHEL 8sudodnfinstall'dnf-command(copr)'sudodnf coprenable@caddy/caddysudodnfinstallcaddy方式三:官方一键安装脚本(通用 Linux)
curl-fsSLhttps://get.caddyserver.com|bash-spersonal方式四:macOS(使用 Homebrew)
brewinstallcaddy方式五:Windows
- 访问 https://caddyserver.com/download 选择 Windows 版本下载
- 解压到
C:\Caddy目录 - 在命令行中运行
caddy run(推荐新建一个配置文件Caddyfile放在同目录下)
1.2 服务管理命令(systemd)
# 启动 Caddysudosystemctl start caddy# 停止 Caddysudosystemctl stop caddy# 重启 Caddysudosystemctl restart caddy# 重新加载配置(不中断服务,推荐)sudosystemctl reload caddy# 查看运行状态sudosystemctl status caddy# 设置开机自启sudosystemctlenablecaddy# 查看日志sudojournalctl-ucaddy-f1.3 手动运行(开发测试)
# 前台运行(方便调试)caddy run# 使用指定配置文件caddy run--configCaddyfile# 后台运行caddy start# 停止后台进程caddy stop二、核心概念
2.1 配置文件结构(Caddyfile)
Caddyfile 是 Caddy 的默认配置文件,语法非常简洁,没有花括号和分号,采用类似缩进的层级结构。
典型的目录结构(Debian/Ubuntu):
/etc/caddy/ ├── Caddyfile # 主配置文件 ├── sites/ # 站点配置目录(可单独存放多个站点配置) │ ├── example.conf │ └── api.conf ├── data/ # 证书和持久化数据存储目录 └── logs/ # 日志目录2.2 基本配置示例
# 最简单的配置:监听 80 端口,提供静态文件服务 localhost:8080 { root * /var/www/html file_server } # 带 HTTPS 的配置(自动申请证书) example.com { root * /var/www/example file_server } # 反向代理配置 api.example.com { reverse_proxy localhost:3000 }2.3 核心指令
| 指令 | 说明 | 示例 |
|---|---|---|
root | 设置网站根目录 | root * /var/www/html |
file_server | 启用静态文件服务 | file_server |
reverse_proxy | 反向代理到后端服务 | reverse_proxy localhost:3000 |
tls | 自定义 TLS/SSL 配置 | tls /path/to/cert.pem /path/to/key.pem |
redir | URL 重定向 | redir /old /new 301 |
rewrite | 内部 URL 重写 | rewrite /api/* /index.php?{query} |
header | 设置响应头 | header Cache-Control max-age=31536000 |
log | 配置访问日志 | log /var/log/caddy/access.log |
注意:root指令中的*表示匹配所有请求路径,这是 Caddy 的推荐写法,明确指定该站点块处理的路径范围。
三、静态文件服务器
3.1 最简单的静态站点
example.com { root * /var/www/example file_server }3.2 自定义首页文件
example.com { root * /var/www/example file_server { index index.html index.htm default.html } }3.3 启用目录浏览
example.com { root * /var/www/files file_server browse }3.4 隐藏特定文件
example.com { root * /var/www/example file_server { hide .git .env *.conf } }四、反向代理配置
4.1 基本反向代理
反向代理是 Caddy 最常用的功能之一,可以将请求转发给后端服务,同时自动处理 HTTPS。
api.example.com { reverse_proxy localhost:3000 }4.2 带请求头传递
api.example.com { reverse_proxy localhost:3000 { header_up Host {host} header_up X-Real-IP {remote_host} header_up X-Forwarded-For {remote_host} header_up X-Forwarded-Proto {scheme} } }4.3 负载均衡
api.example.com { reverse_proxy localhost:3000 localhost:3001 localhost:3002 { lb_policy round_robin health_uri /health health_interval 30s } }4.4 负载均衡算法
| 算法 | 说明 |
|---|---|
round_robin | 轮询分配(默认) |
least_conn | 分配给连接数最少的后端 |
random | 随机选择 |
first | 选择第一个可用后端 |
ip_hash | 根据客户端 IP 哈希分配(会话保持) |
4.5 后端健康检查
api.example.com { reverse_proxy localhost:3000 localhost:3001 { health_uri /health health_interval 30s health_timeout 5s health_port 8080 } }4.6 WebSocket 代理
ws.example.com { reverse_proxy localhost:3000 { header_up Upgrade {http.request.header.Upgrade} header_up Connection {http.request.header.Connection} } }4.7 代理 Node.js 应用
node.example.com { reverse_proxy localhost:3000 }4.8 代理 Python 应用(Gunicorn)
python.example.com { reverse_proxy localhost:8000 }4.9 代理 PHP-FPM
php.example.com { root * /var/www/php-app php_fastcgi localhost:9000 file_server }五、HTTPS 与 SSL/TLS 配置
5.1 自动 HTTPS(默认开启)
Caddy 默认自动为所有域名申请 HTTPS 证书,无需任何额外配置。
example.com { root * /var/www/example file_server }5.2 自定义证书
example.com { tls /etc/ssl/example.crt /etc/ssl/example.key root * /var/www/example file_server }5.3 使用内部证书(开发环境)
example.com { tls internal root * /var/www/example file_server }5.4 禁用 HTTPS(仅开发测试)
example.com { tls internal # 或使用 http 前缀 } # 或监听 HTTP 端口 example.com:80 { root * /var/www/example file_server }5.5 ACME 配置(Let’s Encrypt)
{ # 使用 Let's Encrypt 的 ACME 服务器(默认) acme_ca https://acme-v02.api.letsencrypt.org/directory # 使用测试环境(避免速率限制) # acme_ca https://acme-staging-v02.api.letsencrypt.org/directory # 设置邮箱(用于证书过期通知) email admin@example.com } example.com { root * /var/www/example file_server }5.6 HTTP 自动跳转 HTTPS
Caddy 默认会自动将 HTTP 请求重定向到 HTTPS:
example.com { root * /var/www/example file_server } # 手动配置 HTTP 跳转 http://example.com { redir https://{host}{uri} 301 }六、性能优化
6.1 Gzip 压缩
example.com { encode gzip zstd root * /var/www/example file_server }6.2 静态文件缓存
example.com { root * /var/www/example header Cache-Control "public, immutable" # 对不同文件类型设置不同缓存时间 @static { file path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.webp } header @static Cache-Control "public, max-age=31536000, immutable" file_server }6.3 启用 ETag
example.com { root * /var/www/example header ETag {file.ETag} file_server }6.4 限制请求大小
example.com { # 限制请求体大小为 10MB request_body { max_size 10MB } reverse_proxy localhost:3000 }6.5 速率限制
example.com { rate_limit { zone dynamic { key {remote_host} events 100 window 1m } } reverse_proxy localhost:3000 }七、日志管理
7.1 访问日志配置
example.com { log { output file /var/log/caddy/access.log format json } root * /var/www/example file_server }7.2 自定义日志格式
example.com { log { output file /var/log/caddy/access.log format filter { wrap console fields { common_log {common_log} duration {duration} request {request} status {status} size {size} } } } root * /var/www/example file_server }7.3 特定路径不记录日志
example.com { log { exclude /health /favicon.ico output file /var/log/caddy/access.log } root * /var/www/example file_server }7.4 错误日志
{ log { output file /var/log/caddy/error.log level ERROR } } example.com { root * /var/www/example file_server }八、安全配置
8.1 安全头部
example.com { header { # 防止 XSS 攻击 X-XSS-Protection "1; mode=block" # 防止 MIME 类型嗅探 X-Content-Type-Options "nosniff" # 防止点击劫持 X-Frame-Options "SAMEORIGIN" # HSTS(强制 HTTPS) Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" # 引用来源策略 Referrer-Policy "strict-origin-when-cross-origin" # 跨域资源分享 Access-Control-Allow-Origin "*" } root * /var/www/example file_server }8.2 IP 访问限制
example.com { @allowed { remote_ip 192.168.1.0/24 10.0.0.1 } handle @allowed { reverse_proxy localhost:3000 } handle { abort } root * /var/www/example file_server }8.3 密码保护(基本认证)
example.com { basicauth { admin $2a$14$5cVnQRncx2V8.0NqVfK3YeGfV8zUkFzSGz5HhXQZxZxZxZxZxZxZx } root * /var/www/private file_server }生成密码哈希:
caddy hash-password--plaintext"your-password"8.4 限制请求方法
example.com { @post { method POST } handle @post { reverse_proxy localhost:3000 } handle { abort } root * /var/www/example file_server }8.5 防止目录遍历
example.com { file_server { hide .git .env .htaccess *.sql *.log } }九、URL 处理
9.1 重定向(Redir)
example.com { # 永久重定向 redir /old-page /new-page 301 # 临时重定向 redir /temporary /new-page 302 # 正则匹配重定向 redir /products/(.*) /shop/$1 301 # 路径前缀重定向 redir /blog/* /news/{uri} 301 }9.2 重写(Rewrite)
example.com { # 将 /api 路径重写到 /v2/api rewrite /api/* /v2/api{path} # SPA 路由处理(所有请求返回 index.html) rewrite * /index.html # 条件重写 @blog { path /blog/* } rewrite @blog /posts/{path} root * /var/www/example file_server }9.3 路径操作
example.com { # 添加路径前缀 handle_path /api/* { rewrite * /v2{path} reverse_proxy localhost:3000 } # 移除路径前缀 handle_path /old/* { rewrite * {path} reverse_proxy localhost:3000 } }9.4 自定义错误页面
example.com { handle_errors { @404 { status 404 } handle @404 { rewrite * /404.html file_server } handle { file_server { root /var/www/errors } } } root * /var/www/example file_server }十、多站点配置
10.1 同一端口配置多个站点(基于域名)
site1.com { root * /var/www/site1 file_server } site2.com { root * /var/www/site2 file_server }10.2 同一域名配置多个站点(基于路径)
example.com { handle /app1/* { root * /var/www/app1 file_server } handle /app2/* { root * /var/www/app2 file_server } handle { root * /var/www/default file_server } }10.3 多配置文件管理
# /etc/caddy/Caddyfile 主文件 import sites/*.conf# /etc/caddy/sites/example.conf example.com { root * /var/www/example file_server }十一、与 Docker 配合使用
11.1 使用官方镜像
# 运行 Caddy 容器dockerrun-d\-p80:80-p443:443\-v$PWD/Caddyfile:/etc/caddy/Caddyfile\-v$PWD/data:/data\-v$PWD/html:/usr/share/caddy\--namecaddy\caddy:alpine11.2 Docker Compose 示例
version:'3.8'services:caddy:image:caddy:alpinecontainer_name:caddy-proxyports:-"80:80"-"443:443"-"443:443/udp"# HTTP/3 QUICvolumes:-./Caddyfile:/etc/caddy/Caddyfile:ro-./data:/data-./config:/config-./html:/usr/share/caddy:rorestart:unless-stoppedapp:image:node:18-alpinecontainer_name:app-serverworking_dir:/appvolumes:-./app:/appcommand:node server.jsexpose:-"3000"11.3 在容器中生成配置文件
# 使用环境变量生成配置dockerrun--rm-itcaddy:alpine caddy run--config/dev/stdin<<EOF example.com { reverse_proxy host.docker.internal:3000 } EOF十二、调试与故障排查
12.1 测试配置文件
# 验证配置语法caddy validate--configCaddyfile# 验证并显示配置caddy validate--configCaddyfile--show12.2 查看日志
# 实时查看服务日志sudojournalctl-ucaddy-f# 查看最近 100 条日志sudojournalctl-ucaddy-n100# 查看错误日志sudojournalctl-ucaddy-perr12.3 调试模式运行
# 前台运行并输出详细日志caddy run--configCaddyfile--debug# 显示所有请求日志caddy run--configCaddyfile--debug--log-format console12.4 常用诊断命令
# 检查 Caddy 是否运行psaux|grepcaddy# 检查端口是否监听sudonetstat-tlnp|grepcaddy# 检查证书状态caddy list-tls# 查看缓存caddy list-certs# 强制重新申请证书caddy renew十三、进阶功能
13.1 HTTP/3 支持
Caddy 默认支持 HTTP/3(基于 QUIC 协议),只需确保端口443的 UDP 也对外开放即可。
{ servers { protocol { experimental_http3 } } } example.com { root * /var/www/example file_server }13.2 使用环境变量
{ env MY_APP_PORT 3000 } api.example.com { reverse_proxy localhost:{$MY_APP_PORT} }或从.env文件加载:
# .env 文件APP_PORT=3000api.example.com { reverse_proxy localhost:{$APP_PORT} }13.3 请求体处理
example.com { # 读取请求体 @post { method POST } handle @post { header Content-Type "application/json" respond `{"message": "Received"}` 200 } }13.4 响应模板
example.com { root * /var/www/example file_server # 动态响应 handle /info { respond `{"host": "{host}", "remote": "{remote_host}", "time": "{now}"}` 200 header Content-Type "application/json" } }13.5 WebSocket 升级
ws.example.com { reverse_proxy localhost:3000 { header_up Upgrade {http.request.header.Upgrade} header_up Connection {http.request.header.Connection} } }13.6 文件上传
upload.example.com { root * /var/www/uploads file_server { browse } # 限制上传大小 100MB request_body { max_size 100MB } }十四、常用命令速查
# 运行 Caddy(前台)caddy run# 指定配置文件运行caddy run--configCaddyfile# 后台运行caddy start# 停止后台运行caddy stop# 重新加载配置caddy reload# 验证配置caddy validate--configCaddyfile# 查看版本caddy version# 查看帮助caddyhelp# 列出所有证书caddy list-certs# 申请证书(手动)caddy renew# 密码哈希生成caddy hash-password--plaintext"password"十五、常见问题与解决
| 问题 | 解决方法 |
|---|---|
| 证书申请失败 | 检查域名 DNS 是否正确;检查防火墙是否开放 80/443 端口;尝试使用acme_ca测试环境 |
| 端口 80/443 被占用 | 停止其他 Web 服务器(如 Nginx/Apache);修改监听端口 |
| 反向代理 502 错误 | 检查后端服务是否运行;检查代理地址是否正确 |
| 静态文件 404 | 检查root路径是否正确;检查文件权限 |
| HTTPS 证书过期 | Caddy 会自动续签,或手动运行caddy renew |
| 无法绑定特权端口(<1024) | 使用 sudo 运行;或使用setcap授权 |
| 日志文件过大 | 配置 logrotate;或使用 systemd 日志管理 |
| 内存占用过高 | 减少同时连接数;使用request_body限制大小 |
| 与 Let’s Encrypt 速率限制冲突 | 使用测试环境;或等待速率限制重置 |
十六、配置模板
16.1 静态站点模板
example.com { # 启用 Gzip 压缩 encode gzip zstd # 设置根目录 root * /var/www/example # 安全头部 header { X-XSS-Protection "1; mode=block" X-Content-Type-Options "nosniff" X-Frame-Options "SAMEORIGIN" Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" Referrer-Policy "strict-origin-when-cross-origin" } # 静态文件缓存 @static { file path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.webp *.woff *.woff2 } header @static Cache-Control "public, max-age=31536000, immutable" # 文件服务 file_server # 日志 log { output file /var/log/caddy/example.com.access.log } }16.2 反向代理模板
api.example.com { # 启用 Gzip 压缩 encode gzip zstd # 反向代理 reverse_proxy localhost:3000 localhost:3001 localhost:3002 { # 负载均衡策略 lb_policy round_robin # 健康检查 health_uri /health health_interval 30s health_timeout 5s # 请求头传递 header_up Host {http.request.host} header_up X-Real-IP {http.request.remote_host} header_up X-Forwarded-For {http.request.remote_host} header_up X-Forwarded-Proto {http.request.scheme} } # 日志 log { output file /var/log/caddy/api.example.com.access.log } }16.3 API 服务模板
api.example.com { # 启用压缩 encode gzip zstd # 安全头部 header { Access-Control-Allow-Origin "*" Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" Access-Control-Allow-Headers "Content-Type, Authorization" X-Content-Type-Options "nosniff" } # 处理预检请求 @options { method OPTIONS } handle @options { respond "" 204 } # API 代理 handle /v1/* { reverse_proxy localhost:3000 { header_up Host {http.request.host} header_up X-Real-IP {http.request.remote_host} header_up Authorization {http.request.header.Authorization} } } # API 文档 handle /docs/* { root * /var/www/api-docs file_server } # 限制请求速率 rate_limit { zone api { key {http.request.remote_host} events 100 window 1m } } # 日志 log { output file /var/log/caddy/api.example.com.access.log format json } }16.4 SPA 应用模板
app.example.com { root * /var/www/spa/dist # 所有请求返回 index.html(SPA 路由支持) route { try_files {path} /index.html } # 静态资源缓存 @static { file path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.webp } header @static Cache-Control "public, max-age=31536000, immutable" file_server }16.5 WordPress 模板
blog.example.com { root * /var/www/wordpress # PHP-FPM 处理 php_fastcgi localhost:9000 # 静态文件缓存 @static { file path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.webp } header @static Cache-Control "public, max-age=31536000, immutable" file_server }十七、资源与参考
- 官方文档: https://caddyserver.com/docs/
- Caddyfile 语法: https://caddyserver.com/docs/caddyfile
- 指令参考: https://caddyserver.com/docs/caddyfile/directives
- GitHub 仓库: https://github.com/caddyserver/caddy
- Caddy 社区论坛: https://caddy.community/
- 模块列表: https://caddyserver.com/download
十八、Caddy vs Nginx 对比
| 特性 | Caddy | Nginx |
|---|---|---|
| 配置复杂度 | 简单直观 | 复杂,学习曲线陡峭 |
| 自动 HTTPS | 默认开启 | 需要额外配置 |
| 证书管理 | 自动申请和续签 | 手动或借助第三方工具 |
| 配置文件语法 | 类似 HCL/JSON,简洁 | 自定义,块状结构 |
| 动态重载 | 支持 | 支持(reload) |
| 性能 | 中等(Go 实现) | 极高(C 实现) |
| 模块化 | 基于插件,易于扩展 | 编译时静态模块 |
| 日志格式 | 灵活,支持 JSON | 自定义格式 |
| WebSocket 支持 | 原生支持 | 需配置 upgrade 头 |
| HTTP/3 | 原生支持 | 需单独编译模块 |
| 适用场景 | 中小型项目、API 网关、开发测试 | 大型高并发、复杂路由、CDN |
结语
Caddy 是一款非常适合现代 Web 开发的服务器,其自动 HTTPS、简单配置和丰富功能让开发者能够快速部署安全可靠的服务。无论是静态网站、反向代理还是 API 网关,Caddy 都能以最少的配置完成工作。
建议从最简单的静态站点开始,逐步探索反向代理、负载均衡等高级功能。Caddy 的官方文档非常完善,遇到问题时可以随时查阅。
祝使用愉快!🚀