多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Caddy 使用指南

Caddy 使用指南 Caddy 使用指南Caddy 是一款用 Go 语言编写的现代 Web 服务器以配置极其简单和自动化 HTTPS为核心特色。与 Nginx 或 Apache 相比Caddy 最大的优势在于默认开启 HTTPS它会自动从 Let’s Encrypt 申请并续签 SSL/TLS 证书让网站一键拥有“小绿锁”。一、安装与基本管理1.1 各平台安装方式方式一使用 APT 包管理器推荐 Ubuntu/Debian# 添加 Caddy 官方仓库curl-1sLfhttps://dl.cloudsmith.io/public/caddy/stable/gpg.key|sudogpg--dearmor-o/usr/share/keyrings/caddy-stable-archive-keyring.gpgcurl-1sLfhttps://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 coprenablecaddy/caddysudoyuminstallcaddy# CentOS 8 / RHEL 8sudodnfinstalldnf-command(copr)sudodnf coprenablecaddy/caddysudodnfinstallcaddy方式三官方一键安装脚本通用 Linuxcurl-fsSLhttps://get.caddyserver.com|bash-spersonal方式四macOS使用 Homebrewbrewinstallcaddy方式五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 配置文件结构CaddyfileCaddyfile 是 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/htmlfile_server启用静态文件服务file_serverreverse_proxy反向代理到后端服务reverse_proxy localhost:3000tls自定义 TLS/SSL 配置tls /path/to/cert.pem /path/to/key.pemredirURL 重定向redir /old /new 301rewrite内部 URL 重写rewrite /api/* /index.php?{query}header设置响应头header Cache-Control max-age31536000log配置访问日志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 应用Gunicornpython.example.com { reverse_proxy localhost:8000 }4.9 代理 PHP-FPMphp.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{ # 使用 Lets Encrypt 的 ACME 服务器默认 acme_ca https://acme-v02.api.letsencrypt.org/directory # 使用测试环境避免速率限制 # acme_ca https://acme-staging-v02.api.letsencrypt.org/directory # 设置邮箱用于证书过期通知 email adminexample.com } example.com { root * /var/www/example file_server }5.6 HTTP 自动跳转 HTTPSCaddy 默认会自动将 HTTP 请求重定向到 HTTPSexample.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-age31536000, immutable file_server }6.3 启用 ETagexample.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; modeblock # 防止 MIME 类型嗅探 X-Content-Type-Options nosniff # 防止点击劫持 X-Frame-Options SAMEORIGIN # HSTS强制 HTTPS Strict-Transport-Security max-age31536000; 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--plaintextyour-password8.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 重定向Redirexample.com { # 永久重定向 redir /old-page /new-page 301 # 临时重定向 redir /temporary /new-page 302 # 正则匹配重定向 redir /products/(.*) /shop/$1 301 # 路径前缀重定向 redir /blog/* /news/{uri} 301 }9.2 重写Rewriteexample.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.8services: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:-300011.3 在容器中生成配置文件# 使用环境变量生成配置dockerrun--rm-itcaddy:alpine caddy run--config/dev/stdinEOF 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_PORT3000api.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--plaintextpassword十五、常见问题与解决问题解决方法证书申请失败检查域名 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; modeblock X-Content-Type-Options nosniff X-Frame-Options SAMEORIGIN Strict-Transport-Security max-age31536000; 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-age31536000, 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.htmlSPA 路由支持 route { try_files {path} /index.html } # 静态资源缓存 static { file path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.webp } header static Cache-Control public, max-age31536000, 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-age31536000, immutable file_server }十七、资源与参考官方文档: https://caddyserver.com/docs/Caddyfile 语法: https://caddyserver.com/docs/caddyfile指令参考: https://caddyserver.com/docs/caddyfile/directivesGitHub 仓库: https://github.com/caddyserver/caddyCaddy 社区论坛: https://caddy.community/模块列表: https://caddyserver.com/download十八、Caddy vs Nginx 对比特性CaddyNginx配置复杂度简单直观复杂学习曲线陡峭自动 HTTPS默认开启需要额外配置证书管理自动申请和续签手动或借助第三方工具配置文件语法类似 HCL/JSON简洁自定义块状结构动态重载支持支持reload性能中等Go 实现极高C 实现模块化基于插件易于扩展编译时静态模块日志格式灵活支持 JSON自定义格式WebSocket 支持原生支持需配置 upgrade 头HTTP/3原生支持需单独编译模块适用场景中小型项目、API 网关、开发测试大型高并发、复杂路由、CDN结语Caddy 是一款非常适合现代 Web 开发的服务器其自动 HTTPS、简单配置和丰富功能让开发者能够快速部署安全可靠的服务。无论是静态网站、反向代理还是 API 网关Caddy 都能以最少的配置完成工作。建议从最简单的静态站点开始逐步探索反向代理、负载均衡等高级功能。Caddy 的官方文档非常完善遇到问题时可以随时查阅。祝使用愉快
返回列表