This is a HOWTO on how to build your own ports-mgmt/pkg packages in a jail(8) using ports-mgmt/poudriere.
Few notes about notation:
What is ports-mgmt/poudriere? The port description reads as follows:
This description is now quite out of date since the official FreeBSD binary packages are now built with it. Poudriere is a package building system intended for anyone who wants to build their own binary pkg packages for FreeBSD. Its design is as follows:
Why is poudriere needed in the first place? The ports infrastructure suffers from numerous design faults that are not easy to overcome without a package building tool like poudriere. These faults include:
What poudriere is not:
Requirements:
Before proceeding take note:
This step is only needed on a freshly installed system that has no ports-mgmt/pkg installed yet.
On any supported version of FreeBSD there is bootstrap utility for pkg installed as /usr/sbin/pkg that can be used to install ports-mgmt/pkg. Simply run this on a freshly installed system and you'll be prompted if you want to install pkg(8):
2. Install ports-mgmt/poudriere.
Install poudriere from the official binary packages:
If you need any of the so called bleeding edge features of poudriere, install the ports-mgmt/poudriere-devel port instead.
3. Configure ports-mgmt/poudriere.
First copy the sample configuration file ${LOCALBASE}/etc/poudriere.conf.sample to ${LOCALBASE}/etc/poudriere.conf and make sure the copy is writable:
Edit the following entries in ${LOCALBASE}/etc/poudriere.conf (some already have the desired values, leave them untouched):
Create the /var/cache/distfiles directory, you can put this somewhere else as well but this path is the most compliant one with hier(7):
The comments in the above are verbatim from the sample configuration file, I have chosen to disable Linux support because I don't build anything that requires the Linux emulation layer. There are a number of different configuration options that I'm leaving uncovered here because the defaults are fine for most cases, refer to the configuration file and the documentation for more information.
If you want to disable the use of ZFS leave the ZPOOL and ZROOTFS lines commented out and uncomment the NO_ZFS=yes line. None of the steps below need to be modified if ZFS is not used, poudriere will use alternate methods for jail creation/cloning and handling of ports trees and package repositories that are somewhat slower than with ZFS but the end results are the same.
4. Set up the ports tree for poudriere.
Setting up and managing of ports(7) trees is done with the poudriere-ports(8) command.
This will create a new ports tree located at ${BASEFS}/ports/default using the SVN method of checking out and updating of the ports tree:
After this running
It's now possible to use poudriere-ports(8) to update the ports tree:
It's also possible to register an existing ports tree into poudriere, however this will leave the updating of this ports tree for you to handle:
5. Set up the jail for building packages.
The command to set up and manage jails in poudriere is poudriere-jail(8). The simplest way to create a jail is to use the http method (note: the manual page will claim that http is the default but the default is in fact ftp) to fetch a FreeBSD distribution file set to be extracted in the new build jail. The http method will use the FREEBSD_HOST setting from the configuration file as the mirror site for downloading the necessary files. HTTPS is supported.
This is how an amd64 11.2-RELEASE jail would be created on an amd64 system, substitute amd64 with i386 if creating an i386 jail on an i386 build host:
The jail identifier for the -j option is for you to decide, I used "releng112amd64" to signify that it's 11.2-RELEASE but can be updated with release engineering updates and security fixes. In other words the jail follows the official 11.2-RELEASE branch with updates.
After creation the jail should be in the
Creating an i386 jail on an amd64 build host is done as follows:
If you're tracking a stable or current branch of FreeBSD the easiest way to keep your poudriere jails up to date is to use the -m src=/usr/src method for creating and updating the jails. This is how a stable/11 amd64 jail would be created, it is assumed that
It is also possible to use the -m svn method that fetches the sources for the requested version of FreeBSD, builds a new world using those sources and installs the results of the build as the new jail.
Jails that were installed using the -m ftp or -m http method are updated using freebsd-update(8). Jails that were installed with the -m src=/usr/src method are updated using the sources and objects in /usr/src and /usr/obj of the build host. Jails that were installed using the -m svn method that involves building a world, a new world build is performed with the updated sources.
Updating of a jail regardless of the method of their creation is done with:
6. Create a list of ports to be built into packages.
Create a new file, for example /usr/local/etc/ports.txt (can be also located at your home directory just as well) and put all the ports you want to build in there.
Example:
There is no need to put the dependencies of the built ports in the list, they are built automatically.
Note that you should include the ports-mgmt/pkg port in the list because there are no ports that depend on it. If you don't include it in your list of ports to be built it won't be updated when there's a new version of it.
IMPORTANT: In order to be sure that your repository stays in a consistent state, always try to run poudriere(8) with this full list of ports to build. If you build only a port here, port there, only parts of the repository are updated and many ports that should have been recompiled are not recompiled and that can lead to shared library mismatches.
Few notes about notation:
- First few mentions of a ported program will be a "port link", like net/mtr. I will not repeat the link too many times however.
- I will use a link to a manual page when introducing a new command, like mtr(8). Unfortunately the official manual page are lagging badly behind what's actually available on a recent FreeBSD and many of the links below don't work. You can however take the name of the command from the link and check the manual page on your own system that will have up to date manual pages.
- I will use a couple of variables to avoid repeating paths like /usr/local/poudriere. I will use ${LOCALBASE} for the path of the default location for installed ports, /usr/local. I will use ${BASEFS} for the root folder where poudriere stores ports trees, jails, packages and few other things, default ${LOCALBASE}/poudriere (but see below for the BASEFS setting in the configuration file). I will use ${jailname} in few places where file names vary depending on the name of jail used.
What is ports-mgmt/poudriere? The port description reads as follows:
Code:
poudriere is a tool primarily designed to test package production on
FreeBSD. However, most people will find it useful to bulk build ports
for FreeBSD.
WWW: https://github.com/freebsd/poudriere/wiki
This description is now quite out of date since the official FreeBSD binary packages are now built with it. Poudriere is a package building system intended for anyone who wants to build their own binary pkg packages for FreeBSD. Its design is as follows:
- Mostly sh(1) scripts for portability.
- Uses jail(8)s for creating clean build environments for ports building.
- Makes heavy use of nullfs(5) to avoid unnecessary copying.
- Makes heavy use of ZFS features like snapshots and cloning if ZFS is used.
- Has built-in utilities for setting up and updating ports(7) trees and jail(8)s.
- Customizable trough a configuration file (${LOCALBASE}/etc/poudriere.conf, ${LOCALBSE} defaults to /usr/local) and a dedicated settings directory (${LOCALBASE}/etc/poudriere.d).
- Can be run as a daemon that serves build requests.
Why is poudriere needed in the first place? The ports infrastructure suffers from numerous design faults that are not easy to overcome without a package building tool like poudriere. These faults include:
- Building of ports as outlined in ports(7) is performed on the live system. Many build failures stem from this when an already installed port or leftover files from an old version causes conflicts with the to be built new version of the port. Poudriere avoids this problem by starting every build from a clean state as if the ports were installed for the first time on the system.
- Building ports on the live system pulls in a large number of build time dependencies that are not required to be installed after the builds have finished. These build time dependencies can cause configuration issues and trigger build failures when port dependencies and options change. Again, poudriere avoids this by starting every build from a clean state.
- Building ports on the live system may cause service interruptions while the ports are being built and the situation may not be corrected until all of the ports have been rebuilt. Poudriere uses jails that are separated from the live system for building the packages and therefor can not disrupt the running services on the host.
- There might not always be an easy update path when an important port gets updated because of complicated dependencies between the updated port and its dependents. Usually in such cases there are instructions in the /usr/ports/UPDATING file to remedy the situation but to apply the instructions manual intervention is needed. Poudriere nullifies the need for manual intervention and the need to follow the instructions in first place because the repository gets rebuilt starting from the lowest level of dependencies and all dependents of the changed port/ports that need rebuilding are properly rebuilt resulting in a consistent repository that will result in a consistent system when the updated packages get installed.
- When building individual ports one by one with
# make install
or for example ports-mgmt/portmaster there are no opportunities to make use of the conflict resolution feature of the new pkg system. It is only available when installing sets of packages from a remote repository with pkg-install(8) or pkg-upgrade(8). - Building for a different target system that uses different defaults and options can be next to impossible because of conflicts between already installed ports and the build time dependencies the differing options would pull in to be installed at the same time
- Build once, distribute to many client hosts is cumbersome to implement with only the basic ports system.
What poudriere is not:
- It's not a replacement for any of the existing tools in the FreeBSD base or the ports(7) system. It doesn't modify the standard ports infrastructure in any way to achieve what it does.
- It's not in competition with the few other ports building tools like ports-mgmt/portmaster or ports-mgmt/portupgrade because its goals are different. The two mentioned tools are nice frontends to the ports system but are limited to building the ports on the live system just as the basic ports system is.
- It can't be used as a generic jail(8) management system like sysutils/ezjail. The jails created by poudriere are only suitable for building ports into binary packages.
Requirements:
- Any supported version of FreeBSD installed on the build host system, amd64 or i386. Amd64 very much recommended over i386. The so called stable versions stable/10 and stable/11 are supported. The head branch a.k.a 12-CURRENT should also work also but see here first. Operating system versions installed in the jails used to build packages should not be more recent than the operating system installed on the build host system, jails that have older operating system versions work as long as the kernel on the build host has the proper compatibility options set.
- 64- and 32-bit versions can be mixed but only in a way where the build host system is a 64-bit version and the jail has a 32-bit version of FreeBSD. The kernel on the build host must include the 32-bit compatibility layer for this to work.
- An up to date version of ports-mgmt/poudriere, latest version is 3.2.7 at the time of the last edit of this HOWTO. The development version ports-mgmt/poudriere-devel can be also used if bleeding edge features are needed.
- An up to date version of ports-mgmt/pkg, latest version is 1.10.5 at the time of the last edit.
- Enough memory to build the largest packages. This depends on what you're building, things like www/firefox may take lots of memory. 4GBs or more to be safe (amd64 version of FreeBSD needed if you intend to utilize more that 4GBs of memory).
- Enough free disk space. As above, depends on what you're building. 10GBs or more to be safe.
- Support for the ZFS filesystem on the build host. ZFS makes jail cloning very fast and efficient and in general should be used if possible. I will note below the settings that need to be changed in case you don't want to use ZFS for some reason.
- The kernel on the build host must have support for jail(8) and nullfs(5).
Before proceeding take note:
- All of this assumes that you have a working internet connection right from the start.
- Commands listed as
# command
should be run with root privileges. Other commands work without the root privileges.
This step is only needed on a freshly installed system that has no ports-mgmt/pkg installed yet.
On any supported version of FreeBSD there is bootstrap utility for pkg installed as /usr/sbin/pkg that can be used to install ports-mgmt/pkg. Simply run this on a freshly installed system and you'll be prompted if you want to install pkg(8):
# pkg
2. Install ports-mgmt/poudriere.
Install poudriere from the official binary packages:
# pkg install -y poudriere
If you need any of the so called bleeding edge features of poudriere, install the ports-mgmt/poudriere-devel port instead.
3. Configure ports-mgmt/poudriere.
First copy the sample configuration file ${LOCALBASE}/etc/poudriere.conf.sample to ${LOCALBASE}/etc/poudriere.conf and make sure the copy is writable:
# cp /usr/local/etc/poudriere.conf.sample /usr/local/etc/poudriere.conf
# chmod 640 /usr/local/etc/poudriere.conf
Edit the following entries in ${LOCALBASE}/etc/poudriere.conf (some already have the desired values, leave them untouched):
Code:
#### 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
# 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
# The directory where poudriere will store jails and ports
BASEFS=/usr/local/poudriere
# 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=/var/cache/distfiles
# If set the ports tree or source tree marked to use svn will use the defined
# mirror (default: svn.FreeBSD.org)
# The SSL fingerprints are published here:
# https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/svn.html#svn-mirrors
SVN_HOST=svn.FreeBSD.org
# Disable linux support
NOLINUX=yes
Create the /var/cache/distfiles directory, you can put this somewhere else as well but this path is the most compliant one with hier(7):
# mkdir /var/cache/distiles
The comments in the above are verbatim from the sample configuration file, I have chosen to disable Linux support because I don't build anything that requires the Linux emulation layer. There are a number of different configuration options that I'm leaving uncovered here because the defaults are fine for most cases, refer to the configuration file and the documentation for more information.
If you want to disable the use of ZFS leave the ZPOOL and ZROOTFS lines commented out and uncomment the NO_ZFS=yes line. None of the steps below need to be modified if ZFS is not used, poudriere will use alternate methods for jail creation/cloning and handling of ports trees and package repositories that are somewhat slower than with ZFS but the end results are the same.
4. Set up the ports tree for poudriere.
Setting up and managing of ports(7) trees is done with the poudriere-ports(8) command.
This will create a new ports tree located at ${BASEFS}/ports/default using the SVN method of checking out and updating of the ports tree:
# poudriere ports -c -m svn
After this running
poudriere ports -l
should output:
Code:
PORTSTREE METHOD TIMESTAMP PATH
default svn 2018-08-16 14:29:52 /usr/local/poudriere/ports/default
It's now possible to use poudriere-ports(8) to update the ports tree:
# poudriere ports -u
It's also possible to register an existing ports tree into poudriere, however this will leave the updating of this ports tree for you to handle:
# poudriere ports -c -f none -m null -M /usr/ports -p test
5. Set up the jail for building packages.
The command to set up and manage jails in poudriere is poudriere-jail(8). The simplest way to create a jail is to use the http method (note: the manual page will claim that http is the default but the default is in fact ftp) to fetch a FreeBSD distribution file set to be extracted in the new build jail. The http method will use the FREEBSD_HOST setting from the configuration file as the mirror site for downloading the necessary files. HTTPS is supported.
This is how an amd64 11.2-RELEASE jail would be created on an amd64 system, substitute amd64 with i386 if creating an i386 jail on an i386 build host:
# poudriere jail -c -m http -v 11.2-RELEASE -j releng112amd64
The jail identifier for the -j option is for you to decide, I used "releng112amd64" to signify that it's 11.2-RELEASE but can be updated with release engineering updates and security fixes. In other words the jail follows the official 11.2-RELEASE branch with updates.
After creation the jail should be in the
poudriere jail -l
listing:
Code:
JAILNAME VERSION ARCH METHOD TIMESTAMP PATH
releng112amd64 11.2-RELEASE-p1 amd64 http 2018-08-16 18:21:38 /usr/local/poudriere/jails/releng112amd64
Creating an i386 jail on an amd64 build host is done as follows:
# poudriere jail -c -m http -a i386 -v 11.2-RELEASE -j releng112i386
If you're tracking a stable or current branch of FreeBSD the easiest way to keep your poudriere jails up to date is to use the -m src=/usr/src method for creating and updating the jails. This is how a stable/11 amd64 jail would be created, it is assumed that
make buildworld buildkernel
has been done in /usr/src and the build host has been updated to use the new version of the OS with make installkernel installworld
followed by a reboot.# poudriere jail -c -m src=/usr/src -v stable/11 -j stable11amd64
It is also possible to use the -m svn method that fetches the sources for the requested version of FreeBSD, builds a new world using those sources and installs the results of the build as the new jail.
Jails that were installed using the -m ftp or -m http method are updated using freebsd-update(8). Jails that were installed with the -m src=/usr/src method are updated using the sources and objects in /usr/src and /usr/obj of the build host. Jails that were installed using the -m svn method that involves building a world, a new world build is performed with the updated sources.
Updating of a jail regardless of the method of their creation is done with:
# poudriere jail -u -j releng112amd64
6. Create a list of ports to be built into packages.
Create a new file, for example /usr/local/etc/ports.txt (can be also located at your home directory just as well) and put all the ports you want to build in there.
Example:
Code:
ports-mgmt/pkg
devel/git
devel/subversion
editors/vim
www/apache22
There is no need to put the dependencies of the built ports in the list, they are built automatically.
Note that you should include the ports-mgmt/pkg port in the list because there are no ports that depend on it. If you don't include it in your list of ports to be built it won't be updated when there's a new version of it.
IMPORTANT: In order to be sure that your repository stays in a consistent state, always try to run poudriere(8) with this full list of ports to build. If you build only a port here, port there, only parts of the repository are updated and many ports that should have been recompiled are not recompiled and that can lead to shared library mismatches.
Last edited: