You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.2 KiB

title author lang
How did she do it?! Mina Galić en

So you wanna build your own PkgBase packages and serve them from your own repo? Here's how I did it.

Prerequisites

There are two bottlenecks with providing this service:

  • Storage
  • CPU

The more powerful the machine, the faster your build times will be. And the bigger your storage, the more package sets and history you'll be able to provide.

This is what the machine I have been provided for this project looks like:

~> % sysctl hw | head
hw.machine: amd64
hw.model: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
hw.ncpu: 6
hw.byteorder: 1234
hw.physmem: 8547110912
hw.usermem: 5163855872
hw.pagesize: 4096
hw.floatingpoint: 1
hw.machine_arch: amd64
hw.realmem: 8589934592

It also comes with about 1T of storage:

~> % zfs list zroot
NAME    USED  AVAIL     REFER  MOUNTPOINT
zroot   381G   603G      192K  /zroot

Setting up Poudriere

Setting up poudriere, we'll need poudriere-devel, as it comes with a bunch of fixes for PkgBase.

For building package sets for other platforms than the host, you'll also need to install qemu-user-static, and enable the service.

The essence of my poudriere.conf looks like this:

NO_ZFS=yes
FREEBSD_HOST=https://download.FreeBSD.org
GIT_BASEURL="git.freebsd.org/src.git"
RESOLV_CONF=/etc/resolv.conf
BASEFS=/poudriere
USE_TMPFS=yes
PKG_REPO_SIGNING_KEY=/usr/share/keys/pkg/repo.key
PARALLEL_JOBS=6
TIMESTAMP_LOGS=yes
URL_BASE=https://alpha.pkgbase.live/

Note: The PARALLEL_JOBS setting is tuned down from the default hw.ncpu, because we're sharing this server and we're also running a webserver serving the packages.

Note: We are chosing to not use ZFS (NO_ZFS=yes). Even tho this makes creation and destruction of poudriere jails a little slower, it will make migrating this setup from jail to bhyve to hardware and back a lot easier.

Signing Packages

poudriere allows us to sign packages, by supplying a key via PKG_REPO_SIGNING_KEY. That key only needs to live on the build host, not in the "jails" we're building. That is because when building PkgBase, we're not actually building in a jail.

Preparing the build

We can set some important options in src.conf:

PKG_FORMAT="tzst"
WITHOUT_CLEAN="YES"
WITH_REPRODUCIBLE_BUILD="YES"

and src-env.conf:

WITH_META_MODE="YES"

if you want to take advantage of META_MODE, you'll also have to kldload(8) filemon(4), and persist it via rc.conf(5):

kld_list="filemon"

Building sets

The way I create PkgBase sets with poudriere is generally like this:

~> % poudriere jail -c -j 14-current-aarch64 \
       -x -a arm64.aarch64 \
       -B -b -m git+https \
       -v main \
       -K "GENERIC GENERIC-MMCCAM GENERIC-NODEBUG GENERIC-MMCCAM-NODEBUG"

Let's break this down:

  • We instruct poudriere to -create a -jail called 14-current-aarch64
  • for the arm64.aarch64 -architecture
  • and to build native-xtools cross compile tools
  • build a Pkg-Base set
  • -build the OS
  • fetch the source using the git -method via git+https
  • build the -version (branch) main
  • build using -KERNCONF "GENERIC GENERIC-MMCCAM GENERIC-NODEBUG GENERIC-MMCCAM-NODEBUG"

Updating sets

I use a fish script to update my package sets:

#!/usr/bin/env fish

set -l basedir  (readlink -f (dirname (status filename)))

for j in (poudriere jail -qnl | awk "!/^iso-/ && /$argv/")
    echo "============================================================="
    echo "  Preparing to update $j..."
    echo "============================================================="

    set -l powder (string split ' ' (poudriere jail -ql | grep "^$j "))

    set -l src_path "$powder[-1]/usr/src"
    git -C $src_path pull --ff-only

    set -l cur_hash (git -C $src_path show-ref --abbrev --heads --hash)
    set -l rec_hash $powder[4]
    set -l arch (uname -m)
    set -l jarch $powder[5]
    set -l xarch (test "$arch" = "$jarch"; or echo "-x")

    if test "$cur_hash" = "$rec_hash"
        echo "============================================================="
        echo "  Skipping update of $j: already up-to-date"
        echo "============================================================="
        continue
    end

    set -l poudriere_update "time poudriere jail -u $xarch -j $j"
    if not eval $poudriere_update
        echo "============================================================="
        echo "  Failed to update $j :("
        echo "============================================================="
        break
    end

    echo "============================================================="
    echo "  Successfully updated $j !!"
    echo "============================================================="
end

What this does is to compare the git hash after pulling with what poudriere has stored. We skip if there's no need to update.

Similarly, we compare the architecture and if the jail's doesn't match that of the host, we add -x to the -update.


That's all folks.

If you have questions about replicating my setup, I'll be happy to edit this Howto to make it more complete.