xcaddy - 自定义 Caddy 构建器
此命令行工具及相关 Go 包使得构建 Caddy Web Server 的自定义版本变得轻而易举。
Caddy 插件开发者以及任何希望构建自定义 caddy 二进制文件(无论是否包含插件)的人都在大量使用它。
请保持关注,留意变更,并欢迎提交反馈!谢谢!
要求
安装
您可以从 Release 标签页 下载二进制文件,这些文件已针对您的平台编译完成。
您也可以从源代码构建 xcaddy:
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
对于 Debian、Ubuntu 和 Raspbian,可从我们的 Cloudsmith 仓库 获取 xcaddy 软件包:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-xcaddy.list
sudo apt update
sudo apt install xcaddy
:warning: 专业提示
如果你发现自己在针对自定义或专有构建或开发流程与 xcaddy 进行“搏斗”,手动构建 Caddy 可能更容易!
Caddy 的 main.go 文件,即应用程序的主入口点,其注释中包含说明,解释了如何以与 xcaddy 基本相同的方式构建 Caddy。但当你直接使用 go 命令时,你可以对整个流程拥有更多的控制权,这可能会为你省去很多麻烦。
手动构建过程非常简单:只需将 main.go 复制到一个新文件夹中,初始化一个 Go 模块,插入你的插件(为每个插件添加一个 import),然后运行 go build。当然,你可能希望根据自己的喜好定制 go.mod 文件(特定的依赖版本、替换项等)。
命令用法
xcaddy 命令有两个主要用途:
- 编译自定义的
caddy二进制文件 - 在开发 Caddy 插件时作为
go run的替代
xcaddy 命令默认使用 Caddy 的最新版本。你可以通过设置 CADDY_VERSION 环境变量来为所有调用自定义此版本。
与 go 命令一样,xcaddy 命令会传递 GOOS、GOARCH 和 GOARM 环境变量以进行交叉编译。
请注意,xcaddy 在使用 -mod=readonly 时会忽略 vendor/ 文件夹。
自定义构建
语法:
$ xcaddy build [<caddy_version>]
[--output <file>]
[--with <module[@version][=replacement]>...]
[--replace <module[@version]=replacement>...]
[--embed <[alias]:path/to/dir>...]
[--pgo <file>] # EXPERIMENTAL
-
<caddy_version>是要构建的核心 Caddy 版本;默认为CADDY_VERSION环境变量或最新版本。
这可以是关键字latest,它将使用最新的稳定标签,也可以是任何 git 引用,例如:- 类似
v2.0.1的标签 - 类似
master的分支 - 类似
a58f240d3ecbb59285303746406cab50217f8d24的提交
- 类似
-
--output更改输出文件。 -
--with可以多次使用,通过指定 Go 模块名称及其可选版本来添加插件,类似于go get。模块名称是必需的,但具体版本和/或本地替换是可选的。 -
--replace类似于--with,但不会向代码中添加空白导入;它仅向go.mod写入一个 replace 指令,这在开发 Caddy 的依赖项(非 Caddy 模块)时非常有用。如果在使用--with时遇到错误,例如cannot find module providing package,请尝试此方法。 -
--embed可用于将目录的内容嵌入到 Caddy 可执行文件中。--embed可以多次传递,并带有不同的源目录。源目录可以带有自定义别名和冒号:前缀,以将嵌入的文件写入别名子目录,这与root指令和子指令结合使用时非常有用。 -
--pgo可用于指定包含用于基于配置文件优化的配置文件。如果当前目录中存在名为default.pgo的文件,它将自动使用。此功能是 xcaddy 的新功能,被视为实验性功能。
示例
$ xcaddy build \
--with github.com/caddyserver/ntlm-transport
$ xcaddy build v2.0.1 \
--with github.com/caddyserver/ntlm-transport@v0.1.1
$ xcaddy build master \
--with github.com/caddyserver/ntlm-transport
$ xcaddy build a58f240d3ecbb59285303746406cab50217f8d24 \
--with github.com/caddyserver/ntlm-transport
$ xcaddy build \
--with github.com/caddyserver/ntlm-transport=../../my-fork
$ xcaddy build \
--with github.com/caddyserver/ntlm-transport@v0.1.1=../../my-fork
你甚至可以使用 --with 标志替换 Caddy 核心:
$ xcaddy build \
--with github.com/caddyserver/caddy/v2=../../my-caddy-fork
$ xcaddy build \
--with github.com/caddyserver/caddy/v2=github.com/my-user/caddy/v2@some-branch
这使您可以轻松地对 Caddy 核心进行开发(同时还可以选择性地插入额外的模块!)。
如果 --embed 未使用别名前缀,源目录的内容将直接写入 Caddy 可执行文件内嵌文件系统的根目录。多个未设置别名的源目录的内容将被合并:
$ xcaddy build --embed ./my-files --embed ./my-other-files
$ cat Caddyfile
{
# You must declare a custom filesystem using the `embedded` module.
# The first argument to `filesystem` is an arbitrary identifier
# that will also be passed to `fs` directives.
filesystem my_embeds embedded
}
localhost {
# This serves the files or directories that were
# contained inside of ./my-files and ./my-other-files
file_server {
fs my_embeds
}
}
您还可以使用自定义别名和冒号分隔符作为源目录的前缀,以将源目录的内容写入 embedded 文件系统内的一个单独子目录中:
$ xcaddy build --embed foo:./sites/foo --embed bar:./sites/bar
$ cat Caddyfile
{
filesystem my_embeds embedded
}
foo.localhost {
# This serves the files or directories that were
# contained inside of ./sites/foo
root * /foo
file_server {
fs my_embeds
}
}
bar.localhost {
# This serves the files or directories that were
# contained inside of ./sites/bar
root * /bar
file_server {
fs my_embeds
}
}
这允许您从单个 Caddy 可执行文件中,通过别名引用两个不同的嵌入式目录,从而提供 2 个站点。
如果你需要处理 Caddy 的依赖项,你可以使用 --replace 标志将其替换为该依赖项的本地副本(或者,如果你需要,可以使用你在 github 等平台上 fork 的版本):
$ xcaddy build some-branch-on-caddy \
--replace golang.org/x/net=../net
用于插件开发
如果你在正在开发的 Caddy 插件文件夹内运行 xcaddy 且不带 build 子命令,它将使用你当前的模块构建 Caddy 并运行它,效果等同于你手动将其集成并调用 go run。
二进制文件将从当前目录构建并运行,随后进行清理。
当前工作目录必须位于一个已初始化的 Go 模块内。
语法:
$ xcaddy [--] <args...>
<args...>会被传递给caddy命令。这里不是放置 xcaddy 构建标志(如--with)的地方。- 在 Caddy 标志(如
--config)之前使用--,以便xcaddy不会尝试将它们解析为其自身的标志。如果没有分隔符,像xcaddy run --config caddy.json这样的命令会因unknown flag: --config而失败。
例如:
$ xcaddy list-modules
$ xcaddy run
$ xcaddy -- run --config caddy.json
使用你的插件与其他插件一起构建
上述开发快捷方式仅包含当前目录中的模块。类似 --with 的标志属于 xcaddy build。如果你将它们用于普通的 xcaddy / xcaddy run 调用,它们会被传递给 Caddy 并以 unknown flag: --with 失败。
要生成一个包含你的本地插件 以及 一个或多个其他插件的二进制文件,请使用带有多个 --with 标志的 xcaddy build。使用 =. 将你自己的模块指向当前目录:
# from inside your plugin's module directory
$ xcaddy build \
--with github.com/me/my-plugin=. \
--with github.com/mholt/caddy-events-exec
$ ./caddy run
你可以添加任意数量的 --with 插件。构建完成后,自行运行生成的二进制文件(默认 ./caddy)——与其他自定义构建相同。
可以通过设置 XCADDY_RACE_DETECTOR=1 启用竞态检测器。可以通过设置 XCADDY_DEBUG=1 启用 DWARF 调试信息。
获取 xcaddy 的版本
$ xcaddy version
库的使用
builder := xcaddy.Builder{
CaddyVersion: "v2.0.0",
Plugins: []xcaddy.Dependency{
{
ModulePath: "github.com/caddyserver/ntlm-transport",
Version: "v0.1.1",
},
},
}
err := builder.Build(context.Background(), "./caddy")
版本可以是任何与 go get 兼容的版本。
环境变量
由于子命令和标志受到限制,以利于快速进行插件原型开发,当没有标志可用时,xcaddy 会读取一些环境变量来获取其行为和/或配置的线索。
CADDY_VERSION设置要构建的 Caddy 版本。XCADDY_RACE_DETECTOR=1在构建中启用 Go 竞态检测器。XCADDY_DEBUG=1在构建中启用 DWARF 调试信息。XCADDY_SETCAP=1将在生成的二进制文件上运行sudo setcap cap_net_bind_service=+ep。默认情况下,如果找到sudo命令,将使用该命令;如有必要,设置XCADDY_SUDO=0以避免使用sudo。XCADDY_SKIP_BUILD=1使 xcaddy 不编译程序,它与 GoReleaser 等构建工具配合使用。隐含XCADDY_SKIP_CLEANUP=1。XCADDY_SKIP_CLEANUP=1使 xcaddy 在退出后在磁盘上保留构建产物。XCADDY_WHICH_GO设置要使用的 go 命令,例如当安装了多个版本的 go 时。XCADDY_GO_BUILD_FLAGS覆盖默认构建参数。支持 Unix 风格的 shell 引号,例如:XCADDY_GO_BUILD_FLAGS="-ldflags '-w -s'"。提供的标志应用于go命令:build、clean、get、install、list、run 和 testXCADDY_GO_MOD_FLAGS覆盖默认go mod参数。支持 Unix 风格的 shell 引号。
© 2020 Matthew Holt