Debian 12 自编译 Caddy(含 DNS 插件)并替换 apt 版本

在 Debian 12 上,官方 apt 安装的 Caddy 通常不包含第三方 DNS 插件。
如果你希望使用 DNS Challenge(例如 Cloudflare DNS)自动申请证书,就需要自己编译带插件的 Caddy。

本文记录一种比较直接的做法:

  • 使用 xcaddy 编译带 DNS 插件的 Caddy
  • 使用 apt 安装官方 Caddy 软件包
  • 直接用自编译的二进制替换 /usr/bin/caddy
  • 继续保留 apt 提供的:
    • systemd 服务
    • caddy 用户
    • 默认目录结构
    • 日志管理方式

这种方式的优点是简单直接,适合个人服务器、VPS 和小规模部署。

一、环境说明

示例环境:

  • 系统:Debian 12
  • 架构:amd64
  • 工具:Go、Git、xcaddy

二、安装编译环境

先更新软件源并安装基础工具:

1
2
sudo apt update
sudo apt install -y golang git build-essential curl gnupg debian-keyring debian-archive-keyring

检查 Go 版本:

1
go version

建议使用较新的 Go 稳定版。
Caddy 和插件的 Go 版本要求可能会随着版本变化而提高。

三、安装 xcaddy

安装 xcaddy

1
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

默认安装路径为:

1
~/go/bin/xcaddy

将其加入 PATH:

1
2
echo 'export PATH=$PATH:~/go/bin' >> ~/.bashrc
source ~/.bashrc

验证是否安装成功:

1
xcaddy version

四、编译带 DNS 插件的 Caddy

Caddy 官方 DNS 插件列表:

https://caddyserver.com/docs/modules/dns.providers

以 Cloudflare 为例,执行:

1
2
xcaddy build \
--with github.com/caddy-dns/cloudflare

如果需要多个 DNS 插件,也可以这样:

1
2
3
xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/caddy-dns/alidns

编译完成后,当前目录会生成一个二进制文件:

1
./caddy

检查是否包含 DNS 模块:

1
./caddy list-modules | grep dns

如果输出类似:

1
2
tls.dns.cloudflare
tls.dns.alidns

说明编译成功。

五、安装官方 Caddy 软件包

虽然最终运行的是自编译版本,但仍然建议先安装官方 apt 包,以获得标准的 systemd 服务和目录结构。

导入官方仓库 GPG key:

1
2
3
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor \
-o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

添加仓库:

1
2
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list

安装 Caddy:

1
2
sudo apt update
sudo apt install -y caddy

六、apt 安装后的默认结构

安装完成后,系统通常会提供以下内容:

  • 二进制:/usr/bin/caddy
  • 服务文件:/lib/systemd/system/caddy.service
  • 配置文件:/etc/caddy/Caddyfile
  • 数据目录:/var/lib/caddy
  • 运行用户:caddy

日志可通过以下命令查看:

1
journalctl -u caddy

七、替换 apt 的 Caddy 二进制

这是本文的核心步骤。

1. 备份原始二进制

1
sudo mv /usr/bin/caddy /usr/bin/caddy.orig

2. 复制自编译版本

假设你当前目录下已经有编译好的 ./caddy

1
sudo cp ./caddy /usr/bin/caddy

3. 设置权限

1
2
sudo chmod 755 /usr/bin/caddy
sudo chown root:root /usr/bin/caddy

八、验证替换是否成功

查看版本:

1
caddy version

查看 DNS 模块:

1
caddy list-modules | grep dns

如果能看到你编译进去的 DNS provider,例如:

1
tls.dns.cloudflare

就说明替换成功了。

九、启动并检查服务

重新加载 systemd:

1
sudo systemctl daemon-reload

重启 Caddy:

1
sudo systemctl restart caddy

查看运行状态:

1
sudo systemctl status caddy

查看日志:

1
journalctl -u caddy -f

十、Caddyfile 示例:Cloudflare DNS Challenge

下面是一个最简单的示例:

1
2
3
4
5
6
7
example.com {
tls {
dns cloudflare your_cloudflare_api_token
}

respond "Hello World"
}

如果你使用泛域名,也可以这样写:

1
2
3
4
5
6
7
*.example.com, example.com {
tls {
dns cloudflare your_cloudflare_api_token
}

respond "Wildcard TLS OK"
}

修改完成后重启服务:

1
sudo systemctl restart caddy

查看日志确认签发过程:

1
journalctl -u caddy -f

十一、常用命令

验证配置文件:

1
caddy validate --config /etc/caddy/Caddyfile

格式化配置:

1
caddy fmt --overwrite /etc/caddy/Caddyfile

重启服务:

1
sudo systemctl restart caddy

查看状态:

1
sudo systemctl status caddy

查看日志:

1
journalctl -u caddy -f

十二、升级自编译 Caddy

升级流程也很简单:

1. 重新编译

1
xcaddy build --with github.com/caddy-dns/cloudflare

2. 替换二进制

1
2
3
sudo cp ./caddy /usr/bin/caddy
sudo chmod 755 /usr/bin/caddy
sudo chown root:root /usr/bin/caddy

3. 重启服务

1
sudo systemctl restart caddy

十三、注意事项

最需要注意的一点是:

apt 升级可能覆盖 /usr/bin/caddy

因为你直接替换了官方包安装的二进制,所以在后续执行 apt upgrade 时,/usr/bin/caddy 有可能被官方包重新覆盖。

如果你希望避免这种情况,可以锁定软件包:

1
sudo apt-mark hold caddy

取消锁定:

1
sudo apt-mark unhold caddy

因此,这种方案虽然简单直接,但也意味着你需要自己留意后续升级行为。

十四、备份建议

建议至少备份以下目录:

1
2
/etc/caddy/
/var/lib/caddy/

如果你保留了原始二进制,也可以留着:

1
/usr/bin/caddy.orig

这样后续回滚会更方便。

十五、总结

在 Debian 12 上,自编译带 DNS 插件的 Caddy 并替换 apt 版本,是一种非常直接且实用的方案。

它的特点是:

  • 编译过程简单
  • 保留官方 apt 提供的 systemd 服务和目录结构
  • 可以使用 Cloudflare、AliDNS 等 DNS 插件
  • 适合个人服务器和小规模部署

本文采用的是最直接的做法:用自编译版本替换 /usr/bin/caddy
如果你只是想尽快跑起来,这种方式足够高效;但要记得,后续 apt 升级可能会覆盖该文件,需要自行留意。

附:最小示例

1
2
3
4
5
6
7
example.com {
tls {
dns cloudflare your_cloudflare_api_token
}

reverse_proxy 127.0.0.1:8080
}