前几天用 Netmaker 的时候发现它用 Caddy 替换掉了 Nginx,用了后发现确实简单好用,就安利一下。
Caddy 是一个强大的、可扩展的平台,用 Go 编写,可以为你的站点、服务和应用程序提供服务。如果你是 Caddy 的新手,你服务网络的方式将会改变。
引言
大多数人使用 Caddy 作为网络服务器或代理,但在其核心,Caddy 是一个服务器的服务器(a server of servers)。通过 必要的模块,它可以承担任何长时间运行的进程的角色!
配置是动态的和可通过 Caddy 的 API 导出 。虽然不需要配置文件,但是您仍然可以使用它们; 大多数人最喜欢的配置 Caddy 的方法是使用 Caddyfile。配置文档的格式通过配置适配器采用多种形式,但 Caddy 的本地配置语言是 JSON。
Caddy 为所有主流平台编译,并且没有运行时依赖项。
新手指南
我们建议每个人不管经验如何都要看一下我们的 入门指南。它将为你提供一个全面的视角来看待你的新网络服务器,这对你继续学习是无价的。本教程将探索使用 Caddy 的基础知识,并帮助您在更高的层次上熟悉它。
目的:
- 运行守护进程
- 试试 API
- 给 Caddy 一个配置
- 测试配置
- 制作一个 Caddyfile
- 使用配置适配器(config adapter)
- 从一个初始配置开始
- 比较 JSON 和 Caddyfile
- 比较 API 和配置文件
- 在后台运行
- 零停机时间配置重载
先决条件
- 已安装
caddy
及curl
(安装 Caddy 可以参考 这里)
要启动 Caddy 作为一个守护程序,使用 run
子命令:
caddy run BASH |
默认情况下,Caddy 的配置 (“ config”) 为空。我们可以使用另一个终端访问 管理 API 来验证这一点:
curl localhost:2019/config/ BASH |
ℹ️ 信息 :
上面地址 不是 你的网站,localhost:2019 是用来控制 Caddy 的管理端点,并被默认限制为本机访问。
我们可以通过给它一个配置来使 Caddy 变得有用。这可以通过多种方式完成,但是我们将在下一节使用 curl
向 /load
端点发出 POST 请求。
你的第一个配置
为了准备我们的请求,我们需要做一个配置。
将其保存到 JSON 文件中(例如 caddy.JSON
) :
{ "apps": { "http": { "servers": { "example": { "listen": [":2015"], "routes": [ { "handle": [{ "handler": "static_response", "body": "Hello, world!" }] } ] } } } } } JSON |
然后上传:
curl localhost:2019/load \ -X POST \ -H "Content-Type: application/json" \ -d @caddy.json BASH |
我们可以通过如下命令验证 Caddy 将我们的新配置应用到另一个 GET 请求:
curl localhost:2019/config/ BASH |
然后测试新的配置:
$curl localhost:2015 Hello, world! BASH |
如果你看到 Hello, world!
那恭喜了,成功了!确保配置按预期的方式工作总是一个好主意,尤其是在部署到生产环境之前。
你的第一个 Caddyfile
另一种配置 Caddy 的方法是 Caddyfile。上面我们在 JSON 编写的配置可以简单地表达为:
:2015 respond "Hello, world!" CADDYFILE |
将其保存到工作目录文件中名为 Caddyfile (无扩展名)的文件中。
如果 Caddy 已经在运行, (Ctrl + c)停止它,然后运行:
caddy adapt BASH |
或者你把 Caddyfile 存储在别的地方,或者给它取了别的名字:
caddy adapt --config /path/to/Caddyfile BASH |
您将看到 JSON 输出! 这里发生了什么?
我们只是使用 配置适配器 将 Caddyfile 转换为 Caddy 的原生 JSON 结构。
虽然我们可以获得这个输出并发出另一个 API 请求,但是我们可以跳过所有这些步骤,因为 caddy
命令可以为我们完成这些操作。如果工作目录中有一个叫 Caddyfile 的文件,并且没有指定其他配置,Caddy 会加载 Caddyfile,为我们改编,然后马上运行。
现在当前文件夹中有一个 Caddyfile,让我们再次运行 caddy:
caddy run BASH |
或者如果你的 Caddyfile 在其他地方:
caddy run --config /path/to/Caddyfile BASH |
(如果调用的是不以“ Caddyfile”开头的其他名称,则需要指定 --adapter caddyfile
)
正如你所看到的,有几种方法可以让你使用初始配置启动 Caddy:
- 在工作目录一个名为 Caddyfile 的文件
--config
flag (可选项,带有--adapter
flag)- -
-resume
flag (如果先前加载了配置)
JSON vs. Caddyfile
现在您知道了,Caddyfile 刚刚为您转换为 JSON。
Caddyfile 看起来比 JSON 简单,但是你应该一直使用它吗?每种方法都有利有弊。答案取决于您的需求和用例。
JSON | Caddyfile |
完整的 Caddy 功能 | 最常见的 Caddy 功能部件 |
易于生成 | 易于手工制作 |
易于编程 | 难以自动化 |
非常有表现力 | 适度的表达 |
允许配置遍历 | 不能在 Caddyfile 间转换 |
部分配置更改 | 只能修改整个配置 |
可以导出 | 无法导出 |
与所有 API 端点兼容 | 与某些 API 端点兼容 |
自动生成的文档 | 文档是手写的 |
无处不在 | 小众 |
更有效率 | 更多的计算 |
有点无聊 | 挺有意思的 |
了解更多:JSON 结构 | 了解更多:Caddyfile 文档 |
您将需要决定哪一个最适合您的用例。
需要注意的是,JSON 和 Caddyfile (以及 任何其他支持的配置适配器 ) 都可以与 Caddy 的 API 一起使用。然而,如果您使用 JSON,您将获得 Caddy 的全部功能和 API 特性。如果使用配置适配器,使用 API 加载或更改配置的唯一方法是 /load 端点。
API vs. 配置文件
ℹ️ 信息 :
实际上,即使是配置文件也要经过 Caddy 的 API 端点,命令只是为您包装了这些 API 调用。
您还需要决定您的工作流是基于 API 的还是基于 CLI 的。(您可以在同一台服务器上同时使用 API 和配置文件,但我们不推荐这样做: 最好有一个真实的来源。)
API | 配置文件 |
使用 HTTP 请求修改配置 | 使用 shell 命令修改配置 |
易于扩大规模 | 难以规模化 |
手工操作难度大 | 易于手工操作 |
真的很有趣 | 也很有趣 |
了解更多:API 教程 | 了解更多:Caddyfile 教程 |
ℹ️ 信息 :
使用 API 手动管理服务器配置完全可以通过适当的工具实现,例如: 任何 REST 客户端应用程序
或配置文件工作流的选择与配置适配器的使用是正交的: 你可以使用 JSON,但存储在一个文件中,并使用命令行界面; 相反,你也可以使用 Caddyfile 与 API。
但是大多数人会使用 json + api 或 Caddyfile + CLI 组合。
如您所见,Caddy 非常适合于各种各样的用例和部署!
Start,stop,run
因为 Caddy 是一个服务器,所以它可以无限期地运行。这意味着在执行 caddy run
之后,终端不会解除阻塞,直到进程终止(通常使用 Ctrl + c)。
虽然 caddy run
是最常见的,通常是推荐的(特别是在进行系统服务时!),你也可以选择使用 caddy start
启动 Caddy,并让它在后台运行:
caddy start BASH |
这将允许您再次使用您的终端,这在一些交互式无头环境中非常方便。
然后你必须自己停止这个过程,因为 Ctrl + c 不会为你停止:
caddy stop BASH |
或者使用 API 的/stop 端点。
重新加载配置
您的服务器可以执行零停机时间配置重载 / 更改。
加载或更改配置的所有 API 端点 都是完美的,并且没有停机时间。
但是,在使用命令行时,可能很容易使用 Ctrl + c 来停止服务器,然后再重新启动服务器以获取新的配置。不要这样做: 停止和启动服务器与配置更改是正交的,并将导致停机。
相反,使用 caddy reload 命令来优雅地修改配置:
caddy reload BASH |
这实际上只是在引擎盖下使用了 API。它将加载并在必要时将配置文件调整为 JSON,然后在不停机的情况下优雅地替换活动配置。
如果加载新配置时出现任何错误,Caddy 将回滚到上次工作的配置。
ℹ️ 信息 :
从技术上讲,新配置是在停止旧配置之前启动的,因此在很短的时间内,两个配置都在运行!如果新配置失败,它将中止一个错误,而旧配置则根本不会停止
Caddy 常用功能
- 静态文件访问
- 反向代理
- HTTPS
静态文件访问
命令行方式
在终端中,切换到站点的根目录并运行:
caddy file-server BASH |
如果你得到一个权限错误,这可能意味着你的操作系统不允许你绑定到低端口 ---- 所以改用高端口:
caddy file-server --listen :2015 BASH |
然后在浏览器中打开 (或 localhost:2015)查看您的网站!
如果你没有索引文件,但是你想要显示一个文件列表,可以使用 --browse
选项:
caddy file-server --browse BASH |
您可以使用另一个文件夹作为站点根目录:
caddy file-server --root ~/mysite BASH |
Caddyfile 方式
在站点的根目录中,创建一个名为 Caddyfile
的文件,其中包含以下内容:
localhost file_server CADDYFILE |
或:
localhost file_server browse CADDYFILE |
或
localhost root * /home/me/mysite file_server CADDYFILE |
分别对应以上的几个命令。
反向代理
本教程假设您有一个运行在 127.0.0.1:9000
上的后端 HTTP 服务。
命令行方式
很直白,直接能看明白:
caddy reverse-proxy --to 127.0.0.1:9000 BASH |
如果你没有权限绑定到低端口,你可以从高端口代理:
caddy reverse-proxy --from :2016 --to 127.0.0.1:9000 BASH |
Caddyfile 方式
直接上配置:
localhost reverse_proxy 127.0.0.1:9000 CADDYFILE |
caddy run
运行即可
更改代理的地址很容易:
:2016 reverse_proxy 127.0.0.1:9000 CADDYFILE |
更改 Caddyfile 时,请确保 重新加载 Caddy (或停止并重新启动它)。
使用 反向代理指令 以做很多事情。
HTTPS
本指南将向您展示如何立即使用 完全自管理的 HTTPS 启动和运行。
ℹ️ 信息 :
在默认情况下,Caddy 对所有站点使用 HTTPS,只要在配置中提供了 主机名。本教程假设您希望通过 HTTPS 获得一个公共受信任的站点(即不是“ localhost”) ,因此我们将使用一个公共域名和外部端口
先决条件:
- 对 DNS 的基本了解
- 注册的公共域名
- 对端口 80 和 443 的外部访问
- 已安装
caddy
和curl
在本教程中,将 example.com
替换为您的实际域名。
设置域名的 A/AAAA 记录指向服务器。您可以通过登录到您的 DNS 提供商和管理您的域名来做到这一点。
在继续之前,用权威 lookup 验证正确的记录。用你的域名替换 example.com
,如果你使用的是 IPv6,把 type=A
替换为 type=AAAA
:
curl "https://cloudflare-dns.com/dns-query?name=example.com&type=A" \ -H "accept: application/dns-json" BASH |
ℹ️ 提示 :
一切的前提是你是在 cloudflare 上买的这个域名。
如果不是的话,步骤会复杂一些。
参见这篇 域名在 DNSPod 上的证书申请方式
还要确保您的服务器在端口 80 和 443 上是可以从公共接口访问的。
ℹ️ 提示 :
如果您在您的家庭或其他受限制的网络,您可能需要转发端口或调整防火墙设置
所有我们需要做的是开始用您的域名配置 Caddy。有几种方法可以做到这一点。
Caddyfile
这是获取 HTTPS 的最常用方法。
创建一个名为 Caddyfile (无扩展名)的文件,其中第一行是您的域名,例如:
example.com respond "Hello, privacy!" CADDYFILE |
然后从同一个目录中运行:
caddy run BASH |
您将看到 Caddy 提供一个 TLS 证书,并通过 HTTPS 服务您的站点。这是可能的,因为你的网站在 Caddyfile 中的地址包含一个域名。
file-server
命令
caddy file-server --domain example.com BASH |
可以了。
reverse-proxy
命令
caddy reverse-proxy --from example.com --to localhost:9000 BASH |
总结
Caddy 吸引我的地方:
- 自动申请续约证书
- 简单命令的 Caddyfile
- Go 编写,Caddy 为所有主流平台编译,并且没有运行时依赖项。
👍👍👍