Caddy

默认启用 HTTPS

让每个站点
跑在 HTTPS 上

Caddy 是用 Go 写成的服务器平台。写下站点地址,证书的签发与续期、HTTP 到 HTTPS 的跳转,全部由它自动完成。

$caddy run

example.com

等待证书

HTTP/1.1HTTP/2HTTP/3

启动日志为真实输出格式的示例,域名与时间为示意。

用 Go 实现,官方提供 Docker 镜像,证书由公共 CA 签发,与更多项目协同工作。

配置现场

写下地址,剩下的是 Caddy 的事

Caddyfile 只描述你要什么。证书、跳转、压缩、协议协商都不必写出来,因为它们本来就开着。

example.com {
	root * /var/www/example
	file_server
	encode gzip
}

Caddy 的原生配置是 JSON,Caddyfile 只是它的一种写法。

Caddy 自动完成

  • 向公共 ACME CA 申请 example.com 的证书
  • 80 端口的 HTTP 请求跳转到 HTTPS
  • 按 Accept-Encoding 协商 gzip 压缩
  • 证书到期前在后台自动续期

同一件事,两种写法

把一个目录以 HTTPS 提供出去,并顺带压缩与跳转。

Caddyfile4 行
example.com {
	root * /var/www
	file_server
	encode gzip
}
nginx.conf27 行
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name example.com;

    root /var/www;
    gzip on;
    gzip_types text/plain text/css application/json;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_session_cache   shared:SSL:10m;

    location / {
        try_files $uri $uri/ =404;
    }
}

两者的能力并不等价:nginx 侧还需要额外的工具去申请证书,并配置定时任务完成续期。Caddy 把这部分放进了服务器内部,作为默认行为的一部分。

协议

HTTP/1.1、HTTP/2、HTTP/3 默认全开

不需要开关,也不需要额外的模块。客户端支持哪个就用哪个,握手的时候谈好。

8 个资源 · 共享时间轴 · 时序为示意,非基准测试数据

HTTP/1.1

6 条 TCP 连接

每条连接各自握手

  1. 01
  2. 02
  3. 03
  4. 04
  5. 05
  6. 06
  7. 07
  8. 08
  • 超过并发上限的请求要排队
  • 连接内串行,一个慢请求堵住一条连接

HTTP/2

1 条 TCP 连接

1 次 TLS 握手

  1. 01
  2. 02
  3. 03
  4. 04
  5. 05
  6. 06
  7. 07
  8. 08
  • 所有请求在同一条连接上多路复用
  • 丢包会让全部流一起等重传

HTTP/3

1 条 QUIC 连接

0-RTT 恢复

  1. 01
  2. 02
  3. 03
  4. 04
  5. 05
  6. 06
  7. 07
  8. 08
  • 基于 UDP,握手与传输不再互相牵制
  • 丢包只影响丢的那一条流

它还能做什么

自动 HTTPS

公网域名向公共 ACME CA 申请证书,内网域名与 IP 由 Caddy 自己的本地 CA 签发。证书在到期前于后台续期,不影响在线请求。

主题
example.com
颁发者
Let's Encrypt / ZeroSSL
有效期
90 天
续期
到期前自动完成
回退
一家 CA 失败则换下一家
挑战方式
HTTP-01 / TLS-ALPN / DNS-01

一个二进制

编译到所有主流平台,运行时没有外部依赖。

$ file caddy

ELF 64-bit, statically linked

$ ldd caddy

not a dynamic executable

模块化

从 HTTP 处理器到存储介质都是模块,按需编译进二进制。

  • http.handlers.reverse_proxy
  • http.handlers.file_server
  • http.handlers.static_response
  • http.encoders.zstd
  • http.matchers.path_regexp
  • tls.issuance.acme
  • tls.issuance.internal
  • logging.encoders.json
  • storage.file_system

在线改配置

通过管理端点换配置,零停机;新配置有问题就回滚到上一份。

curl -X POST localhost:2019/load \
  -H "Content-Type: application/json" \
  -d @caddy.json

不止一种写法

原生配置是 JSON,配置适配器可以把别的格式转成它。

  • Caddyfile内置
  • JSON 5适配器
  • YAML适配器
  • NGINX 配置适配器

已经在生产里跑了很多年

数万亿

已服务的 HTTPS 请求

数百万

纳管的 TLS 证书

数十万

单个实例可承载的站点

多个 Caddy 实例共用同一份存储时,会自动协同证书管理,组成集群。规模数据来自官方项目说明。

装上它

挑一个顺手的方式。官方包只含标准模块,需要插件时用 xcaddy 从源码构建。

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

官方包会自动以名为 caddy 的 systemd 服务启动运行。

从入门指南开始,把它跑起来

官方建议所有人都先读一遍入门指南,不管你有多少经验。