从 Apache httpd 切换到 Caddy2

技术 秋水逸冰 14355浏览 9评论

2022 年 6 月 HTTP/3 的 RFC 发布迄今已经有一年了。市面上常用的几款 Web Server,Caddy Web Server 是最早支持 HTTP/3 的,而 Nginx 直到 2023 年 5 月 23 日 1.25.0 版本才开始体验支持。至于 Apache httpd,也不知道要到什么时候才支持 HTTP/3。
之所以打算正式从 Apache httpd 切换到 Caddy,是因为除 Caddy 之外的 Web Server 配置证书以及自动续期还是比较麻烦。众所周知,一般情况下市面上大部分的免费证书有效期只有 90 天,需要在过期之前续签。采用 acme.sh 脚本进行自动续签,然后 nginx reload 或者 httpd reload 有时候不太靠谱,有一定的失败几率。所以最后决定 Caddy 一把梭,将证书问题一劳永逸。
本文在 LCMP (Linux + Caddy + MariaDB + PHP) 环境的基础下,涉及到切换到 Caddy 的一些细节,在此记录一下。

1. 适用于 WordPress 的 Caddy 2 配置

适用于 WordPress 的 Apache httpd 的 .htaccess 基本上不需要转换,是因为 Caddy 2 的 php_fastcgi 指令已经提前做好了一些预设。
php_fastcgi 指令其实是一系列指令的快捷方式。具体解释如下:

route {
	# 为目录请求添加尾部斜线
	@canonicalPath {
		file {path}/index.php
		not path */
	}
	redir @canonicalPath {path}/ 308
	# 如果请求的文件不存在,尝试索引文件
	@indexFiles file {
		try_files {path} {path}/index.php index.php
		split_path .php
	}
	rewrite @indexFiles {http.matchers.file.relative}
	# 将 PHP 文件代理给 FastCGI 应答器
	@phpFiles path *.php
	reverse_proxy @phpFiles  {
		transport fastcgi {
			split .php
		}
	}
}

只需要禁止访问一些 WordPress 的资源即可。比如 xmlrpc.php,以及 wp-content/uploads 下的 php 文件。
下面的配置就是将禁止访问的资源重定向到首页 index.php。

www.example.com {
	header {
		Strict-Transport-Security "max-age=31536000; preload"
		X-Content-Type-Options nosniff
		X-Frame-Options SAMEORIGIN
	}
	# Set this path to your site's directory.
	root * /data/www/yoursiterootfolder
	encode gzip
	@disallowed {
		path /xmlrpc.php
		path /wp-content/uploads/*.php
	}
	rewrite @disallowed /index.php
	# Serve a PHP site through php-fpm
	php_fastcgi unix//run/php-fpm/www.sock
	# Enable the static file server.
	file_server {
		index index.html
	}
	log {
		output file /var/log/caddy/ssl_access.log {
			roll_size 100mb
			roll_keep 3
			roll_keep_for 7d
		}
	}
}

注意替换域名 www.example.com 为你自己的域名,以及网站根目录 /data/www/yoursiterootfolder 为你自定义的路径。同时在此之前,域名的 DNS 也要解析到 Caddy 所在服务器的 IP 地址。

2. 适用于 Typecho 的 Caddy 2 配置

适用于 Typecho 的配置如下:

www.example.com {
	header {
		Strict-Transport-Security "max-age=31536000; preload"
		X-Content-Type-Options nosniff
		X-Frame-Options SAMEORIGIN
	}
	# Set this path to your site's directory.
	root * /data/www/yoursiterootfolder
	encode gzip
	handle_path / {
		try_files {path} {path}/ /index.php/{uri}
	}
	# Serve a PHP site through php-fpm
	php_fastcgi unix//run/php-fpm/www.sock
	# Enable the static file server.
	file_server {
		index index.html
	}
	log {
		output file /var/log/caddy/ssl_access.log {
			roll_size 100mb
			roll_keep 3
			roll_keep_for 7d
		}
	}
}

Typecho 默认是由 index.php 进行静态化路由的,所以try_files {path} {path}/ /index.php/{uri}将网址参数统一由 index.php 重定向。
注意替换域名 www.example.com 为你自己的域名,以及网站根目录 /data/www/yoursiterootfolder 为你自定义的路径。同时在此之前,域名的 DNS 也要解析到 Caddy 所在服务器的 IP 地址。

3. 适用于 YOURLS 的 Caddy 2 配置

适用于 YOURLS 的配置如下:

www.example.com {
	header {
		Strict-Transport-Security "max-age=31536000; preload"
		X-Content-Type-Options nosniff
		X-Frame-Options SAMEORIGIN
	}
	# Set this path to your site's directory.
	root * /data/www/yoursiterootfolder
	encode gzip
	route {
		try_files {path} {path}/index.php /yourls-loader.php
		php_fastcgi unix//run/php-fpm/www.sock {
			split .php
			index index.php
		}
	}
	# Enable the static file server.
	file_server {
		index index.html
	}
	log {
		output file /var/log/caddy/ssl_access.log {
			roll_size 100mb
			roll_keep 3
			roll_keep_for 7d
		}
	}
}

YOURLS 默认是由 yourls-loader.php 进行加载的,所以try_files {path} {path}/index.php /yourls-loader.php将网址参数统一由 yourls-loader.php 尝试重定向。
注意替换域名 www.example.com 为你自己的域名,以及网站根目录 /data/www/yoursiterootfolder 为你自定义的路径。同时在此之前,域名的 DNS 也要解析到 Caddy 所在服务器的 IP 地址。

4. 关于 Caddy 2 发行的证书位置

Caddy 2 最大的优势就是证书一把梭,自动 HTTPS,基本上不让人操心。
其发行的证书默认的存储位置,经过实际使用体验,应该是在如下位置。
Linux 系统

/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/

Windows 系统

C:\Windows\System32\config\systemprofile\AppData\Roaming\Caddy\certificates\acme-v02.api.letsencrypt.org-directory\

5. 关于 Caddy 2 的 API

Caddy 2 默认可以通过使用地址 localhost:2019RESTAPI 进行 HTTP 访问。除非你知道怎么用,否则还是建议将其禁用。不然 Caddy 2 启动默认会监听 localhost 的 2019 端口。
禁用方法很简单,在 Caddyfile 的全局配置理如下设置。

{
	admin off
}

当然禁用之后,就不能使用 systemctl reload caddy 命令了,因为 Caddy 是通过 API 来加载新配置的。
使用 systemctl restart caddy 命令重启即可。

6. 切换总结

Caddy 的配置文件 Caddyfile 写起来简单,其语法匹配器十分强大,行为明确,比其他 Web Server 的配置少写很多行。
不用操心证书问题,自动 HTTPS 证书申请和续期。妈妈再也不用担心网站的证书过期啦。
至于有人说 Caddy 的缺点就是性能没有 Nginx 高,这个就是仁者见仁智者见智了。
还有个 Caddy 的缺点就是其二进制文件体积比较大,这是 Go 写的软件的通病了,以 v2.6.4 为例,标准模块数量 100 个,占用 46MB。Nginx 是 C 写的,以 v1.25.0 为例,其二进制文件占用 1.6MB,确实小巧。可是这年头,谁还在乎这点硬盘空间呢,你说是吧。

写在最后

请关注我的 Telegram 频道:https://t.me/qiushuiyibing
我会在此不定期发布一些杂七杂八的作品。
同时也欢迎加入交流群:https://t.me/qiushui2018

转载请注明:秋水逸冰 » 从 Apache httpd 切换到 Caddy2

发表我的评论
取消评论

请输入正确答案后提交评论 *超出时限。 请再次填写验证码。

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (9)

  1. Is it possible in the future a patch for caddy to use Apache config so we can directly replace the Apache?
    Archipelago5个月前(11-29)回复
  2. 我用caddy一直没写rewrite,感谢大佬的伪静态。 :cry: 我从一开始玩Linux搭网站选的就是Caddy,图的就是需要写的少,但从V1到V2这跨版本着实搞得有点懵。
    咕咕咕咕咕7个月前(09-21)回复
    • 其实习惯了 V2 的配置,你会发现其更简单实用。 大版本的不兼容导致人有一种抗拒心理,会对比其配置写法,有预设的心理预期。 都是人之常情。
      秋水逸冰7个月前(09-21)回复
  3. Caddy对于普通用户的最大问题恐怕是2.x版本的语法不向下兼容,习惯使用1.x的用户需要重新学习一遍。比如调用php-fpm,1.x版本的命令是fastcgi / php,到了2.x就变成了php_fastcgi unix/。 另外,不同的 Linux 发行版软件仓库里的 php-fpm 默认设定的socket文件名称和路径不一样,比如RedHat系的是/var/run/php-fpm/www.sock,SUSE的是/var/run/php-fpm/php-fpm.sock,Debian/Ubuntu系的是/var/run/php.sock(文件名会随php版本更新而改变,建议在Caddyfile使用/etc/alternatives/php-fpm.sock软链接否则需要同步更改)。
    lalala10个月前(07-13)回复
    • 尖括号里的内容无法显示,是为了防止xss攻击吗?
      lalala10个月前(07-13)回复
  4. 感谢分享typecho的伪静态。
    chenmo11个月前(06-11)回复
  5. 作为一个 Caddy 重度用户,给 Caddy 泼一点冷水。 想要使用 Caddy 替换 Nginx ,一大阻碍便是 Caddy 不支持缓存。 Caddy 2 目前可以使用的缓存模块有两个 http.handlers.cache ( https://github.com/caddyserver/cache-handler )、http.handlers.http_cache ( https://github.com/sillygod/cdp-cache ),但均是非官方模块,Caddy 2 自身并不支持缓存。 如果你因为一些需求,比如说反代S3媒体库,需要用到缓存功能,Caddy 2 就…… 一个反向代理,连缓存都不支持,多少有一点嘈点满满。 下面再说一说这两个非官方的缓存模块。 http.handlers.cache 基于 Souin cache,存储后端支持 Badger、NutsDB、Etcd、Olric、Redis,值得注意的一点是该模块并不支持像 Nginx 那样的 filesystem cache。 后三个都是 in-memory cache ,内存消耗巨大,本人只尝试使用过 Olric (因为支持 embedded olric 无需额外安装软件)。 embedded olric 不知道为什么,内存消耗特别大,测试时缓存 nitter 媒体文件,请求了大约1000个文件,传输流量140MB,Caddy的内存占用就已经达到了1.5GB。继续测试,发现Caddy的内存占用基本上是按请求流量十倍大小来算的。 前面两个 Badger 与 NutsDB 都是KV数据库,算是 filesystem+memory 的 hybrid cache 。 但实际使用下来,问题多多。 Badger 存在缓存污染问题,模块开发者自己都建议不要使用 Badger ( https://github.com/caddyserver/cache-handler/issues/27 )。 NutsDB 倒确实没有缓存污染问题,但却存在内存占用的问题。将 EntryIdxMode 设为 HintBPTSparseIdxMode,按 NutsDB 官方的说法『HintBPTSparseIdxMode 是专门节约内存的设计方案,单机10亿条数据,只要80几M内存』。但实际使用中却存在内存占用持续增长的问题。反代 img.bgme.me ,大约8个小时后,便 OOM Kill 了,OOM kill 时 total-vm:26129016kB, anon-rss:9457364kB。 此外 http.handlers.cache 配置相当的复杂,一点都和简单易用沾不上边。 再说一说 http.handlers.http_cache 模块。 http.handlers.http_cache 倒确实是简单易用,也完全是基于文件的 filesystem cache。 在实际使用中发现存在部分请求超时的问题。这是一个老问题,之前也有人提过 issue https://github.com/sillygod/cdp-cache/issues/24 ,按理来说应该也修复了,但在实际使用中我确实是又遇到了这个问题(caddy v2.7.0-beta.1 、cdp-cache v0.5.0)。感觉可能与请求并发有关,本地环境测试时并没有那么容易出问题,但放到生产环境中,便经常出现请求超时。 另外,重启服务后该插件会令之前缓存的Key丢失,遇到相同请求时会再次请求上流。 https://github.com/sillygod/cdp-cache/issues/38 此外,该插件并不支持 Nginx 那样设置最大存储大小。 总之,目前 Caddy 并不存在靠谱的 Cache 方案。如果你因为一些需求,比如说反代S3媒体库,需要用到缓存功能,并不非常推荐使用 Caddy。
    bgme11个月前(06-11)回复
    • Caddy 还在慢慢完善中,毕竟不如 Nginx 开发的早。 就总体来说,目前的功能是够用的了。
      秋水逸冰7个月前(09-16)回复
    • 确实咱用这个插件也经常遇到问题,它有时还会panic自动退出,最后弃用了
      365cent6个月前(10-21)回复