
很多站长在给网站上线 HTTPS 时都遇到过同样的折腾:证书要手动申请,到期前要记得续期,Nginx 配置文件里 HTTP 跳转、证书路径、加密参数一项都不能写错。一旦忘记续期,浏览器就会给访客弹出刺眼的安全警告。如果你正在维护多个站点或内部服务,这个问题会被成倍放大。
本文将教你如何用 Caddy 解决这个问题。Caddy 是一个开源的轻量 Web 服务器,最大的特点是默认全自动处理 HTTPS:只要你把域名指向服务器,它就会自动向证书颁发机构申请 SSL(安全传输协议)证书,并在到期前自动续期,整个过程不需要人工介入。我们会从安装讲起,完成一个反向代理的真实配置,最后对比它与 Nginx 加 Certbot 组合的差异,帮助你判断它是否适合自己的业务场景。
一、Caddy 是什么,为什么它适合中小站点
Caddy 使用 Go 语言编写,编译后是单个二进制文件,没有外部依赖。与动辄配合多个模块和插件的的传统方案相比,它的部署成本非常低:把二进制文件放到服务器上,写十几行配置,服务就能跑起来。
它适合中小站点的原因主要有三点。第一,自动 HTTPS 是默认行为,不是可选插件,域名解析到位即可自动签发证书。第二,配置语法简洁,一个域名一个区块,反向代理通常只需要一行 reverse_proxy。第三,资源占用低,在 1 核 1G 的入门级 VPS(虚拟专用服务器)上运行绰绰有余,内存占用通常在 30MB 左右,对预算有限的用户很友好。
当然,它也有边界。如果你的架构依赖大量 Nginx 生态模块(例如复杂的 Lua 扩展或精细的负载均衡策略),Caddy 的覆盖能力有限;超大规模集群也不是它的主场。对个人博客、企业官网、外贸站点和内部工具的反代场景,它是目前省心程度最高的选择之一。
二、准备工作与安装

开始之前,先确认两件事:一台可以 SSH 登录的服务器,以及一个 DNS(域名解析系统)解析已指向这台服务器公网 IP 的域名。自动 HTTPS 依赖域名验证,解析没到位,证书就签不下来。建议先在本地用 dig 或在线工具确认 A 记录已经生效,再继续安装,可以省掉后面排查证书失败的多数时间。
以 Ubuntu/Debian 为例,使用官方软件源安装:
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
CentOS、RHEL、Fedora 系统也有对应的官方仓库,命令类似。安装完成后,Caddy 会注册为 systemd 服务并立即启动,默认会监听 80 和 443 端口。此时用 systemctl status caddy 确认服务处于 active 状态,并在云服务商的安全组里放行 80、443 端口——80 端口不能省,证书颁发的 HTTP 验证和跳转都依赖它。
如果你更喜欢容器化部署,也可以直接用官方镜像:docker run -d -p 80:80 -p 443:443 -v caddy_data:/data -v $PWD/Caddyfile:/etc/caddy/Caddyfile caddy。注意一定要把 /data 卷持久化,证书和账号信息都存在里面,容器重建后没有这个卷就会重新签发,次数多了可能触发证书颁发机构的频率限制。如果你对服务器初始化和安全加固还不熟悉,可以先浏览我们的服务器运维栏目补齐基础。
三、编写 Caddyfile:一个真实的反向代理配置
Caddy 的全部配置集中在一个叫 Caddyfile 的文本文件里,默认路径是 /etc/caddy/Caddyfile。我们以最常见的场景为例:后端跑着一个 Node.js 应用,监听在本机 3000 端口,希望通过 example.com 以 HTTPS 访问它。
配置只需三行:
example.com {
reverse_proxy 127.0.0.1:3000
}
保存后执行 sudo systemctl reload caddy 让配置生效。reload 是平滑操作,不会中断现有连接。此时 Caddy 会自动完成几件事:向 Let’s Encrypt 申请 example.com 的证书、把 HTTP 请求 301 跳转到 HTTPS、对 3000 端口的转发自动带上正确的 Host 和 X-Forwarded-For 头。用浏览器打开域名,地址栏出现锁形图标就说明全链路已经通了。
日常使用中还有几个高频需求。比如后端服务分布在多台机器上做负载均衡,写成多行地址即可:
example.com {
reverse_proxy 10.0.0.2:3000 10.0.0.3:3000
}
Caddy 默认采用随机轮询策略,节点故障会自动剔除。再比如同一个域名下按路径把不同前缀转发给不同服务:handle_path /api/* { reverse_proxy 127.0.0.1:8000 },handle 与 reverse_proxy 组合起来就能覆盖绝大多数网关类需求。静态文件服务同样是一行的事:root * /var/www/html 加 file_server。
配置写完不要忘了验证这一步。caddy validate --config /etc/caddy/Caddyfile 可以在不重启服务的情况下检查语法,caddy fmt 则会自动整理缩进。养成先 validate 再 reload 的习惯,可以避免把语法错误直接推到线上导致服务中断。
四、部署验证与常见问题排查

部署完成后,建议按顺序做三项验证。第一项看证书:在浏览器开发者工具的安全面板里确认证书由 Let’s Encrypt 签发、有效期约 90 天。第二项看跳转:用 curl -I http://example.com 检查返回是否为 301 且 Location 指向 https 地址。第三项看转发:访问域名确认拿到的是后端应用的响应,而不是 Caddy 的默认欢迎页。
如果证书签发失败,多数情况集中在三个原因上。端口未放行:80 或 443 被安全组、系统防火墙拦截,验证请求进不来,可用 sudo ufw status 和云控制台安全组逐项核对。DNS(域名解析系统)未生效:域名还没解析到本机 IP,证书机构从公网访问不到验证路径,用 dig example.com +short 对照服务器公网 IP 即可确认。80 端口被占用:安装过 Nginx 或 Apache 的机器上常见,用 sudo lsof -i :80 找到占用进程并停用,再重启 Caddy。
看日志是定位问题的最快路径。Caddy 的运行日志在 systemd 里,用 journalctl -u caddy -f --no-pager 实时跟踪,证书申请、验证失败、配置重载都会记录在案。遇到 “challenge failed” 字样时,对照上面三个原因逐项排查基本都能解决。反代跑通之后,如果你还想压榨首字节的响应速度,可以接着阅读这篇 TTFB 主机优化指南。
五、Caddy 与 Nginx:如何选择

同样是”反代 + HTTPS”这个需求,传统路线是 Nginx 加 Certbot:Nginx 负责代理和跳转,Certbot 负责证书申请与续期,两者通过定时任务和配置钩子协作。这条路线生态成熟、资料丰富,但组件多、配置长,一个域名通常要维护 server 块、证书路径、续期钩子三处内容。
Caddy 把这两件事合并成了一件。证书的申请、续期、跳转全部内建,Caddyfile 一个区块描述一个站点,同样规模的多站点配置通常只有 Nginx 版本的三分之一长度。对于站点数量在个位数到十几个、团队没有专职运维的场景,Caddy 的总持有成本明显更低。
选择上可以参考这样一条经验线:如果你的需求以反代、静态文件、自动 HTTPS 为主,追求省心和低维护,Caddy 是更合适的起点;如果你需要细粒度的流量控制、复杂重写规则,或者团队已经积累了大量 Nginx 配置资产,继续使用 Nginx 加 Certbot 也完全合理。两者都支持平滑迁移,不必担心被锁定。
总结与下一步行动
回顾整个过程:安装 Caddy、写一个三行的 Caddyfile、reload 生效,证书申请、HTTPS 跳转和反向代理就全部就位。相比传统方案的证书申请、续期配置、Nginx server 块三线维护,它把复杂度压缩到了一个文件里。
我们的建议是分两步走。第一步,在测试域名或内部工具上先用 Caddy 跑一个反代,验证证书签发和转发行为符合预期;这一步不涉及生产流量,试错成本几乎为零。第二步,把成熟的站点逐步迁移过来,迁移前记得用 caddy validate 检查配置,并保留旧配置的备份以便快速回滚。如果你在为这套方案挑选运行环境,可以考虑 Hostease 的 WordPress 主机与独立服务器方案,配合 Caddy 的自动 HTTPS,能让站点安全和维护效率同时上一个台阶。