从接触服务器开始,我就一直学习并使用着 Nginx。
Nginx 性能强大也足够好用,但证书要自己解决。
之前也搞过 自动化 SSL 证书,已经可以完全甩手了。
不过我还是觉得更换到 Caddy,因为——
折腾果然是很有意思的嘛!
去年抽了个时间,把主要用的这台服务器上所有配置从 Nginx 迁移到了 Caddy 上,在此做一点记录。
安装
安装方法就不赘述,文档 简单且详尽。
但默认安装的 Caddy 是不支持 Cloudflare API 申请泛域名证书的,于是我又去 Download 页面选择 Linux amd64
版本并选中 caddy-dns/cloudflare
插件,将下载下来的二进制文件替换已经安装的 Caddy,重启服务后,现在的 Caddy 就可以支持了。
这样虽然折腾点,但不用配置权限、systemd 等一堆麻烦的东西,我个人觉得是更省事的办法。
使用
Caddyfile
因为 Nginx 已经有自己的使用习惯,在更换到 Caddy 后我想尽可能保持相同的使用习惯,那就一点规划。
那么清空默认的 Caddy 配置文件,写一份新的 Caddyfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { admin localhost:2019 email <example@mail.com> }
import /srv/caddy/*.caddy0
*.neko7ina.com { import /srv/caddy/tls.conf import /srv/caddy/*.caddy
log { output file /var/log/caddy/access.log { roll_size 10mb roll_keep 5 roll_keep_for 48h } format json } }
|
我用 Nginx 习惯把每个服务的配置文件都拆开各写各的,再用 Include
全部引用。
Caddy 有个类似的 import
,这里使用了两个引用。
一个引用非泛域名的配置,类似直接 IP 或者裸域;另一个为其他二级域名的配置。
tls.conf
是使用 caddy-dns/cloudflare
的配置段,直接写 Caddyfile 里也行。
caddy0 配置
IP 配置参考
IP 的配置很简单,直接写好 IP 加端口就可以了,比如下面一个工作日接口的配置:
1 2 3
| 110.40.192.82:80 { reverse_proxy localhost:3007 }
|
裸域配置参考
裸域的配置也很简单,比如下面博客本体的配置:
1 2 3 4 5 6 7 8 9 10 11
| neko7ina.com { import /srv/caddy/tls.conf root * /home/git/hexo file_server encode gzip
handle_errors { rewrite * /404.html file_server } }
|
非标端口配置参考
有一些服务不想给别人看见,就会使用非标准端口,比如 Frp Dashboard 的服务:
1 2 3 4 5
| frp-example.neko7ina.com:79 { import /srv/caddy/tls.conf reverse_proxy localhost:79 encode gzip }
|
caddy 配置
这里是重头戏了,因为引用 caddy 文件实际上是被包在泛域名的配置段里,所以配置就不能像 caddy0 文件那么写。
我们需要先声明一个变量为哪个二级域名,然后再对这个变量进行配置,比如下面服务器流量查看服务的配置:
1 2 3 4 5 6
| @vnstat host vnstat.neko7ina.com handle @vnstat { root * /srv/www/vnstat file_server encode gzip }
|
这里先用 @vnstat
声明了二级域名 vnstat.neko7ina.com
,然后再使用 handle @vnstat
来进行配置。
图片优化
服务器是小水管,有的地方图片有多,为了保证加载速度想尽了办法。
之前在 Lazyload 上做了点优化,现在对图片本身再动点手脚。
简单来说,就是判断客户端请求头是否支持 webp 与 avif 格式图片,优先返回体积更小的图片来达到加快加载速度的目的。
如果客户端不支持也可以返回原本的图片,保证了兼容性。
比如我的图片都是用一个二级域名来管理,那么配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| @image host image.neko7ina.com handle @image { root * /home/git/hexo/images encode zstd gzip header Cache-Control "public, max-age=31536000"
@procPath { path_regexp proc (?i).*_proc.* } handle @procPath { @acceptsWebp_proc { header Accept *image/webp* path_regexp webp_proc (?i)^(.+)\.(jpg|jpeg|png)$ } handle @acceptsWebp_proc { @hasWebp_proc file {re.webp_proc.1}.webp rewrite @hasWebp_proc {re.webp_proc.1}.webp }
@acceptsAVIF_proc { header Accept *image/avif* path_regexp avif_proc (?i)^(.+)\.(jpg|jpeg|png)$ } handle @acceptsAVIF_proc { @hasAVIF_proc file {re.avif_proc.1}.avif rewrite @hasAVIF_proc {re.avif_proc.1}.avif }
file_server }
@acceptsAVIF { header Accept *image/avif* path_regexp avif (?i)^(.+)\.(jpg|jpeg|png)$ } handle @acceptsAVIF { @hasAVIF file {re.avif.1}.avif rewrite @hasAVIF {re.avif.1}.avif }
@acceptsWebp { header Accept *image/webp* path_regexp webp (?i)^(.+)\.(jpg|jpeg|png)$ } handle @acceptsWebp { @hasWebp file {re.webp.1}.webp rewrite @hasWebp {re.webp.1}.webp }
file_server }
|
配置参考了这篇 文字 作为参考,逻辑是判断请求头中是否支持 avif,如果是就返回图片同名的 avif 文件,否则再判断请求头中是否支持 webp,如果是就返回图片同名的 webp 文件,都不支持则返回源文件。
Lazyload 会有个占位图,我发现在图片体积很小的情况下(通常是几百 KB),webp 的表现会比 avif 更好,于是在基本规则前又单独加了规则判断路径中带 _proc.
的请求优先处理,按照 webp > avif > 源文件的优先级排列。
便利性配置
上文也说到,尽可能保证和 Nginx 使用时一样的习惯。
在使用 Nginx 时我会频繁使用到 nginx -t
与 nginx -s reload
命令,为了在 Caddy 上也能使用类似的指令,还需要在 Shell 的配置文件里加点配置。
1 2 3 4 5 6 7 8 9 10
| function caddy() { if [[ "$1" == "-t" ]]; then command caddy validate --config /etc/caddy/Caddyfile "${@:2}" elif [[ "$1" == "-s" && "$2" == "reload" ]]; then command caddy reload --config /etc/caddy/Caddyfile "${@:3}" else command caddy "$@" fi }
|
这样使用 caddy -t
与 caddy -s reload
也可以实现类似的效果了。
注意,Caddy 的重载配置是通过 admin API 来实现的,如果你在配置文件中关闭了 admin 那将无法使用。
结语
虽然这篇文字不多,但在迁移时总会遇到各种各样的问题,实际上花的时间并不少。
还好,我对 Caddy 的表现非常满意。
参考