wanna build 和 buildd 不完全使用指南

最近在 Debian 上折腾Debian for rva22 ,看了一下 Debian 提供了较为完善的生态能够很方便的构建和维护自己的发行版。主要用到的工具有 wanna build , reprepro , buildd 这三个。他们的关系图如下:

wanna build , buildd , reprepro 关系图

接下来我介绍以下这三种工具的使用和他们的联系,大部分的内容是基于 debian wiki 的信息,还有少部分内容是踩过的一些坑。

通常情况下, wanna build 和 reprepro 是在同一台性能一般的机器上,主要负责仓库管理和维护。 buildd 运行在性能强劲的构建机上的,可以有一台或者多台。

1. reprepro

1.1 install

Debian 仓库中提供了 reprepro,因此可以直接安装

1
apt-get install reprepro

1.2 创建仓库目录

1
2
3
mkdir -p /srv/ftp.debian.org/ftp/apt/
cd /srv/ftp.debian.org/ftp/apt/
mkdir conf dists incoming indices logs pool project

这里,第一个路径 /srv/ftp.debian.org/ftp/apt/ 可自行替换,建议替换为当前想要构建的版本代号。例如:我的 rva22 的路径就是 /repo/rva22/repo

1.3 配置文件

配置文件在 conf 路径下

1
cd /srv/ftp.debian.org/ftp/apt/conf/

1.3.1 distributions

1
vim distributions
1
2
3
4
5
6
7
Origin: Alexander Pashaliyski
Label: Alexander Pashaliyski
Codename: sid
Architectures: i386 amd64 source
Components: main
Description: Alexander Pashaliyski APT Repository
SignWith: yes

下面是一些字段解释:Origin 代表仓库维护者或组织名称,Label 代表仓库名称,Codename 表示发行版的代号,Architectures 指定该仓库支持的 CPU 架构,Components 表示该仓库包含的组件,Description 说明该仓库的用途,SignWith 指定是否对仓库进行 GPG 签名。

同时还有一些字段这里面没有显示出来,包括了 Version,UDebComponents,Log 同时还能指定 log 文件,方便日后定位问题。

同时,一个 distributions 中可以写多个仓库,但是最好还是创建不同的仓库目录会更好。但是如果你像我一样建立仓库导入 source 的时候没有仔细甄别,遇到 oracular
中依赖了 oracular-security 的 pkg,那就可以写在同一个 distributions 中。

1.3.2 incoming

1
vim incoming
1
2
3
4
5
Name: default
IncomingDir: incoming
TempDir: /tmp
Allow: sid
Cleanup: on_deny on_error

incoming 是定义如何处理上传到仓库的 .deb 包。它有 5 个字段。 比较重要的是 Allow 字段,表明了允许导入的软件包的目标发行版,不再目标发行版中的软件包将无法被导入。

1.3.3 options

options 用来定义 reprepro 的基本工作目录和行为, wiki 中这部分的内容比较少,我在补充以一下我的配置

1
vim options
1
2
3
4
5
verbose
basedir repo/xxx
outdit out/xxx
morguedir +o/archrives
logdir +o/log

以下是字段解释

  • verbose: 开启详细模式,方便排查问题
  • basedir: 仓库的基础目录,所有的操作都将会在这个目录中
  • outdit: 输出目录,可用于 web 服务器提供仓库服务
  • morguedir: 存放删除的软件包,避免手滑
  • logdir:日志目录,方便记录日志

1.3.4 updates

上游配置,用于从上游仓库同步软件包

1
vim updates
1
2
3
4
5
6
7
Name: import
Method: https://mirror.nju.edu.cn/xxxxx
Suite: oracular
Components: main restricted universe multiverse
Architectures: source
IgnoreRelease: yes
UDebComponents: main

这是我的配置,字段解释如下

  • Name: 规则名称
  • Method: 上游仓库的地址
  • Suite: 发行版名称,需要和 distributions 中的 codename 匹配
  • Components: 指定拉去的软件包组件
  • Architectures: 需要同步的架构,因为这边我准备完全重新编译,所以就只导入了源代码
  • IgnoreRelease: 是否要忽略 Release 文件校验
  • UDebComponents: 指定 udeb 组件

同样,一个 update 中也可以写多个 import 规则,只需要名字和对应的发行版区分开就好

至此, reprepro 的基础配置就已经完成了。

1.4 使用

1.4.1 更新软件包索引

获取上游软件包,更新软件包索引

1
reprepro -b . update oracula

注意: 执行这条命令的时候需要在 /srv/ftp.debian.org/ftp/apt/ 目录下,其中的 . 指的是当前路径。如果不在 /srv/ftp.debian.org/ftp/apt/ 路径下,需要将 . 替换为绝对路径,该命令变形为:

1
reprepro -b /srv/ftp.debian.org/ftp/apt/ update oracula

1.4.2 导入 deb 包/ dsc 文件

1
2
3
reprepro -b /srv/ftp.debian.org/ftp/apt/ includedeb oracular *.deb

reprepro -b /srv/ftp.debian.org/ftp/apt/ includedsc oracular *.dsc

1.4.3 查看软件包 list

1
reprepro -b /srv/ftp.debian.org/ftp/apt/ list oracular

1.4.4 删除 deb 包

1
reprepro -b /srv/ftp.debian.org/ftp/apt/ removesrc oracular  pkgname

以上就是 reprepro 的基本操作和配置,还有部分操作等之后遇到了在继续分享。

wanna build

install

wanna build 和 reprepro 不一样, wanna build 目前并不是 debian 的一个软件包,所以需要手动安装。还好官网给了不错的安装教程。

  1. 通过 github 获取 wanna build 的仓库

    1
    2
    3
    mkdir -p /srv
    git clone https://salsa.debian.org/wb-team/wanna-build.git /srv/wanna-build
    ln -s /srv/wanna-build/bin/wanna-build /usr/local/bin/wanna-build
  2. 安装运行依赖

    1
    apt install libdbi-perl libyaml-libyaml-perl libhash-merge-perl libstring-format-perl libtimedate-perl libyaml-tiny-perl libdpkg-perl libdbd-pg-perl libany-uri-escape-perl dctrl-tools moreutils dose-builddebcheck dose-distcheck
  3. 安装数据库

    1
    apt-get install postgresql-${version} postgresql-${version}-debversion
  4. 导入数据库

    切换到数据库用户

    1
    2
    su postgres
    psql

    创建数据库

    1
    2
    3
    4
    CREATE DATABASE wannadb;
    CREATE USER wbadm WITH PASSWORD 'wannapass';
    GRANT ALL PRIVILEGES ON DATABASE wannadb to wbadm;
    ALTER ROLE wbadm CREATEROLE;

    退出数据库,然后导入 sql 文件

    1
    2
    3
    4
    quit

    psql -d wannadb -f /srv/wanna-build/schema/roles.sql
    psql -d wannadb -f /srv/wanna-build/schema/main-tables.sql
  5. 生成特定架构的 wanna build 表

    1
    2
    cd /srv/wanna-build/schema/
    ./arches-tables.sh $ARCH | psql -d wannadb

    注意: $ARCH 记得替换成想要生成的架构, 包括不限于 riscv64, x86 等。请按需填写

  6. 创建 wanna build 用户

    1
    2
    3
    4
    5
    su
    adduser --disabled-password --gecos "" wbadm
    mkdir -p /srv/wanna-build/tmp
    chmod 750 /srv/wanna-build/tmp/
    chown wbadm /srv/wanna-build/tmp/

    wanna build 配置完成之后,大部分的操作都会在这个用户下进行

  7. 配置 wbadm 和 sql 的连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cp /usr/share/postgresql/*/pg_service.conf.sample /etc/postgresql-common/pg_service.conf

    cat >> /etc/postgresql-common/pg_service.conf
    [wanna-build]
    dbname=wannadb
    user=wbadm

    [wanna-build-privileged]
    dbname=wannadb
    user=wbadm

    同时允许 wbadm 用户允许本地访问数据库

    1
    2
    3
    vim /etc/postgresql/*/main/pg_hba.conf

    local all wbadm trust

    这里面的 * 请自行替换为自己的 sql 版本

  8. 重启数据库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        /etc/init.d/postgresql restart
    ````

    ### 插入架构和构建版本信息

    这部分内容都是对数据库的操作,其中很多内容都需要进行替换。

    1. 登录到 wbadm 数据库

    ```sh
    su postgres
    psql -U wbadm -d wannadb
  9. 定义支持的架构和发行版

    1
    2
    3
    4
    INSERT INTO distributions(distribution,build_dep_resolver) VALUES ('sid','apt');
    INSERT INTO architectures(architecture) VALUES ('amd64'),('i386');
    INSERT INTO distribution_architectures(distribution,architecture,archive) VALUES ('sid','amd64','debian'),('sid','i386','debian');
    INSERT INTO locks(distribution,architecture) VALUES ('sid','amd64'),('sid','i386');

    这里面的 distributionarchitecture 要和 reprepro 中的配置保持一致。

  10. 设定发行版别名 (可选)

    1
    INSERT INTO distribution_aliases(distribution,alias) VALUES('sid','unstable');

    表示 unstable 是 sid 发行版的 别名。

添加 Packages-arch-specific

packages-arch-specific 是debian 中列出仅适用于特定架构的软件包的一个文件。 因为我只是单一架构,所以并未涉及到这部分,就只做摘录。
1
2
3
4
5
su
SUITE=sid
mkdir -p /srv/buildd.debian.org/web/quinn-diff/${SUITE}
cd /srv/buildd.debian.org/web/quinn-diff/${SUITE}/
wget https://buildd.debian.org/quinn-diff/${SUITE}/Packages-arch-specific

添加软件包到数据库

这里面需要用到一个 trigger.local 的文件。
wiki 上有这样一份文件案例,我只讲述修改的部分。

1
2
3
4
5
ARCHIVE='local'
SUITES="sid"
ARCHES="amd64 i386"

REPOSITORY='/org/ftp.debian.org/ftp/apt/dists'

需要注意的是文件开头的部分

  • ARCHIVE 指定的是储存库的名称,可以任意起名
  • SUITES 指定支持的发行版,和 distribution 保持一致。
  • ARCHES 指定支持的架构,记得按需修改
  • REPOSITORY 这个很重要,指定了仓库的 dists/ 目录路径,里面存放的是 Packages.gz 和 Release 文件。这个路径是 reprepro 的路径,记得一直写到 dists 层。
1
2
3
4
5
6
# copy trigger.local into /srv/wanna-build/triggers
su
chmod a+x /srv/wanna-build/triggers/trigger.local
su wbadm
cd /srv/wanna-build/triggers
./trigger.local

有几个仓库就需要有几个 trigger.local,当然是可以更改名称和后缀了,为了便于多仓库之间的区分,我建议直接用仓库名称命名。

踩坑小贴士

1
2
3
4
5
6
7
for suite in $SUITES
do
SOURCES="Sources.$suite.incoming-filtered.gz"
filter_out_nonfree "$ARCHIVE_BASE/archive/$suite/main/source/Sources.gz" "$SOURCES"
PACKAGES="$ARCHIVE_BASE/archive/$suite/main/binary-%ARCH%/Packages.gz"
trigger_wb_update "$suite" "$ARCHES" "$SOURCES" "$PACKAGES"
done

trigger.local 里面有一点点小坑,里面用到了一个脚本 filter_out_nonfree 已经被移除了,会报错找不到命令。我们研究后发现, filter_out_nonfree 这个函数并没有做什么别的事情,只是在复制而已。于是可以直接简单除暴的修改为 cp,修改后的如下

1
2
3
4
5
6
7
8
for suite in $SUITES
do
SOURCES="Sources.$suite.incoming-filtered.gz"
cp "$ARCHIVE_BASE/archive/$suite/main/source/Sources.gz" "$SOURCES"
PACKAGES="$ARCHIVE_BASE/archive/$suite/main/binary-%ARCH%/Packages.gz"
trigger_wb_update "$suite" "$ARCHES" "$SOURCES" "$PACKAGES"
done

常用命令

命令都需要在 wbadm 用户下来运行,否则会有权限问题

  1. 添加完软件包后,就可以来看软件包的情况了
1
wanna-build --list all --arch riscv64 -d oracular

这会打印出 oracular 仓库下所有软件包的信息。 其中 list 的状态有以下几种,可以根据具状态来筛选不同的软件包 Auto-Not-For-Us,BD-Uninstallable,Build-Attempted,Building,Built,Installed.

  1. 设置软件包的状态,比如说某个失败的软件包,我修改后想要重新 build ,目前我暂未找到更好的方案,现在是直接修改数据库
1
2
sudo -u postgres psql -d wannadb -U wbadm

1
UPDATE packages SET state='Needs-Build' WHERE distribution='oracular' AND architecture='riscv64' AND state='BD-Uninstallable'

这一条就是将所有依赖问题导致失败的软件包重新设置为需要 build ,然后 wanna build 就会给 buildd 下发 build 任务,让这些软件包再次构建。

buildd

安装

1
apt-get install sbuild buildd sudo schroot debootstrap

设置 sbuild 和 schroot

sbuild 和 schroot 的资料有很多,这边就不赘述。

配置 buildd

  1. 添加 buildd 用户,在 sbuild 组下
1
usermod -a -G sbuild buildd
  1. 修改配置 buildd 配置文件
1
vim /etc/buildd/buildd.conf

以下是我在用的的 buildd conf

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
# build 架构
$build_arch ='riscv64';

# 仓库信息
$distributions = [
{
# 指定定支持的发行版,和 `distribution` 保持一致
dist_name => ['oracular'],
# build 架构
built_architecture => $build_arch ,
# wanna build 服务器 ip
wanna_build_ssh_host => "xxx.xxx.xxx.xx",
# wanna build 服务器 ssh 用户名和数据库用户名,这些不用修改
wanna_build_ssh_user => "buildd",
wanna_build_db_user => "wbadm",
# dupload 配置
dupload_local_queue_dir => "upload",
logs_mailed_to => $admin_mail,
# 使用构建的 chroot ,这个请指定上一步创建的 chroot
sbuild_chroot => 'xxxx_chroot',
}
];

# 本机架构
$host_arch = 'x86';

# 日志配置
$daemon_log_file = '/var/log/buildd.log';
$idle_sleep_time = 300;
$verbose = 16;
$admin_mail = 'root';
$log_queued_messages = 1;

# 相关命令路径
$apt_get = 'apt-get';
$mailprog = '/usr/sbin/sendmail';
$ssh = 'ssh';
$sudo = 'sudo';

# 上传队列
$upload_queues = [
{
dupload_local_queue_dir => "upload",
dupload_archive_name => "anonymous-ftp-master",
}
];

以上只是我的 buildd 配置,不一定是最优解。

  1. 配置 ssh
    可以看到,在上面我们是通过 ssh 连接到 wanna build 服务器的,所以我们需要给 buildd 配置一套 ssh key ,并把公钥添加到 wanna build 服务器中.
1
2
3
# 编译机
su - buildd
ssh-keygen
1
2
3
# wanna build 机
cd /var/lib/buildd/.ssh/
cat id_rsa.pub > authorized_keys
  1. 创建 log 文件
1
2
3
#编译机
touch /var/log/buildd.log
chown buildd:buildd /var/log/buildd.log
  1. 然后就可以愉快的运行 buildd 了

吗?

如果你跟着 wiki 走,这时候就是直接运行

1
/etc/init.d/buildd start

然后就会运行失败,为什么呢? 因为现在已经跑者一个 buildd 了。 debian 在安装 buildd 的时候就已经默认运行了,所以我们需要先手动 kill 掉正在运行的 buildd,然后在重新 start 运行。但是我更喜欢用 systemctl 来管理 buildd 的状态,所以 kill 之后我会通过 systemctl start buildd.service 来运行 buildd.

之后就能顺利运行 buildd 啦,现在这一套系统就完美的跑在你的服务器上了。如果有什么有的建议和方案请与我交流。

一些小问题

  1. buildd 接收任务后打包完成的 deb 包并不会上传到 wanna build 服务器中,以至于我需要手动拷贝。
  2. 批量修改状态不够优雅,需要在研究下 wanna build 命令,看看有没有批量修改的工具。

参考:

  1. SetupBuildServiceForWanna-build
  2. DebianWannaBuildInfrastructureOnOneServer