如何使用Buildbot和Poudriere为您的FreeBSD服务器构建和部署软件包

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。

介绍

FreeBSD 端口和软件包集合 ,以下称为 端口树 ,是 FreeBSD 的外部软件构建系统。 它提供了一种基于 Makefile 的、一致的构建包的方式。 port 指的是构建配方,即Makefile和相关文件; 而 package 是将一个端口构建到包文件及其元信息的二进制(压缩)存档中的输出。

使用 make install 可以手动构建和安装超过 30,000 个端口的子集或全部。 但是,构建将在您的一台服务器上运行,而不是一个干净的环境。 对于生产用例,手动构建还意味着每个主机都需要相同的端口树版本,并且需要为自己编译所有包。 这意味着人和服务器重复的、容易出错的工作。 最好在每台主机上检索和使用相同的预构建二进制包,并从中央安全包存储库提供它们。

为了实现这一点,Poudriere 是 FreeBSD 上构建、测试和审计包以及维护包存储库的标准工具。 每个构建都在一个新的 监狱 中隔离运行,运行所需版本的 FreeBSD,并且从没有安装任何软件包开始。 只有基本系统以及任何明确指定的依赖项可用于干净构建。 Poudriere 负责在必要时重建包以及在构建完成后更新包存储库。 poudriere 命令行工具是管理不同端口树、FreeBSD 版本、端口构建选项以及运行构建的核心。

在本教程中,您将配置 Poudriere,构建一组所需的包,设置基于 HTTP 的包托管,并使用 Buildbot 作为持续集成平台自动构建。 最后,您将从客户端计算机安全地访问这些包。

注意:为了涵盖类似生产的用例,教程示例使用端口树季度稳定分支。 如果您定期从上游(Subversion 或其 GitHub 镜像)更新树,则保持在一个这样的分支上可以保护您免受重大更改的影响,并在必要时提供安全性和构建修复。 您可以选择在一个分支上停留较长时间,具体取决于开发人员/基础架构团队处理系统更新的速度。 ports 集合支持 FreeBSD 版本,直到它们成为生命周期结束 (EOL) - 请参阅 支持的 FreeBSD 版本 - 以便可以独立处理操作系统和软件包更新。 或者,您可以考虑从上游树克隆的本地版本控制存储库。 这样,您可以管理补丁并仅在您需要的时候合并上游更改。


先决条件

在开始本指南之前,您需要:

  • 运行 FreeBSD 11.2 的服务器。 如果您是使用 FreeBSD 的新手,您可能会发现按照我们关于 如何开始使用 FreeBSD 的指南自定义此服务器很有帮助。 注意: FreeBSD 12.0 目前有一个 嵌套监狱问题,在 12.x 可用于本教程之前,首先需要修复该问题。
  • 10 GB 可用磁盘空间或更多,以便有足够的容量来存储包和日志。
  • 通过完成 如何在 FreeBSD 上设置 Buildbot 教程来进行基本的 Buildbot 设置。
  • 另一台运行 FreeBSD 的服务器,相同版本,您将使用它作为客户端来获取和安装您将自动构建并托管在基于 HTTP/HTTPS 的包存储库中的包。

第 1 步 — 安装 Poudriere 以在 Buildbot Worker 中使用

完成先决条件教程后,您将拥有一个可以工作的 Buildbot 主机和工作监狱以及 Nginx 设置。 您将在以下步骤中基于此现有设置进行构建。 在第一步中,您将在工作监狱中安装构建工具 Poudriere,因为 Buildbot 工作进程稍后将触发构建。

连接到托管 Buildbot 的服务器并使用以下命令在工作监狱中打开 root shell:

sudo jexec buildbot-worker0 csh

将 Poudriere 安装为一个包:

pkg install poudriere

然后按 y 然后按 ENTER 确认安装。

注意: Buildbot、Poudriere等安装最好使用FreeBSD官方包仓库。 如果您自己构建这些工具包,那么您一开始就处于先有鸡还是先有蛋的境地:想要安装外部软件,但需要安装 Poudriere 才能获得干净构建的包。 由于 Poudriere 是一个非常稳定且向后兼容的工具,因此没有什么可以反对定期更新它并独立于您的生产包。

如果您遵循了先决条件教程,则已经是这种情况,您可以不遵循本说明继续。


您已成功安装最新的 Poudriere 工具和依赖项。 在接下来的几个步骤中,您将完成配置 Poudriere 的准备工作。

第 2 步 — 创建包签名密钥(可选)

建议为构建的包设置数字签名以提供更高的安全性。 如果您想稍后或以其他方式保护您的安装,请跳过此步骤。 否则,让我们继续创建一个用于签署包(使用私钥)和验证包(使用公共部分)的密钥对。

默认情况下,包被构建为 .txz 文件,它们是包内容的强压缩 tarball。 压缩文件的校验和以及通过 HTTP/HTTPS(TCP 校验和)提供文件,已经提供了一些防止数据损坏的保护。 包内容通常包括文件和目录以及元信息,例如包名称、版本和其他选项。 文件甚至可能包括 setuid-able 程序 (如 sudo 软件包中所见——尽管 sudo 未内置到 FreeBSD 中),并且安装时脚本运行为root 用户。 因此,从未经验证的来源安装会带来安全风险。

通过 HTTPS 提供软件包,您无法检测是否有人篡改了磁盘上的软件包。 可以通过将 Poudriere 配置为使用 RSA 私钥对包存储库进行签名来添加包的完整性和真实性。 签名的摘要和相应的公钥因此存储在包存储库的 digests.txz 文件中。 除非私钥丢失或泄露,否则所需的密钥对(RSA 私钥和公钥)可以长期保持不变。

在此步骤中,您将创建运行构建的密钥对(worker jail)并下载公共部分以供以后在包客户端上使用(在后面的步骤中讨论)。

确保您仍在工作人员监狱 root shell 中。

创建一个新的 RSA 私钥:

openssl genrsa -out /usr/local/etc/poudriere.key 4096

私钥文件只需要由 root(运行 Poudriere 的用户)访问。 保护其访问权限:

chmod 0600 /usr/local/etc/poudriere.key

稍后,您将需要客户端上可用的公钥部分来验证包签名。 现在让我们提取公钥:

openssl rsa -in /usr/local/etc/poudriere.key -pubout -out /tmp/poudriere.pub

最后,从您自己的计算机上下载公钥文件:

scp your-server:/usr/jails/buildbot-worker0/tmp/poudriere.pub /tmp/poudriere.pub

至此,可选择创建用于包签名的密钥对。 您稍后将使用 Poudriere 配置实际签名,并使用客户端上下载的公钥文件进行验证。

另一个可选步骤如下:如果您使用 ZFS 文件系统,Poudriere 可以利用它来加快构建速度。 否则,您可以跳到 步骤 4 来配置 Poudriere,以便为运行第一个构建做好准备。

第 3 步 — 设置 ZFS(可选)

此步骤仅适用于在 ZFS 文件系统 之上运行 FreeBSD 系统的情况。 例如,如果您使用的是 DigitalOcean Droplet,则图像标记为 11.2 x64 zfs(对于 FreeBSD 11.2)。 在这一步中,您将创建 Poudriere 可以用来更快地创建和管理监狱的文件系统,从而可能加快您的构建速度。

您可以通过列出池来了解您是否在使用 ZFS。 确保您在服务器的外壳上,而不是在监狱中。

exit

运行以下命令列出 zpool:

sudo zpool list

如果任何池可用,它将打印有关它的信息:

OutputNAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
zroot   148G  94.4G  54.1G        -         -    66%    63%  1.00x  ONLINE  -

否则,如果 ZFS 支持不可用,该工具将打印 no pools availablefailed to initialize ZFS library。 这意味着您的系统都没有使用 ZFS; 在这种情况下,请跳到下一步。 如果您决定使用其他磁盘或存储类型,例如 UFS 文件系统,您也可以继续下一步。

如果您计划使用 ZFS,请记住要存储构建相关数据的打印池名称。 您应该规划几 GB 的存储空间。

ZFS 有助于分离 Poudriere 的各种数据集,例如构建监狱、端口树、日志、包和其他数据。 这些是独立存储的,因此可以快速删除,并且不会留下可用空间或痕迹。

要让 Poudriere 使用 ZFS,您需要做三件事:创建父 ZFS 数据集,允许创建和删除 ZFS 数据集(Buildbot 工作监狱或任何其他监狱,默认情况下不能这样做),以及编辑Poudriere 的配置相应。

在先决条件教程中,您在 /etc/jail.buildbot-worker0.conf 中配置了 Buildbot worker jail。 使用您首选的文本编辑器打开此文件,并添加以下突出显示的行以委派父数据集,以允许监狱管理父数据集下的 ZFS 数据集。 请记住将 zroot 替换为您想要的池名称:

sudo ee /etc/jail.buildbot-worker0.conf

/etc/jail.buildbot-worker0.conf

buildbot-worker0 {
    host.hostname = buildbot-worker0.localdomain;
    ip4.addr = "lo1|10.0.0.3/24";
    path = "/usr/jails/buildbot-worker0";
    exec.start = "/bin/sh /etc/rc";
    exec.stop = "/bin/sh /etc/rc.shutdown";
    mount.devfs; # need /dev/*random for Python
    persist;

    exec.poststart = "/sbin/zfs jail buildbot-worker0 zroot/pdr/w0";
}

在本文中,我们将在 ZFS 池 zroot 上存储与构建相关的数据——如果您选择了不同名称的池,请在此处和本文的其余部分调整此 ZFS 相关配置。

添加此内容后,保存并退出编辑器。 如果您使用的是 ee,请按 CTRL+C,键入 exit,然后按 ENTER

创建配置文件中提到的父 ZFS 数据集:

sudo zfs create zroot/pdr
sudo zfs create zroot/pdr/w0

这故意假设您将来可能想要添加更多工作人员,因此为您的第一个工作人员创建一个子数据集。 数据集名称故意很短,因为旧版本的 FreeBSD(12.0 之前)的挂载名称限制为 88 个字符。

为了让监狱控制父数据集并管理任何子数据集,必须用以下标志标记数据集:

sudo zfs set jailed=on zroot/pdr/w0

现在满足先决条件后,jail 将使用新配置正确启动:

sudo service jail restart buildbot-worker0

通过这些说明,您成功地创建了所需的文件系统——ZFS 数据集——并允许监狱管理父数据集。 在下一步中,您将配置 Poudriere,其中涉及指定用于存储构建相关数据的所选 zpool 和数据集。

第 4 步 — 配置 Poudriere、Build Jail 和端口树

至此,您已经安装了 Poudriere 并可选地涵盖了包签名和 ZFS 的要求。 为了让 Poudriere 能够以“被监禁”的方式运行(即在 Buildbot 工作人员监狱中正常运行),您需要为监狱提供某些权限。 例如,如果您使用 ZFS,则您已经委托了一个父数据集供监狱使用和管理。

让我们先配置回环 IP 和所有权限,然后根据更改逐步了解各自的含义。

Poudriere 希望每个构建启动两个构建监狱:一个具有仅环回网络,另一个具有互联网访问权限。 只有应该连接到 Internet 的构建阶段才会使用后者。 例如,fetch 可以下载源 tarball,但 build 阶段不允许访问 Internet。 worker jail 的现有配置具有允许互联网访问的 ip4.addr = "lo1|10.0.0.3/24"。 为了允许 Poudriere 为新开始的构建监狱分配环回地址,还必须将 IP 传递给其父级(工人监狱)。 为此,请确保您已应用必备教程中最新版本的防火墙配置文件 /usr/local/etc/ipfw.rules,这将阻止环回接口 lo0 通过 NAT 打开传出连接。

将突出显示的行添加到您的工作人员监狱配置中:

sudo ee /etc/jail.buildbot-worker0.conf

/etc/jail.buildbot-worker0.conf

buildbot-worker0 {
    host.hostname = buildbot-worker0.localdomain;
    ip4.addr = "lo1|10.0.0.3/24";
    ip4.addr += "lo0|127.0.0.3";
    path = "/usr/jails/buildbot-worker0";
    exec.start = "/bin/sh /etc/rc";
    exec.stop = "/bin/sh /etc/rc.shutdown";
    mount.devfs; # need /dev/*random for Python
    persist;

    # If you followed the ZFS setup step, you have this line
    # already (keep it). For non-ZFS setup, this line must be absent.
    exec.poststart = "/sbin/zfs jail buildbot-worker0 zroot/pdr/w0";

    allow.chflags;
    allow.mount;
    allow.mount.devfs;
    allow.mount.nullfs;
    allow.mount.procfs;
    allow.mount.tmpfs;
    allow.mount.zfs; # only needed if you use ZFS
    allow.raw_sockets; # optional
    allow.socket_af; # optional
    allow.sysvipc; # optional
    children.max=16;
    enforce_statfs=1;
}

在这里,您添加了以下内容(另请参阅 jail(8) 手册页 ):

  • ip4.addr += "lo0|127.0.0.3" 将另一个 IPv4 地址添加到监狱。 稍后您将配置 Poudriere 的 LOIP4 变量,以便分配此环回地址来构建不应该与互联网或网络中其他机器通信的监狱,例如在 build 阶段。 如果您在构建期间有需要访问 Internet 的构建,Poudriere 支持变量 ALLOW_NETWORKING_PACKAGES 作为解决方法。 但是,最好在 Poudriere 允许 Internet 访问的 fetch 阶段遵循最佳实践并更早地执行下载和其他面向 Internet 的任务。
  • allow.chflags 允许 Poudriere 渲染某些系统文件,例如 /bin/sh 在构建监狱中不可变。
  • allow.mount 和其他 allow.mount.* 选项使 Poudriere 能够将某些必需的文件系统挂载到构建监狱中。
  • 允许使用原始套接字的 allow.raw_sockets 和允许使用任何套接字地址系列的 allow.socket_af 都适用于支持互联网的构建监狱。 这很有帮助,因此您可以在交互模式下运行 ping 之类的工具,例如进入构建监狱以调试问题时。
  • allow.sysvipc 被弃用,取而代之的是三个单独的设置 sysvmsg/sysvsem/sysvshm 来限制监狱只能看到他们自己的共享内存对象(通过“SYS V ” IPC 原语)。 但是,Poudriere 只能传递 allow.sysvipc 来构建 jail,因为它无法读取三个单独参数的相关 sysctl 信息(从 FreeBSD 11.2 开始)。 使用这种不推荐使用的配置,监狱可以读取监狱外进程的共享内存。 这仅与某些依赖 IPC 功能的软件有关,例如 PostgreSQL,因此影响安全性的可能性很小。 您可以删除此配置,除非您依赖于在构建期间需要它的端口。
  • children.max=16 允许工人监狱以下 16 个子监狱。 如果你有很多 CPU 并且 Poudriere 试图创建比允许更多的构建监狱,你可以稍后提高这个数字。 每个 Poudriere 构建将尝试为每个“作业”创建一个参考监狱和两个构建监狱,其默认设置是使用 CPU 数量(由 sysctl -n hw.ncpu 输出)作为作业计数。
  • 需要 enforce_statfs=1allow.mount 一起安装某些文件系统。

保存并退出配置文件。

重启 jail 使其配置立即生效:

sudo service jail restart buildbot-worker0

必须加载相应的内核模块,以便 Poudriere 可以执行挂载。 运行以下命令以在启动时立即加载模块:

sudo sysrc -f /boot/loader.conf nullfs_load=YES
sudo kldload -n nullfs
sudo sysrc -f /boot/loader.conf tmpfs_load=YES
sudo kldload -n tmpfs

您之前已经安装了 Poudriere 包,它已将示例文件 /usr/local/etc/poudriere.conf.sample 复制到 /usr/local/etc/poudriere.conf。 接下来,您将对配置文件进行编辑。 示例中已经存在所有可能的配置变量,因此请取消注释或修改文件中的相应行以将变量设置为某个值。

对于以下命令,请确保您仍在工作监狱中的 root shell 中:

sudo jexec buildbot-worker0 csh

使用以下命令打开文件:

ee /usr/local/etc/poudriere.conf

如果您决定使用 ZFS,请填写您想要的 zpool 和父数据集:

/usr/local/etc/poudriere.conf(片段)

. . .
# Poudriere can optionally use ZFS for its ports/jail storage. For
# ZFS define ZPOOL, otherwise set NO_ZFS=yes
#
#### ZFS
# The pool where poudriere will create all the filesystems it needs
# poudriere will use ${ZPOOL}/${ZROOTFS} as its root
#
# You need at least 7GB of free space in this pool to have a working
# poudriere.
#
ZPOOL=zroot

### NO ZFS
# To not use ZFS, define NO_ZFS=yes
#NO_ZFS=yes

# root of the poudriere zfs filesystem, by default /poudriere
ZROOTFS=/pdr/w0
. . .

否则,如果您决定不使用 ZFS,请禁用 ZFS 支持:

/usr/local/etc/poudriere.conf(片段)

. . .
# Poudriere can optionally use ZFS for its ports/jail storage. For
# ZFS define ZPOOL, otherwise set NO_ZFS=yes
#
#### ZFS
# The pool where poudriere will create all the filesystems it needs
# poudriere will use ${ZPOOL}/${ZROOTFS} as its root
#
# You need at least 7GB of free space in this pool to have a working
# poudriere.
#
#ZPOOL=zroot

### NO ZFS
# To not use ZFS, define NO_ZFS=yes
NO_ZFS=yes

# root of the poudriere zfs filesystem, by default /poudriere
# ZROOTFS=/poudriere
. . .

稍后您将指示 Poudriere 下载 FreeBSD 基础系统,从而引导第一个构建监狱。 这需要指定下载主机,添加以下突出显示的行:

/usr/local/etc/poudriere.conf(片段)

. . .
# the host where to download sets for the jails setup
# You can specify here a host or an IP
# replace _PROTO_ by http or ftp
# replace _CHANGE_THIS_ by the hostname of the mirrors where you want to fetch
# by default: ftp://ftp.freebsd.org
#
# Also note that every protocols supported by fetch(1) are supported here, even
# file:///
# Suggested: https://download.FreeBSD.org
FREEBSD_HOST=https://download.FreeBSD.org

由于 Poudriere 会在监狱中运行,因此 12.0 之前的 FreeBSD 版本的挂载名称限制为 88 个字符尤其有害,因为监狱 /usr/jails/buildbot-worker0 的完整路径是每个挂载路径的一部分。 超过限制将致命地破坏构建,所以让我们小心减少路径长度。 您可以使用 /pdr 代替典型的目录 /usr/local/poudriere,如下所示:

/usr/local/etc/poudriere.conf(片段)

. . .
# The directory where poudriere will store jails and ports
BASEFS=/pdr

现在,创建该目录:

mkdir /pdr

再次切换到 poudriere.conf 的编辑器:

ee /usr/local/etc/poudriere.conf

Poudriere 将在运行构建时为 dist 文件(每个端口的源代码 tarball)挂载一个中央目录,以便所有构建器共享相同的缓存。 默认目录是:

/usr/local/etc/poudriere.conf(片段)

. . .
# If set the given directory will be used for the distfiles
# This allows to share the distfiles between jails and ports tree
# If this is "no", poudriere must be supplied a ports tree that already has
# the required distfiles.
DISTFILES_CACHE=/usr/ports/distfiles

现在,创建该目录:

mkdir -p /usr/ports/distfiles

如果您按照步骤 2 并创建了包存储库签名密钥,请再次进入编辑器并指定它:

ee /usr/local/etc/poudriere.conf

/usr/local/etc/poudriere.conf(片段)

. . .
# Path to the RSA key to sign the PKG repo with. See pkg-repo(8)
PKG_REPO_SIGNING_KEY=/usr/local/etc/poudriere.key

如果您为下次缓存 C/C++ 编译器和链接器输出,构建将运行得更快。 端口树通过利用工具 ccache 直接支持这一点。 如果您可以多留出至少 5GB 的空间(默认缓存大小),请启用它并创建相应的缓存目录:

/usr/local/etc/poudriere.conf(片段)

. . .
# ccache support. Supply the path to your ccache cache directory.
# It will be mounted into the jail and be shared among all jails.
# It is recommended that extra ccache configuration be done with
# ccache -o rather than from the environment.
CCACHE_DIR=/var/cache/ccache
mkdir /var/cache/ccache

构建和运行 Linux 软件并不常见,因此在需要时禁用它:

ee /usr/local/etc/poudriere.conf

/usr/local/etc/poudriere.conf(片段)

. . .
# Disable linux support
NOLINUX=yes

监狱应该得到一个分配的环回地址,否则 Poudriere 会警告它。 我们可以继承监狱的 IP,因为它位于仅环回网络接口 (lo1) 上。 为此,请将以下行添加到配置文件的末尾:

/usr/local/etc/poudriere.conf(片段)

LOIP4=127.0.0.3

保存并退出配置文件。

对于工作构建,我们还需要两个资源:一个用作构建监狱模板的 FreeBSD 基础系统和一个最新的端口树。 选择您的目标 FreeBSD 版本。 在本教程中,我们将告诉 Poudriere 为 amd64 架构下载 FreeBSD 11.2。 您可以随意命名监狱,但建议使用一致的命名方案,如 112amd64。 还要记住在季度稳定端口树分支(这里,我们使用 2019Q2)和可能导致不时更新后破坏构建的前沿“头”分支之间的选择。 比服务器上更新的 FreeBSD 版本不能在 build jail 中使用。

下载并创建构建监狱:

poudriere jail -c -j 112amd64 -v 11.2-RELEASE -a amd64

最后,让我们下载端口树。 默认下载方法是 portsnap,它使用树的压缩快照,没有历史信息。 Subversion 或 Git 更适合合并上游更改或回馈。 如果您想在版本控制系统中使用自定义的自托管树,这一点也很重要。 在以下命令中,请填写当前年份和季度。

如果你想从上游的官方端口树开始:

poudriere ports -c -p 2019Q2 -m svn+https -B branches/2019Q2

方法 svn+https 将从 FreeBSD Subversion 主机同步( 可在此处在线查看 )。 如果您打算使用替代来源,请阅读以下说明,否则请跳过它。

注意: 作为替代方法,git 方法默认从 GitHub 上的 mirror 克隆树。

要使用“head”分支,请将最后一个参数替换为 -B head(用于 Subversion)或 -B master(用于 Git)。

如果您更喜欢使用自己的 Git 存储库,则必须明确指定存储库 URL 和分支名称。 假设您想将树命名为 customtree 并使用分支 custom

poudriere ports -c -p customtree -m git -B custom -U https://github.com/AndiDog/freebsd-ports.git

示例 URL 指向 GitHub 上的 freebsd-ports 分支,但可以是 CI 服务器有权访问的任何 Git 或其他受支持类型的存储库。


可用的树可以用 poudriere ports -l 列出,它输出如下列表:

OutputPORTSTREE METHOD    TIMESTAMP           PATH
2019Q2    svn+https 2019-04-20 19:23:19 /pdr/ports/2019Q2

您现在已经完成了 Poudriere 的配置和资源的设置。 您已经为 Poudriere 配置了触发第一次构建所需的数据并启用了监狱来创建子监狱。 接下来,您将手动运行第一个构建以验证设置是否正常工作。

第 5 步 — 运行手动测试构建

您可以使用命令 poudriere bulk 构建一个或多个包及其所有依赖项。 在第一次构建包后,Poudriere 还会自动检测是否需要重新构建,或者保持现有包文件不变。 虽然 bulk 子命令仅构建包,但使用 poudriere testport 运行构建还将使用端口的 Makefile 中给出的“测试”定义测试指定的端口。 在本文的范围内,我们只对提供在客户端上安装的软件包感兴趣,因此我们使用批量构建。

确保您仍在安装 Poudriere 的工作监狱的根 shell 中。 稍后,这也将是 Buildbot 工作进程将自动运行构建的地方。

运行构建,使用您之前选择的构建监狱名称和端口树名称填充占位符:

poudriere bulk -j 112amd64 -p 2019Q2 ports-mgmt/pkg

这将构建端口 ports-mgmt/pkg。 官方树中的端口存储在 <category>/<name> 层次结构中,这些路径(称为 package origin)用于告诉 Poudriere 应该构建哪些包。 一开始,我们选择只构建包管理器 pkg,它没有任何第三方依赖项,因此可以快速检查配置。 如果一切正常,您将看到如下输出:

Output[00:00:00] Creating the reference jail... done
[00:00:06] Mounting system devices for 112amd64-2019Q2
[00:00:06] Mounting ports/packages/distfiles
[00:00:06] Using packages from previously failed build
[00:00:06] Mounting ccache from: /var/cache/ccache
[00:00:06] Mounting packages from: /pdr/data/packages/112amd64-2019Q2
/etc/resolv.conf -> /pdr/data/.m/112amd64-2019Q2/ref/etc/resolv.conf
[00:00:06] Starting jail 112amd64-2019Q2
[00:00:07] Logs: /pdr/data/logs/bulk/112amd64-2019Q2/2019-04-20_19h35m00s
[00:00:07] Loading MOVED for /pdr/data/.m/112amd64-2019Q2/ref/usr/ports
[00:00:08] Ports supports: FLAVORS SELECTED_OPTIONS
[00:00:08] Gathering ports metadata
[00:00:08] Calculating ports order and dependencies
[00:00:08] pkg package missing, skipping sanity
[00:00:08] Skipping incremental rebuild and repository sanity checks
[00:00:08] Cleaning the build queue
[00:00:08] Sanity checking build queue
[00:00:08] Processing PRIORITY_BOOST
[00:00:08] Balancing pool
[00:00:08] Recording filesystem state for prepkg... done
[00:00:08] Building 1 packages using 1 builders
[00:00:08] Starting/Cloning builders
[00:00:14] Hit CTRL+t at any time to see build progress and stats
[00:00:14] [01] [00:00:00] Building ports-mgmt/pkg | pkg-1.10.5_5
[00:03:24] [01] [00:03:10] Finished ports-mgmt/pkg | pkg-1.10.5_5: Success
[00:03:25] Stopping 1 builders
[00:03:25] Creating pkg repository
Creating repository in /tmp/packages: 100%
Packing files for repository: 100%
[00:03:25] Committing packages to repository
[00:03:25] Removing old packages
[00:03:25] Built ports: ports-mgmt/pkg
[112amd64-2019Q2] [2019-04-20_19h35m00s] [committing:] Queued: 1  Built: 1  Failed: 0  Skipped: 0  Ignored: 0  Tobuild: 0   Time: 00:03:18
[00:03:25] Logs: /pdr/data/logs/bulk/112amd64-2019Q2/2019-04-20_19h35m00s
[00:03:25] Cleaning up
[00:03:25] Unmounting file systems

此输出显示包在构建后将去往何处,以及在不需要重新构建的情况下从何处获取现有包(此处:/pdr/data/packages/112amd64-2019Q2)。 此外,输出显示了 Poudriere 运行时正在运行的构建的概述(您可以在交互式 shell 中按 CTRL+T 以打印进度)。 在最后的摘要中,您将看到一个包已构建。 您可以在日志目录 (/pdr/data/logs/bulk/112amd64-2019Q2/*) 中查看详细的构建输出。

此输出确认构建成功。 如果 Poudriere 至少成功构建了一个包,它将自动将其提交到包存储库。 这意味着包仅在所有构建完成后才可用,即使其他包未能构建。 您现在在 Buildbot 工作人员监狱中的 /pdr/data/packages/112amd64-2019Q2 处拥有一个工作包存储库。

您已完成返回工作 Poudriere 构建所需的所有配置,并且您已通过手动构建成功验证。 在 Buildbot 中自动化批量构建后,您将在本教程后面看到相同的输出。 此外,应可从 Web 界面访问查看详细日志的链接。 为了实现这一点,并将包存储库提供给客户端,接下来您将设置一个 Web 服务器。

第 6 步 — 配置 Nginx 以服务于 Poudriere Web 界面和包存储库

Poudriere 提供了几个我们希望使用 Web 服务器托管的输出工件:

  • 包存储库可供客户端使用,因此他们可以使用常规的pkg updatepkg install命令访问它们,使用HTTPS或HTTP作为传输。
  • 详细的构建日志有助于开发人员调试有问题的构建或调查构建输出。 它们存储在每个包和每个构建中——在上一步的 Poudriere 输出中,您看到日志存储在每个构建的一个目录中,并标有日期和时间。
  • Poudriere 的内置 Web 界面 是一个小型的单个 HTML 页面,每个构建使用 WebSocket 定期更新页面上显示的状态。 这有助于更好地了解构建有多远,哪些依赖项触发了其他包构建失败,最后作为命令行输出的替代品,它只在最后显示一个摘要,除非你特别让它打印当前的构建进度。

Nginx 中的配置更改很短,因为只需要提供静态文件。 由于您要将它们提供给外部世界,因此您现在将在监狱外部的服务器上配置现有的 Nginx 实例,以从工作监狱中的路径提供上述文件。

请退出 jail shell,因为您现在要在服务器上工作:

exit

使用 Nginx 配置 /usr/local/etc/nginx/nginx.conf 打开一个编辑器:

sudo ee /usr/local/etc/nginx/nginx.conf

server { 块内添加以下位置:

/usr/local/etc/nginx/nginx.conf

. . .
http {
    . . .
    server {
        . . .
        location / {
            root /usr/local/www/nginx;
            index index.html index.htm;
        }

        # poudriere logs
        location ~ ^/logs(/(.*))?$ {
            include mime.types;
            types {
                text/plain log;
            }

            alias /usr/jails/buildbot-worker0/pdr/data/logs/bulk$1;
            index index.html index.htm;
            autoindex on;
        }

        # poudriere packages
        location ~ ^/packages(/(.*))?$ {
            alias /usr/jails/buildbot-worker0/pdr/data/packages$1;
            index no-index-file-but-required-directive-to-list-dir-contents;
            autoindex on;
        }

        location /buildbot/ {
            proxy_pass http://10.0.0.2:8010/;
        }

        . . .
    }
}
. . .

保存并关闭 Nginx 配置文件。 然后,重新加载 Nginx 服务:

sudo service nginx reload

现在让我们看看第一次手动构建创建的工件。 在本地计算机上打开您首选的 Web 浏览器以访问资源。

软件包存储库 位于 https://your-domain/packages/(或 http://your-server-ip/)下方。 您将在根目录中找到元信息,例如 112amd64-2019Q2,以及子目录All中的所有构建包:

详细的构建日志Poudriere的内置Web界面可以在https://your-domain/logs/下面找到。 单击目录层次结构以访问您之前手动构建的数据。 在此示例中,您可能最终会访问 https://your-domain/logs/112amd64-2019Q2/latest/build.html 之类的 URL。

如果您没有为您的服务器设置域名,您将需要为这些示例输入您的服务器的公共 IP 地址,例如 http://your-server-ip/logs/

这结束了所有手动设置以获取工作构建并查看输出(包和日志)。 展望未来,您将自动构建以实现 持续集成

第 7 步 — 为您的包设置 Buildbot 构建器

您在此步骤中的目标是通过以与手动方式相同的方式执行 Poudriere 来自动化批量包构建 - 通过添加到现有的 Buildbot 示例配置。 在此步骤结束时,只要端口树的所选分支发生更改,Buildbot 就会触发包构建。 在本教程的示例中,这将是季度分支 2019Q2

所有必要的更改都在 Buildbot 主配置中完成,因此请在主监狱中打开 root shell:

sudo jexec buildbot-master csh

首先,必须定义一个 builder 来描述为运行构建而执行的命令和操作。 在现有配置 /var/buildbot-master/master.cfg 中,您会找到一个节 ####### BUILDERS——打开一个编辑器并 替换 整个节,直到下一个以 ####### ... 开头的标题,使用以下配置:

ee /var/buildbot-master/master.cfg

/var/buildbot-master/master.cfg(片段)

. . .
####### BUILDERS

c['builders'] = []

PORTS_TO_BUILD = {
    'security/sudo',
    'shells/bash',
    'sysutils/tmux',
}


# Custom classes
class PoudriereLogLineObserver(util.LogLineObserver):
    _logsRe = re.compile(r'Logs: /pdr/data/logs/bulk(/[-_/0-9A-Za-z]+)$')

    def __init__(self):
        super().__init__()
        self._hadUrls = False

    def outLineReceived(self, line):
        if not self._hadUrls:
            m = self._logsRe.search(line.strip())
            if m:
                poudriereUiUrl = f'''{re.sub('/buildbot/$', '', c['buildbotURL'])}/logs{m.group(1)}'''
                self.step.addURL('Poudriere build', poudriereUiUrl)
                self.step.addURL('Poudriere logs', poudriereUiUrl + '/logs/')
                self._hadUrls = True


class PoudriereCompileStep(steps.Compile):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.addLogObserver('stdio', PoudriereLogLineObserver())


# Poudriere bulk build
bulkBuildFactory = util.BuildFactory()
bulkBuildFactory.addSteps([
    steps.ShellCommand(
        name='update ports tree',
        command=['sudo', 'poudriere', 'ports', '-u', '-p', '2019Q2', '-v'],
        haltOnFailure=True,
    ),
    PoudriereCompileStep(
        name='make bulk',
        command=['sudo', 'poudriere', 'bulk', '-j', '112amd64', '-p', '2019Q2'] + list(sorted(PORTS_TO_BUILD)),
        haltOnFailure=True,
    ),
])
c['builders'].append(util.BuilderConfig(name='bulk-112amd64-2019Q2',
                                        workernames=['worker0'],
                                        factory=bulkBuildFactory))
. . .

请注意这如何利用 Buildbot 的可扩展性:自定义类用于观察和解析来自 Poudriere 日志输出的信息。 即添加PoudriereLogLineObserver作为“日志观察者”,即 每当在构建期间打印新的日志行时都会调用它。 该类在日志中搜索日志目录并将其转换为超链接。 这些链接将与构建步骤一起显示,并将用户直接带到 Poudriere 的 Web 界面和日志。

在第一个构建步骤“更新端口树”中,我们使用 Poudriere 的内置更新命令 (ports -u) 来拉取最新版本的端口树。 这将自动使用之前配置的方法(例如 SVN/Git)。 这样,您可以确保软件包始终针对最新提交的树构建,如果您拥有自己的版本化存储库来维护软件版本和补丁,这将特别有用。

在顶部,列表 PORTS_TO_BUILD 指定应该构建哪些端口。 它用于在块底部指定的构建工厂的步骤中。 构建工厂是用于实例化构建的模板。 每当触发构建机器人时,Buildbot 都会创建一个唯一的构建,并且该构建使用当时为构建工厂定义的步骤的副本。 在这种情况下,我们正好配置了两个步骤:

  • 更新端口树。 由于此示例使用季度分支 2019Q2,因此它不会经常收到更改(通常只有安全和构建修复)。
  • 使用同一棵树运行批量构建。

要使添加的代码块工作,请在文件顶部添加所需的导入:

/var/buildbot-master/master.cfg(片段)

# -*- python -*-
# ex: set filetype=python:

import re

from buildbot.plugins import *

Python 中的 re 库实现了 正则表达式 ,这是一种搜索或替换部分字符串的功能 - PoudriereLogLineObserver 类使用它来搜索行 [ X175X] 提到了日志目录。

构建命令使用 sudo 来运行某些命令。 这是必需的,因为 Poudriere 在运行构建时需要超级用户权限——以便创建、管理和销毁构建监狱——并且 Poudriere 管理的端口树也是以 root 用户作为所有者创建的。 在前面的教程中,我们为运行 Buildbot 工作进程的用户配置了 sysrc buildbot_worker_uid=buildbot-worker。 因此,我们希望允许 buildbot-worker 用户以 root 身份运行所需的命令,而不是其他命令(出于安全原因)。 让我们安装 sudo 程序并进行相应的配置。

这需要在工人监狱而不是主人上完成。 请退出主监狱外壳并进入工人监狱:

exit
sudo jexec buildbot-worker0 csh

安装 sudo 包:

pkg install sudo

yENTER 确认安装。

在 FreeBSD 上,sudo 软件包默认从 /usr/local/etc/sudoers.d/ 读取配置文件。 打开编辑器以创建新的配置文件:

env EDITOR=ee visudo /usr/local/etc/sudoers.d/buildbot-worker

使用 visudo 是有意的,因为它会警告语法错误并允许修复它们而不是提交错误的配置。

指定 buildbot-worker 用户可以在不需要任何密码的情况下以 root 身份运行哪些命令:

/usr/local/etc/sudoers.d/buildbot-worker

buildbot-worker ALL=(ALL) NOPASSWD: /usr/local/bin/poudriere bulk *
buildbot-worker ALL=(ALL) NOPASSWD: /usr/local/bin/poudriere ports -u *

保存文件并切换回 master jail 以进一步配置 Buildbot master:

exit
sudo jexec buildbot-master csh

您刚刚满足了使批量构建工作的要求。 但如前所述,每个构建都必须 触发 才能运行。 Buildbot 使用术语 scheduler 来表示定义何时触发构建的对象,以及包含哪些额外信息,例如已更改的分支。 请把配置文件中已有的SCHEDULERS去掉,把下面的内容放在BUILDERS节的之后,这样代码就可以全部使用了现有的建造者名称:

ee /var/buildbot-master/master.cfg

/var/buildbot-master/master.cfg(片段)

. . .
####### SCHEDULERS

c['schedulers'] = []

# Forceful scheduler allowed for all builders
c['schedulers'].append(schedulers.ForceScheduler(
    name='force',
    builderNames=[builder.name for builder in c['builders']]))

# Watch ports tree for changes on given branch
c['schedulers'].append(schedulers.SingleBranchScheduler(
    name='sched-bulk-112amd64-2019Q2',
    change_filter=util.ChangeFilter(project='freebsd-ports', branch='branches/2019Q2'),
    builderNames=['bulk-112amd64-2019Q2']))
. . .

这将替换示例配置,以便在每个构建器上显示 force 按钮。 最重要的是,它创建了一个调度程序来监视与给定 project/branch 相关的所有更改,并为每个更改触发构建。 然而,不会发生这样的更改事件——您首先必须创建一个 更改源 。 通常,这些是 版本控制系统 ,例如 SVN 或 Git,可以在其上检测分支上的更改。 Buildbot 支持最流行的,因此我们可以使用它的功能将我们选择的上游端口树存储库添加为源。 将 CHANGESOURCES 部分完全替换为以下配置:

/var/buildbot-master/master.cfg(片段)

. . .
####### CHANGESOURCES

c['change_source'] = []

c['change_source'].append(changes.SVNPoller(
    'svn://svn.freebsd.org/ports/',
    project='freebsd-ports',
    split_file=util.svn.split_file_branches,
    svnbin='svnlite',
    pollInterval=4 * 3600))

# Example for Git:
# c['change_source'].append(changes.GitPoller(
#     repourl='https://github.com/AndiDog/freebsd-ports.git',
#     project='freebsd-ports',
#     branches=['custom'],
#     pollInterval=4 * 3600))
. . .

这会在 Buildbot 主服务器上每四个小时轮询一次 SVN 存储库,并且任何新的(以前未见过的)更改都将转发到匹配的调度程序,这反过来会触发构建,这些构建最终会被分派到我们的单个 Buildbot 工作人员上运行。 端口树非常大,在第一次运行时,这些轮询器将下载完整的历史记录(对于 Git,只有指定的分支),这可能需要几分钟并且需要大量空间(数 GB)。

通过重新启动 Buildbot 应用新的配置文件:

service buildbot restart

在此示例中,您使用了来自 svn://svn.freebsd.org/ports/ 的上游端口集合,并且每当分支 2019Q2 更改时都会安排构建。 如前所述,季度分支大多是稳定的,不会经常收到更新。 由于您可能不想在第一次触发构建之前等待此类更改出现,因此让我们手动运行一次。

打开您的 Buildbot Web 界面 (https://your-domain/buildbot/),导航到 Builds > Builders > bulk-112amd64-2019Q2。 它不会显示任何构建。

单击右上角的 force 按钮,然后单击 Start Build。 这将使用其默认设置触发构建,即 原因、分支和其他值不会被覆盖。 “更新端口树”步骤可能需要一分钟才能运行,最终 Poudriere 构建也应该成功运行。 Web 界面将显示构建成功。

单击其中一个链接(Poudriere buildPoudriere logs)将带您进入 Poudriere Web 界面并分别针对此特定构建构建日志(如步骤 6 所示)。 单击 make bulk 旁边的箭头,然后单击 stdio > 查看所有…行 以显示 poudriere bulk ... 命令的完整输出。

完成第一次构建后,现在可以使用包,如第 6 步中 Nginx 中的配置。 在浏览器中前往 https://your-domain/packages/(或 http://your-server-ip/packages/)并单击由 Poudriere 创建的包存储库。 进入其中一个存储库并导航到 All/ 子目录后,您可以找到实际的包文件 (*.txz)。

现在包可以通过 HTTPS(或 HTTP,如果您决定这样做)并且自动构建在端口树更改上,您可以配置一个或多个主机来使用这些包。

第 8 步 — 配置包客户端

在这一步中,您需要第二个 FreeBSD 服务器并将其设置为可以获取和安装构建在 CI 服务器上的软件包。 我们将这第二台服务器称为 包客户端

SSH 进入 客户端 主机。 本节中剩余的大部分指令将在 客户端 上完成:

ssh package-client

为自定义包存储库配置创建目录:

sudo mkdir -p /usr/local/etc/pkg/repos

作为 root 用户,打开编辑器以创建文件 /usr/local/etc/pkg/repos/ci.conf,并指定检索包的方式和位置:

sudo ee /usr/local/etc/pkg/repos/ci.conf

如果您选择包签名,请使用以下内容:

/usr/local/etc/pkg/repos/ci.conf

ci: {
    url: "https://your-domain/packages/112amd64-2019Q2",
    signature_type: "pubkey",
    pubkey: "/usr/local/etc/pkg/repos/ci.pub",
    enabled: yes
}

或者,如果您决定不使用包签名,请禁用签名检查,如下所示:

/usr/local/etc/pkg/repos/ci.conf

ci: {
    url: "https://your-domain/packages/112amd64-2019Q2",
    signature_type: "none",
    enabled: yes
}

注意: 仅当您按照步骤 2 创建包存储库签名密钥时,此说明才适用。 否则请跳过。

从您的 本地计算机 中,将公钥上传到包客户端:

scp /tmp/poudriere.pub package-client:/tmp/ci.pub

再次使用 客户端外壳 ,将密钥移动到位,以便它可以验证包的真实性:

sudo mv /tmp/ci.pub /usr/local/etc/pkg/repos/ci.pub

您完成了软件包存储库的配置并启用了它,但是在常规的 FreeBSD 安装中,官方软件包存储库“FreeBSD”也将被启用。 由于不兼容的软件版本或不同的 ABI、API 或构建选项,混合来自不同来源的已安装包是一种万无一失的方法,可以让您的生产软件在某些时候崩溃。 主机上的所有软件包都应来自同一来源。

官方仓库的默认配置存放在/etc/pkg/FreeBSD.conf中。 该文件属于基本系统,不应触碰。 但是,您可以通过在 /usr/local/etc/pkg/repos 下的配置文件中添加相应的标志来覆盖其设置 - 即,我们希望完全禁用存储库,您自己的存储库也在其中配置。 请使用编辑器创建一个新文件 /usr/local/etc/pkg/repos/FreeBSD.conf,并使用以下内容禁用 FreeBSD 存储库:

sudo ee /usr/local/etc/pkg/repos/FreeBSD.conf

/usr/local/etc/pkg/repos/FreeBSD.conf

FreeBSD: {
    enabled: no
}

如果您使用的是完全原始的 包客户端 主机,则尚未安装任何包,您可以立即开始使用自己的包存储库。 但是,即使仅从另一个来源安装了一个包,建议您卸载这些包并使用您自己的来源从头开始。 包管理器 pkg 本身是作为一个包安装的——为了解决先有鸡还是先有蛋的问题,FreeBSD 的基础系统附带了一个小的可执行文件 /usr/sbin/pkg,它可以引导包管理器。 也就是说,下载 pkg 包并将其作为系统上的第一个包安装。 从那时起,该包的可执行文件 /usr/local/sbin/pkg 支持您作为成熟的包管理器。

运行以下命令引导 pkg

sudo pkg bootstrap

pkg bootstrap 的输出中,您应该看到包是从您自己的包存储库中获取的,我们在配置文件中将其称为 ci。 如果您使用包签名密钥,输出还将提示安全验证。

OutputThe package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: y
Bootstrapping pkg from https://your-domain/packages/112amd64-2019Q2, please wait...
Verifying signature with public key /usr/local/etc/pkg/repos/ci.pub... done
Installing pkg-1.10.5_5...
Extracting pkg-1.10.5_5: 100%

如果你看到这个成功的输出,请跳到下一个注释块。 但是,如果包管理器或其他包已经从另一个源安装,你会得到这个错误:

Outputpkg already bootstrapped at /usr/local/sbin/pkg

然后请按照说明中的说明进行操作。

注意 – 仅当包管理器已经被引导时:

您可以使用 pkg info 列出已安装的软件包。 在这种情况下,您应该卸载包括 pkg 在内的所有它们,然后再重新安装它们。 为此,请首先使用 pkg query -e "%a==0" "%n" 列出手动安装的软件包。 记住以后要再次安装其中的哪一个。 例如,如果您使用的 shell 不是基本系统的一部分(例如 bash 是一个外部包),您将需要稍后重新安装它,否则您可能无法再次登录。

以下命令将删除所有现有包和包管理器,从您自己的包存储库中再次引导包管理器,并给出重新安装所需包(如 bash)的示例。 请注意,您将只能安装通过 CI 构建的软件包,即 在 Buildbot 主配置中列出(变量 PORTS_TO_BUILD)。

首先,在卸载 sudo 软件包之前打开一个 root shell,否则您可能无法再获得超级用户权限。 保持打开状态,直到您通过教程引导 pkg 并成功重新安装 sudo

sudo sh

卸载所有包,包括pkg

pkg delete --all --force

引导包管理器:

pkg bootstrap

y 确认引导包管理器,然后按 ENTER


在您使用 Let's Encrypt HTTPS 证书设置包主机的可能情况下,您将遇到先有鸡还是先有蛋的问题,即您的包主机不受信任,但您需要安装包 [X229X ](包含可信赖的根证书颁发机构)以信任 Let's Encrypt CA,从而也信任托管您定制包的服务器。 如果您使用内部 CA(由您或您的公司自签名),也会出现同样的问题。 引导包管理器时,证书验证错误会导致如下错误输出:

OutputThe package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: y
Bootstrapping pkg from https://example.com/packages/112amd64-2019Q2, please wait...
Certificate verification failed for /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
34389740104:error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed:/usr/src/crypto/openssl/ssl/s3_clnt.c:1269:
[...]

如果您看到此错误,请按照以下说明中的说明进行操作。 否则,您已经准备就绪,可以跳过这部分并在注释之后继续。

注意 – 仅在使用 HTTPS 且证书验证失败时:

有一个直接的解决方法:信任包签名密钥的安全性,因此引导 pkg 并通过未加密的 HTTP 安装 ca_root_nss 包。 由于隐私问题、阻塞的 HTTP 端口等原因,这并不总是一种选择,我们应该更喜欢一种“最佳实践”的方式。 官方的 FreeBSD 存储库也由 Let's Encrypt 签名,因此我们不能简单地从那里安装 ca_root_nss 包。 无论是哪个 CA,建议您使用一组固定的 HTTPS CA 来设置您的软件包客户端以进行信任。 您可以在接下来的几条指令中完全实现这一点。 我们将假设这是为 Let's Encrypt 准备的,但这些说明对您自己的自签名 CA 的工作方式相同(您需要方便的证书链)。

在您的 Web 浏览器中,访问位于 https://letsencrypt.org/certificates/ 的 Let's Encrypt 证书列表。 确保网站受到浏览器的信任。 以 PEM 格式下载 Root Certificates > Active > ISRG Root X1 (self-signed)Intermediate Certificates > Active > Let's Encrypt Authority X3 (Signed by ISRG Root X1) 下的证书到/tmp/root.pem/tmp/intermediate.pem 分别在本地计算机上。

下载成功后,将文件连接到证书链中:

cat /tmp/intermediate.pem /tmp/root.pem >/tmp/letsencrypt-chain.pem
scp /tmp/letsencrypt-chain.pem package-client:/tmp/.

回到包客户端的外壳,您现在需要在包管理器配置/usr/local/etc/pkg.conf中指定此信任链,以便将其用于TLS验证。 使用编辑器添加这些行,如果文件尚不存在,则创建该文件:

sudo ee /usr/local/etc/pkg.conf

/usr/local/etc/pkg.conf(片段)

pkg_env: {
    SSL_CA_CERT_FILE: "/usr/local/etc/pkg/repos/letsencrypt-chain.pem",
}

将 CA 链移动到位:

sudo mv /tmp/letsencrypt-chain.pem /usr/local/etc/pkg/repos/.

如果您因为 sudo 包被删除而直到现在还停留在 root shell 中,则该命令必须在没有 sudo 的情况下运行。 这同样适用于本注释中的下一个命令。

使用此设置,您可以再次尝试引导,并且不应再收到任何 TLS 错误。 有一个小转折:FreeBSD 内置的 /usr/sbin/pkg,它引导完整的包管理器,不支持配置的 pkg_env 设置,所以我们必须覆盖相应的环境变量。仅时间,使用与配置相同的值:

sudo env SSL_CA_CERT_FILE=/usr/local/etc/pkg/repos/letsencrypt-chain.pem pkg bootstrap

如果您之前删除了现有的软件包,现在是重新安装基本工具的好时机(例如 sudo),以及任何其他所需的软件包。

pkg install bash sudo

如果仍然如此,请退出 root shell:

exit

为了测试一切是否正常,请从 Buildbot 主配置(变量 PORTS_TO_BUILD)中指定的列表中安装软件包。 例如,Bash shell 和 sudo:

sudo pkg install bash sudo tmux

再次按 y 确认安装,然后按 ENTER。 软件包安装应该没有任何问题地运行。

您可以使用 pkg info 列出当前安装的软件包(包括依赖项,如果有的话)。 要验证没有安装来自其他来源的软件包,可能会导致冲突或不兼容,您可以使用 pkg query "%n: autoinstalled=%a from repo=%R" 列出已安装的软件包以及这些详细信息。 请注意,pkg 将显示为从 unknown-repository 引导 - 这就是为什么之前,您验证引导输出以查看包管理器本身也是从您自己的包存储库中获取的。

在最后一步中,您在客户端上配置了对 CI 包存储库的访问权限,出于安全目的可选地启用包签名验证,确保包仅来自单一来源以避免兼容性问题,引导包管理器 pkg ,并安装由 CI 构建的所需软件包。

结论

在本教程中,您已经安装和配置了 Poudriere,自动运行包构建,并配置了从客户端主机对包存储库的安全访问,最终从单个中央源安装了最新构建的包。 该设置使您处于保持服务器一致和最新状态以及管理外部软件包版本升级的绝佳位置。

为了进一步增强您当前的设置,您可以考虑选择后续步骤:

  • 仅限私人访问:默认情况下,Droplet 在互联网上有一个公共 IP 地址。 此外,Buildbot 支持身份验证,但默认情况下不受保护。
  • 关于构建问题的警报:查看如何设置 Buildbot 报告器 以开始使用。
  • 保持端口树为最新:在本教程的示例中,使用了 季度分支 2019Q2,但您最终应该切换到更新的树或使用您自己的版本控制存储库应用所需的补丁。
  • 为自己的项目添加构建:如果您想构建和安装内部软件FreeBSD 软件包。
  • 监控客户端上的过期包:您可以使用 sudo pkg update -q && sudo pkg version -q --not-like "=" 的输出将客户端上已安装的包与 CI 上的最新可用包进行比较,该输出会打印所有版本不完全匹配的包。 有关详细信息,请参阅 pkg-version 手册页。
  • 添加清理工作:随着时间的推移,Buildbot 工作监狱将运行完整的旧构建日志文件、源 tarball 和可能已弃用的包。 使用命令 poudriere {logclean,distclean,pkgclean} 进行清理(参见 poudriere 手册页)。