Caddy 是一款用 Go 语言编写的开源 Web 服务器,以其自动 HTTPS 功能、简洁的配置以及强大的功能而闻名。它被设计成现代 Web 的瑞士军刀,能够胜任静态文件服务、反向代理、负载均衡、API 网关等多种任务,并且在安全性和易用性方面表现出色。

“Caddy 是未来 Web 服务器的样子:默认安全、易于管理、功能强大,并且能够自动处理 HTTPS 证书的申请和续期,让你的网站在几秒钟内上线并享受加密连接。”


一、Caddy 简介

1.1 什么是 Caddy?

Caddy 是一个高性能、可扩展的 Web 服务器,其核心特性包括:

  • 自动 HTTPS:这是 Caddy 最吸引人的特性之一。对于绝大多数公共可访问的域名,Caddy 可以自动从 Let’s Encrypt 申请、配置和续期 SSL/TLS 证书,无需手动干预。
  • 配置简洁:Caddyfile 配置文件语法非常直观易懂,相比 Nginx 和 Apache 更加简洁。
  • HTTP/2 和 HTTP/3 支持:Caddy 默认启用 HTTP/2,并且是首批支持 QUIC (HTTP/3) 的服务器之一。
  • 模块化架构:Caddy 2 采用了高度模块化的设计,可以通过插件扩展其功能,以适应各种复杂的场景。
  • 作为库使用:Caddy 不仅仅是一个 Web 服务器,其核心模块也可以作为 Go 库嵌入到你的应用程序中。
  • 跨平台:由于 Go 语言的特性,Caddy 可以轻松地在 Linux、Windows、macOS 甚至 ARM 设备上运行。

1.2 为什么选择 Caddy?

  • 极易上手:如果你需要快速搭建一个 HTTPS 网站或反向代理,Caddy 的配置复杂度远低于 Nginx 或 Apache。
  • 默认安全:自动 HTTPS 解决了大部分用户在配置 SSL 证书时的痛点,确保了数据传输的安全性。
  • 现代协议支持:HTTP/2 和 HTTP/3 的支持意味着更好的性能和用户体验。
  • 灵活强大:虽然配置简洁,但其模块化和插件系统足以应对复杂的生产环境需求。
  • 单一二进制文件:部署极其简单,只需下载一个可执行文件即可运行。

二、Caddy 的安装

Caddy 的安装非常简单,因为它是一个单一的可执行文件。

2.1 通过官方脚本 (Linux/macOS)

这是最推荐的方式,会自动检测你的系统并安装最新版本。

1
2
3
4
5
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/dist/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/dist/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-main.list
sudo apt update
sudo apt install caddy

或者使用 Caddy 官方更通用的安装脚本:

1
2
3
4
curl -sL 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -sL '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 并配置为系统服务。

2.2 通过 Docker

Docker 是部署 Caddy 的另一种流行方式,尤其适用于容器化环境。

1
2
3
4
5
6
7
docker run -d \
--name caddy \
-p 80:80 \
-p 443:443 \
-v /path/to/Caddyfile:/etc/caddy/Caddyfile \
-v /path/to/caddy_data:/data \
caddy/caddy:latest
  • --name caddy: 给容器命名。
  • -p 80:80: 映射 HTTP 端口。
  • -p 443:443: 映射 HTTPS 端口。
  • -v /path/to/Caddyfile:/etc/caddy/Caddyfile: 将你本地的 Caddyfile 配置文件挂载到容器中。
  • -v /path/to/caddy_data:/data: 将 Caddy 的数据目录(包含 SSL 证书、OCSP 缓存等)挂载到宿主机,便于持久化和备份。
  • caddy/caddy:latest: 使用最新的 Caddy 官方 Docker 镜像。

2.3 手动下载

你可以从 Caddy 官方下载页面 下载预编译的二进制文件,选择适合你操作系统的版本。解压后即可直接运行。

三、Caddyfile 配置详解

Caddy 的核心配置是通过 Caddyfile 文件完成的。它的语法简洁而强大。

3.1 基础语法

一个 Caddyfile 包含一个或多个站点块 (site block),每个站点块定义了一个网站或服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 这是一个注释

# 站点块定义,可以包含域名、端口等
your-domain.com {
# 指令
root * /srv/www
file_server

# 其他指令...
}

:8080 { # 监听 8080 端口
respond "Hello from Caddy!"
}

3.2 常用指令

3.2.1 静态文件服务

这是最基本的用法,用于部署静态网站。

1
2
3
4
your-domain.com {
root * /srv/www # 网站根目录
file_server # 启用文件服务器
}
  • root * <path>: 指定静态文件的根目录。* 表示适用于所有请求。
  • file_server: 启用 Caddy 的文件服务器功能。

3.2.2 反向代理

将请求转发到后端服务,常见于与后端应用服务器(如 Node.js, Python, Java 等)配合使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
api.your-domain.com {
# 将所有请求代理到本地 8000 端口
reverse_proxy localhost:8000
}

# 负载均衡示例
app.your-domain.com {
reverse_proxy backend1.local:8080 backend2.local:8080 {
# 负载均衡策略 (可选, 默认为 LeastConn)
lb_policy random
# 健康检查 (可选)
health_uri /health
health_interval 10s
}
}
  • reverse_proxy <upstream_address>...: 将请求代理到指定的上游地址。可以指定多个地址进行负载均衡。
  • lb_policy: 设置负载均衡策略,如 randomround_robinleast_conn 等。

3.2.3 自动 HTTPS

Caddy 的杀手锏,无需任何额外配置,只需指定域名。

1
2
3
4
5
6
7
8
9
10
# 如果你的域名是 example.com,Caddy 会自动为它申请并配置 HTTPS 证书
example.com {
root * /srv/example
file_server
}

# 多个域名
blog.example.com admin.example.com {
reverse_proxy localhost:3000
}

注意:自动 HTTPS 需要 Caddy 能够通过 80 或 443 端口被外部访问,以完成 Let’s Encrypt 的域名验证。

3.2.4 重定向

1
2
3
4
5
6
7
8
9
10
# 将所有来自 www.old-domain.com 的请求重定向到 new-domain.com
www.old-domain.com {
redir https://new-domain.com{uri} permanent
}

# 将 HTTP 请求强制重定向到 HTTPS (Caddy 默认已经开启了,但为了演示可以这样写)
http://your-domain.com {
# respond "This site must be accessed over HTTPS."
redir https://{host}{uri}
}
  • redir <destination> [status_code]: 重定向请求。permanent 相当于 HTTP 301。

3.2.5 路径匹配

Caddy 使用基于请求路径的匹配器来选择要执行的指令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
your-domain.com {
# 根路径的文件服务器
root * /srv/www
file_server

# /api 路径下的请求代理到后端
handle /api/* {
reverse_proxy localhost:8000
}

# /admin 路径下的请求需要认证
handle /admin/* {
basicauth {
user_account JDUxNj... # 密码加密哈希
}
reverse_proxy localhost:8081
}
}
  • handle <matcher>: 匹配特定的请求,并只对匹配的请求执行其内部的指令。
    • * 表示所有请求。
    • /path/* 表示匹配 /path/ 开头的所有请求。
    • /some/exact/path 表示匹配精确路径。

3.3 进阶配置

3.3.1 环境变量

你可以在 Caddyfile 中使用环境变量。

1
2
3
{$APP_DOMAIN} {
reverse_proxy {$APP_BACKEND_ADDRESS}
}

通过 CADDY_APP_DOMAIN=my-app.com CADDY_APP_BACKEND_ADDRESS=localhost:3000 caddy run 方式启动。

3.3.2 JSON 配置 (GCL - Go Caddy Language)

Caddy 2 的底层配置格式是 JSON。Caddyfile 只是 JSON 配置的一个简化抽象。对于非常复杂的场景或需要动态配置时,可以直接使用 JSON 配置。

你可以用 caddy adapt --config Caddyfile --pretty 将 Caddyfile 转换为 JSON。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [":443"],
"routes": [
{
"match": [{"host": ["example.com"]}],
"handle": [
{"handler": "file_server", "root": "/srv/www"}
],
"terminal": true
}
]
}
}
}
}
}

四、Caddy 的运行与管理

4.1 命令行操作

  • 启动 Caddy
    1
    2
    caddy run --config Caddyfile --watch # 启动并监听 Caddyfile 文件的变化
    caddy start # 以后台服务方式启动 (需要 Caddy 管理 socket)
  • 优雅停止
    1
    caddy stop
  • 重载配置
    1
    caddy reload --config Caddyfile
  • 检查配置
    1
    caddy validate --config Caddyfile
  • 查看状态
    1
    caddy untrap

4.2 作为系统服务

如果你通过包管理器安装 Caddy,它通常会作为一个 systemd 服务运行。

  • 启动sudo systemctl start caddy
  • 停止sudo systemctl stop caddy
  • 重启sudo systemctl restart caddy
  • 查看状态sudo systemctl status caddy
  • 查看日志sudo journalctl -u caddy

4.3 Docker 部署后的管理

  • 启动docker start caddy
  • 停止docker stop caddy
  • 重启docker restart caddy
  • 查看日志docker logs caddy
  • 重载配置:修改 Caddyfile 后,需要 docker restart caddy 或在容器内部执行 caddy reload (如果安装了 curl 并配置了 admin API)。

五、高级特性与应用场景

5.1 HTTP/3 (QUIC) 支持

Caddy 默认支持 HTTP/3。只要你的客户端支持,它就可以通过 UDP 进行更快的连接和数据传输。

5.2 API 网关 & 认证

结合其反向代理和认证指令(如 basicauth, jwt 插件),Caddy 可以作为一个简单的 API 网关,提供鉴权、路由等功能。

5.3 动态 DNS

Caddy 可以与 DNS 提供商集成,使用 DNS 验证 Let’s Encrypt 证书,这对于那些无法通过 HTTP 验证的场景(如内部服务,或需要通配符证书)非常有用。这需要安装相应的 DNS 插件。

5.4 模块化和插件系统

Caddy 2 的设计核心就是模块化。你可以通过重新编译 Caddy(使用 xcaddy 工具)来添加额外的插件,例如:

  • DNS 验证插件caddy-dns/cloudflarecaddy-dns/route53 等。
  • 认证插件caddy-security(提供了 OAuth2, OIDC, JWT 等更高级的认证方式)。
  • 日志插件压缩插件等。

5.5 作为嵌入式服务器

由于是 Go 编写,Caddy 可以作为库集成到你自己的 Go 应用程序中,提供 Web 服务功能。

六、Caddy 与 Nginx/Apache 的对比

特性 Caddy Nginx Apache HTTP Server
自动 HTTPS 原生支持,无需配置 需额外配置 certbot 或手动管理 需额外配置 certbot 或手动管理
配置语法 Caddyfile,简洁直观,易读易写 nginx.conf,功能强大但相对复杂 httpd.conf,功能强大但学习曲线陡峭
HTTP/3 (QUIC) 原生支持 需手动编译 OpenSSL/Nghttp2 或使用特定版本 需手动编译或使用特定模块
易用性 极高,部署和管理简单 中等,需要理解其配置哲学 中等,尤其对于初学者
性能 高性能,Go 语言优势,适用于中小型到大型服务 极高性能,尤其适用于高并发静态服务 良好,但对于极高并发可能需要更多优化
部署方式 单一二进制文件,Docker 包管理器,Docker 包管理器,Docker
用途 静态文件、反向代理、API 网关、WebSockets 静态文件、反向代理、负载均衡、缓存 静态文件、动态内容 (mod_php等)、反向代理

七、总结

Caddy 是一个适合现代 Web 需求的新一代 Web 服务器。对于需要快速部署、重视自动 HTTPS 和简洁配置的用户而言,Caddy 提供了一个极具吸引力的选择。无论是个人博客、小型应用还是作为微服务的反向代理,Caddy 都能以其优雅的方式,助你轻松应对挑战。

如果你是 Web 服务器的新手,或者希望摆脱繁琐的 HTTPS 配置,Caddy 绝对值得一试。其活跃的社区和持续的开发也确保了其在未来的发展潜力。