Building FreeBSD Media With Custom Packages
Building a FreeBSD release can be as simple as executing:
# cd /usr/src # make buildworld # cd release # make release # PKG_TREE=$pkg_dir PKG_DEST=$CHROOTDIR/R/cdrom/dvd1 PKG_DVD=Yes make package-split
The Use Case
I generate company specific FreeBSD distributions based on our internal requirements including loading specific packages. The FreeBSD DVD release from freebsd.org includes a packages/ directory created by the package-split.py script. I use the same script to accomplish the same task with custom packages.
We generate an ISO from the release and import it into Cobbler. We’ve setup Cobbler to allow us to provision operating systems non-interactively using PXE, DHCP, TFTP, and HTTP.
Prerequisites
- A directory containing at least the packages to include. One can download packages for 8.3-RELEASE via ftp at ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/.
- An INDEX file. The INDEX file will already exist if one downloads the packages from the above ftp server.
Configuring package-split.py
package-split.py is a Python script that “generates a master INDEX file for the CD images built by the FreeBSD release engineers. Each disc is given a list of desired packages. Dependencies of these packages are placed on either the same disc or an earlier disc. The resulting master INDEX file is then written out”.
In our use case, the files are not split into separate discs because we are packaging for a DVD as identified by the PKG_DVD environment variable.
View the package-split.py here. Because I am currently working with 8.3-RELEASE, I link directly to the that version of the script.
Our use case involves commenting lines 43 – 81 and copying lines 63 – 81. The copied lines are modified with names of packages installed in our base distribution. An example might look similar to:
if doing_dvd: pkgs.extend(['ftp/wget', 'devel/subversion', 'lang/perl5.12', 'lang/python', 'lang/ruby18', 'net/rsync'])
Caveats
- There are inconsistencies in the INDEX file where some package names and origins do not match. An example such as ruby18-iconv shows the package name (column 1) is ruby18-iconv-$version while the origin (column 2) is /usr/ports/converters/ruby-iconv. `make package-split` errored on this package citing “Unable to find package for converters/ruby18-iconv” (see image below). Changing origin from “ruby-iconv” to “ruby18-iconv” resolved this.
- use the origin field to identify the package in configuring the package-split.py script. For example, ruby18-iconv, would be specified as ‘converters/ruby19-iconv’ as opposed to ‘ruby/ruby18-iconv’ despite having multiple categories and existing multiple directories.
Executing `make package-split`
Once the release is built, create the packages directory and move it to the new release by executing the following. This would also be an appropriate time to make additional modifications to the image such as replacing the mfsroot.gz with a new custom mfsroot.
# PKG_TREE=/tmp/packages PKG_DEST=$CHROOTDIR/R/cdrom PKG_DVD=Yes make package-split # mv $CHROOTDIR/R/cdrom/disc1/packages $CHROOTDIR/R/cdrom/dvd1
Generate the ISO
The release is now ready to be made into an ISO that we use to import the distribution into our provisioning platform, Cobbler.
# mkisofs -R -no-emul-boot -b boot/cdboot -o /tmp/iso/FreeBSD-8.3-RELEASE-p4-amd64-CUSTOM.iso $CHROOTDIR/R/cdrom/dvd1
