Table of Contents

Poudriere image

Unofficial Poudriere technical resources

Why using poudriere in place of nanobsd ?

BSDRP use a heavy customized nanobsd script that include package generation. This code need to be adapted each time the port build infrastructure change.

Why not using the new shinny “poudriere image” feature that will avoid to re-invent the wheel ?

Externals links about Poudriere

Here are a list of docs and tutorials about Poudriere:

Understanding Poudriere image

What is Poudriere ?

It's a shell script used for build package in a clean (jail) environment. But once you get a clean jail in one side, and a list of fresh generated package in other side, why not mix them together in a “nanobsd like” firmware ?

This is the “poudriere image” feature includes in poudriere-git-3.3.99.20220713 that is presented here.

Images generated by Poudriere

Poudriere can generate multiple “image” types (default is iso+zmfs):

The 6 minimum steps to build a poudriere firmware image

Using poudriere from a ZFS is not mandatory but strongly advised.

  1. Install poudriere and configure it:
    sudo pkg install poudriere-devel
    echo "ZPOOL="`zpool list -H | cut -f1` | sudo tee -a /usr/local/etc/poudriere.conf
  2. Create a poudriere jail WITH a GENERIC kernel (by default kernel is not build & installed), here named “router”:
    sudo poudriere jail -c -j router -v 14.2-RELEASE -K GENERIC
  3. Create a port-tree using “poudriere ports”:
    sudo poudriere ports -c -p router_ports
  4. Generate list of ports to be build & added into the firmware image:
    cat > ~/router-pkglist <<EOF
    sysutils/tmux
    net/frr10
    net/bird2
    net/mpd5
    EOF
  5. Build the ports (ie: generate binary packages) from the corresponding jail using “poudriere bulk”:
    sudo poudriere bulk -j router -p router_ports -f ~/router-pkglist
  6. Generate your disk image (4Gb total, because 2 systems partitions of 2Gb) using “poudriere image”:
    sudo poudriere image -t firmware -j router -s 4g -p router_ports -h router -n router -f ~/router-pkglist
    (...)
    [00:00:15] Creating ESP image
    [00:00:15] ESP Image created
    [00:00:21] Image available at: /usr/local/poudriere/data/images/router.img

Comparing poudriere firmware image and nanobsd image

Final firmware file size

Start by checking poudriere firmware file size:

# ls -alh /usr/local/poudriere/data/images/router.img
-rw-r--r--  1 root  wheel   3.8G Jul 22 19:24 /usr/local/poudriere/data/images/router.img

We've obtained a 3.8GiB disk image file… which fit into a marketed-size 4GB flash disk.

Partition scheme

The resulting images partition layout will have the same behavior than a nanobsd:

# mdconfig -a -t vnode -f /usr/local/poudriere/data/images/router.img
md0
# gpart show -l md0
=>      4  7995515  md0  GPT  (3.8G)
        4    20480    1  (null)  (10M)
    20484      123    2  (null)  (62K)
    20607  3921920    3  router1  (1.9G)
  3942527  3921920    4  router2  (1.9G)
  7864447    65536    5  cfg  (32M)
  7929983    65536    6  data  (32M)
  
# mount /dev/gpt/router1 /mnt/
# df -h /mnt
Filesystem          Size    Used   Avail Capacity  Mounted on
/dev/gpt/router1    1.8G    1.5G    103M    94%    /mnt

/etc ram disk

Poudriere image is correctly compliant to a nanobsd /etc & /var ramdisk:

root@router:~ # mount
/dev/gpt/router1 on / (ufs, local, read-only)
devfs on /dev (devfs, local, multilabel)
/dev/md0 on /etc (ufs, local)
/dev/md1 on /var (ufs, local)

Comparing to a standard nanobsd:

[root@nanobsd]~# mount
/dev/ufs/NANOs1a on / (ufs, local, read-only)
devfs on /dev (devfs, local)
/dev/md0 on /etc (ufs, local)
/dev/md1 on /var (ufs, local)

fstab

poudriere's fstab is using gpt labels, while nanobsd one using ufs labels:

root@router:~ # cat /etc/fstab
/dev/gpt/router1 / ufs ro 1 1
/dev/gpt/cfg  /cfg  ufs rw,noatime,noauto        2 2
/dev/gpt/data /data ufs rw,noatime,noauto,failok 2 2
[root@nanobsd]~# cat /etc/fstab
/dev/ufs/NANOs2a / ufs ro 1 1
/dev/ufs/NANOs3 /cfg ufs rw,noatime,noauto 2 2
/dev/ufs/NANOs4 /data ufs rw,noauto,failok 2 2

Migrating from NanoBSD to poudriere image

Features matrix comparison

nanobsd configuration file is a shell script,and BSDRP use a highly nanobsd customized configuration file generated by a wrapper (make.sh).

The challenge of migrating the customization done on nanobsd to poudriere image can be resumed here:

BSDRP customized nanobsd usage poudriere image Purpose
Support differents src.conf: One for buildworld and another for installword src.conf used for buildworld and installworld, image-JAILNAME[-SET]-src.conf added for installworld/delete-old. Allow to use the -X exclude_list too Using WITHOUT_INCLUDES or WITHOUT_DEBUG just for installworld but not for buildworld
Downloading a specific source revision of a stable/releng/head use svn url@rev (or custom source tree with '-b -m src=/usr/src') or using branches Allow reproducing the same build on different systems
Build a specific kernel file Just had to install custom kernel int the custom source tree Customized kernel
Build only list of kernel modules Declaring MODULES_OVERRIDE in -src.conf Customized module list
Advanced scripting for building non-ports softwares Solution should be to create a port Need to build some of /usr/src/tools
Advanced tuning of final image -A post-script and -B pre-script Generating a mtree (for host-IDS), creating specific users
Building ports using own (outdated) embedded script NATIVE role of poudriere Adding ports to image
System upgrade by changing MBR active mode on system partition System upgrade by setting “bootonce” attribute on system partition (and need to be removed from older?) Upgrading system partition (new/old)

poudriere-image patches

List of mandatory patches for poudriere in Pull-request review:

Merged patches:

Customized poudriere image for BSDRP

How to configure poudriere to generate a BSDRP firmware image.

Set of configuration files

To be able to reproduce the highly customized BSDRP firmware image, we need multiples configuration files.

Poudriere will requiere jail and port so prepending j and p to avoid confusion:

We need to start creating a set of configuration files, named prefixed with the name BSDRP-:

Then need other configuration files:

poudriere.d/BSDRPj-src.conf

The previous section of the NanoBSD configuration files found in variables CONF_BUILD and CONF_WORLD in file BSDRP/BSDRP.nano should be copied in this file.

Notice this jail will be used to build the port, so compiler should be kept here.

The BSDRPj-src.conf is on github.

poudriere.d/image-BSDRPj-src.conf

Allow to ADD WITHOUT_ knob that will be removed during installworld into the final image.

This is where we remove compiler and other no-more used part.

The image-BSDRPj-src.conf is on github.

poudriere.d/BSDRPj-make.conf

This file contains build parameters for the ports.

The BSDRPj-make.conf is on github.

BSDRP-pkglist

This file includes the list of package to be builded and added to the final image.

The BSDRP-pkglist is on github.

excluded.files

List of files/directory that WITHOUT_ wasn't able to prevent to be on the final image.

The excluded.files is on github.

Packages excluded files

When customizing ports options, some could not be disabled but we could configure pkg to not install some files from packages while extracting them.

The customized pkg.conf is on github.

Building the jail

The simplest solution is to re-use already existing BSDRP patched source tree: specific kernel configuration files can be installed into these source tree and use after.

Start by only patching BSDRP sources (sources and ports) using the BSDRP makefile:

make patch-sources

There are now 2 sources ready patched:

poudriere jail -e poudriere.etc -c -j BSDRPj -b -m src=obj/FreeBSD -K amd64

Command line details:

Creating port tree

Now we need to create a port-tree using the patched existing port tree:

poudriere ports -e poudriere.etc -c -p BSDRPp -m null -M obj/ports

Build packages

poudriere native role, we just give the jail name and port-tree name to use then the list of packages.

poudriere bulk -e poudriere.etc -j BSDRPj -p BSDRPp -f /usr/local/etc/poudriere.d/BSDRP-pkglist.common

Generating firmware image

Here I'm instructing to build a 2GB image using the previous sets, jail, port-tree.

poudriere image -t firmware -s 2g \
    -j BSDRPj -p BSDRPp -n BSDRP -h router.bsdrp.net \
    -c BSDRP/Files/ \
    -f poudriere.etc/poudriere.d/BSDRP-pkglist \
    -X poudriere.etc/poudriere.d/excluded.files \
    -A poudriere.etc/poudriere.d/post-script.sh

Command line explanation: