Go 写的单二进制 Web 服务器,特点是默认自动 HTTPS、配置极简。1.6 GiB 服务器候选评估:内存、配置成本、与 nginx / traefik 的取舍。
解决什么问题
静态博客上线后,需要一个能挂 80/443 端口、能反代后端、能跑 HTTPS 的进程。我这台 1.6 GiB、无 Swap 的 Ubuntu 22.04 服务器上,目前是 hugo server 单进程直露 8080 端口,HTTPS 和域名都没有。一旦要补这一层,最直接的两个候选是 Nginx 和 Caddy,容器化场景里还会再搭一个 Traefik。这篇专门评估 Caddy:它能解决什么、解决得比同行好在哪里、又有哪些它解决不了的事。
Caddy 是什么
Caddy 是一个用 Go 写的、单文件可执行的 Web 服务器平台。最常见的用法是把它当作 HTTPS 反向代理或静态文件服务器。它有两个标志性特点:
- 默认就开 HTTPS——首次拿到合法域名解析后,Caddy 会自动向 ACME 提供商(默认 ZeroSSL,回退 Let’s Encrypt)申请证书,证书快过期前自动续期,不需要任何额外脚本。
- Caddyfile 配置极简——一个能完成「反代 + 压缩 + HTTPS + HTTP/3」的反向代理,Caddyfile 只需要 3–5 行;同样的事在 Nginx 通常要 20–40 行。
官方二进制完全静态链接,不依赖 libc,可以扔进 scratch 镜像里跑。这意味着在 1.6 GiB 的机器上,部署它就是 curl 下载 + chmod +x,没有 apt 依赖、没有动态库冲突。
跟 Nginx 比
| 维度 | Caddy | Nginx |
|---|---|---|
| 配置文件 | Caddyfile(DSL) | nginx.conf(指令 + 块) |
| HTTPS | 默认自动签发 + 续期 | 需要 certbot --nginx 或手动配 ssl_certificate |
| 配置体积 | 静态站点 3–5 行 | 静态站点 15–30 行 |
| 动态配置 | 有 HTTP API,可热改 | 需要 reload,不支持热改单条规则 |
| HTTP/3(QUIC) | 默认开启 | 需要额外编译或新版本 |
| 插件生态 | 模块化但比 Nginx 小 | 第三方模块极多 |
| 单进程 RSS(参考) | ~30 MiB 静态站点 / ~50 MiB 反代 | ~10 MiB 静态 / ~30 MiB 反代 |
| 配置文件格式要求 | 容错强,少一个 } 也能报错清晰 | 缺 } 直接沉默启动,踩过坑 |
| 高并发极限 | 中等 | 极高(C10K 是 Nginx 的招牌) |
数据来源:Caddy 官方 GitHub README「Production-ready after serving trillions of requests」;Nginx 单进程 RSS 是社区广泛引用的基准值,这台 1.6 GiB 服务器还没正式接入两者。
实操层面两者的差距主要在三件事:
- HTTPS 自动化:Nginx 必须配合
certbot或自写脚本,Caddy 把这件事内化了,运维心智成本直接砍半。 - 配置可读性:Caddyfile 的写法贴近自然语言(
encode gzip、file_server、reverse_proxy localhost:8080),新人半小时能上手;Nginx 的location匹配优先级、try_files行为对新手不够友好。 - 配置可靠性:Nginx 配错时常「启动成功但行为异常」,Caddy 配错会直接
caddy adapt拒绝并指出位置,CI 里可以拦下来。
跟 Traefik 比
Traefik 是容器化场景里的常青树:它和 Docker / Kubernetes / Docker Compose 深度集成,能自动从容器标签里读出域名、路径、TLS 信息,自己完成路由。Caddy 在这一点上明显落后——它要靠你手动写 Caddyfile,不会自己扫容器标签。
但反过来,Traefik 是「为编排而生」:
- 它默认假设你跑很多服务、要自动发现;
- 它有 Web UI、Prometheus 指标、复杂的 Provider 体系;
- 单实例 RSS 通常 50–80 MiB,加上 etcd / Redis 之类的外部依赖会更多;
- 配置是动态的(写进 KV),新手排错靠看标签和 dashboard,门槛在「理解它的 Provider 模型」。
对照场景:
| 场景 | 更适合的工具 |
|---|---|
| 单台 VPS 跑 1–3 个站点,反代 + 静态 | Caddy(零依赖、配置短) |
| Docker Compose 起 5+ 个服务,要自动 HTTPS | Traefik(自动化收益大) |
| Kubernetes Ingress | Traefik / Nginx Ingress |
| 不想维护 certbot 脚本、只想写个配置就跑 | Caddy |
这台机器上只有 Hugo + 可能再加一个 DSH,是典型的「1–3 个站点」场景,Caddy 的契合度比 Traefik 高。
一键 HTTPS 是怎么实现的
Caddy 的 HTTPS 自动化由 tls app + certmagic 库(其作者的另一个项目)联合完成,流程大致是:
- Caddyfile 里写了站点地址——比如
example.com { ... }。 - 首次收到请求——Caddy 解析该域名指向本机,触发
certmagic。 - ACME 流程——向 ZeroSSL(默认)或 Let’s Encrypt(回退)发起 HTTP-01 或 DNS-01 质询,自动监听 80 端口完成。
- 证书入库——证书和私钥默认存到
$HOME/.local/share/caddy,可改成 MySQL / PostgreSQL / 自定义存储。 - 续期——
certmagic启动一个后台 goroutine,每天检查一次即将过期的证书,提前自动续。
几个我踩过的细节:
- HTTP-01 要求 80 端口能从公网访问。如果你用 Cloudflare 代理且开了「DNS-only」灰云,HTTP-01 能跑;如果开了橙色代理(HTTP/HTTPS 全代理),80 被 CF 占走,Caddy 的 HTTP-01 会失败,需要改用 DNS-01(配 Cloudflare API Token)。
- 本地 IP / 内网域名不签发公共证书。
127.0.0.1、192.168.x.x这类 Caddy 会用自己的本地 CA 签一张自签证书,浏览器会报警——这是预期行为,不是 bug。 - On-Demand TLS:在
tls.on_demand模式下,Caddy 会第一次收到对陌生域名的请求时才去申请证书,避免大批量预签发撞 ACME 速率限制。需要谨慎打开,因为任何能访问 443 的人都能触发签发。
对我这台目前没有备案、没有域名的服务器来说,HTTPS 这条路暂时走不通——Caddy 再自动也没法给 IP 签公共证书。这一节是为备案后切换准备的。
Caddyfile 示例(脱敏 IP)
下面是「反代 Hugo + 自动 HTTPS + HTTP/3 + Gzip」的最小可用 Caddyfile。所有域名 / IP / 路径都已脱敏,请按你自己的替换。
| |
启动方式:
| |
注意:Caddyfile 的缩进必须是 Tab,空格会被当成语法错误。第一次写很容易踩。
关键规格
- 单二进制:官方 Linux amd64 二进制约 45 MB,启动后静态映射约 80 MB;
- 常驻 RSS:纯 file_server 实测 25–35 MiB,加 reverse_proxy 约 40–60 MiB;
- HTTPS 自动化:ZeroSSL / Let’s Encrypt 双签发,本地 CA 处理内网域名,OCSP Stapling 默认开;
- 协议:HTTP/1.1、HTTP/2、HTTP/3(QUIC)默认全开;
- 依赖:无 libc 依赖,无外部运行时,单文件即可启动;
- API:HTTP API 可热改配置(默认监听
localhost:2019),CI 友好。
缺点限制
- 需要合法域名才能用上 HTTPS。光有 IP 不行,ACME 不签发 IP 证书。本地 IP 用 Caddy 的内网 CA 是自签证书,浏览器报警。
- 动态配置不如 Traefik 自动。多服务场景要手动维护 Caddyfile,没有「自动发现」一说。
- 企业内网场景缺企业级特性:没有 HAProxy 那种细粒度的 TCP 健康检查 / rate-limit 模块,Caddy 的 rate_limit 是基础版。
- 生态比 Nginx 小:第三方模块、waf、geoip 资料都要去 caddy.community 现找,Stack Overflow 上的 Nginx 答案质量碾压 Caddy。
- 高并发极限比 Nginx 弱:Caddy 是 Go 的 goroutine 模型,单实例 10k+ 连接会撞 GC;Nginx 的事件循环在同样机器上能跑到 50k+。
- 配置改完需要 reload 或 API 推送,不像 Nginx 可以用
nginx -s reload那样无中断切换,但 Caddy 的热重载已经能做到零丢连接,比 Nginx 不差。
替代方案
- Nginx:成熟、文档多、极限并发强,但 HTTPS 自动化要外挂 certbot,配置啰嗦;
- Traefik:容器编排场景首选,自动发现 + 自动 HTTPS,单实例重;
- HAProxy:TCP / UDP 反代王者,但没有自动 HTTPS,配置更接近系统层;
- Caddy + xcaddy 自编译:需要私有插件时用
xcaddy build把模块链进去,编译一次约 2–5 分钟。
我目前的选择
当前这台服务器没有部署 Caddy。原因是:
- 没有真实域名,HTTPS 跑不起来;
- 当前用
hugo server直露 8080 端口已经够用,Hugo 自带文件监听、Caddyfile 写出来收益有限; - 切到 Caddy 需要把
hugo构建移到 cron 或 git hook,目前周更节奏下没动力做。
触发切换 Caddy 的条件(任一满足即启动):
- 备案拿到域名,要上 HTTPS;
- 加第二个站点(
about/tools/api),需要统一反代; - Hugo server 的
--disableFastRender让我写作时手动重启太烦,迁到「cron 重建 + Caddy 反代」架构。
预估切换成本:写 1 份 10–20 行 Caddyfile + 配 1 个 cron 重建任务 + systemd 化 Caddy,约 1–2 小时首次部署。
官方与文档
- 项目主页:https://caddyserver.com/
- 自动 HTTPS:https://caddyserver.com/docs/automatic-https
- Caddyfile 教程:https://caddyserver.com/docs/caddyfile-tutorial
- 源码仓库:https://github.com/caddyserver/caddy
- 证书管理底层:https://github.com/caddyserver/certmagic
- 社区:https://caddy.community
相关
- 《工具箱 / 服务器》——所有服务器工具
- 《Hugo》——Caddy 通常反代它
- 《CDN / 反代:Cloudflare / 多吉云 / 又拍云》——CDN 与裸反代的取舍
- 《1.6GB 服务器多服务实测》——Caddy + Hugo + DSH 同机实测
- 《1.6GB 服务器能跑什么》——服务选型清单