Hi folks, long time no see. Today we are going to cover how to build pkg(8) (pkgng) packages away from the FreeBSD ports tree. This is useful for external/private repositories (mostly bigger ones or generally fast-moving) or non-conventional ports like database content or even system updates. pkg(8) itself provides the essential pkg-create(8) tool, as well as pkg-query(8), which we will use to generate embedded dependencies.
Custom packages can be used in a wide variety of tasks, meaning you don’t have to ship conventional ports. One of my personal favourites is the automation of update tasks and system administration. In theory, a package upgrade could reconfigure your systems according to the latest security policies, so all you have to do on the remote machine is to create a cron job for pkg-upgrade(8) or trigger the installation manually using a single shell command.
First, a couple of files will have to be set up in this imaginary package:
#!/bin/sh STAGEDIR=/tmp/stage rm -rf ${STAGEDIR} mkdir -p ${STAGEDIR} cat >> ${STAGEDIR}/+PRE_DEINSTALL <<EOF # careful here, this may clobber your system echo "Resetting root shell" pw usermod -n root -s /bin/csh EOF cat >> ${STAGEDIR}/+POST_INSTALL <<EOF # careful here, this may clobber your system echo "Registering root shell" pw usermod -n root -s /bin/sh EOF
There is +PRE_DEINSTALL, +POST_DEINSTALL, +PRE_INSTALL as well as +POST_INSTALL. Generally, you want to run post-install and pre-deinstall tasks as it makes sure your files are in place when you do the system manipulation, but that’s just a rule of thumb. Next, the master file +MANIFEST is written:
cat >> ${STAGEDIR}/+MANIFEST <<EOF name: mypackage version: "1.0_5" origin: sysutils/mypackage comment: "automates stuff" desc: "automates tasks which can also be undone later" maintainer: john@doe.it www: https://doe.it prefix: / EOF
This will get you going, but what if the package has dependencies that should be enforced? Maybe the package is simply a meta-package that holds all essential packages so you can design fast customised system setups? If the packages are installed on the build system, then pkg-query(8) may be used to generate these dependencies:
echo "deps: {" >> ${STAGEDIR}/+MANIFEST pkg query " %n: { version: \"%v\", origin: %o }" portlint >> ${STAGEDIR}/+MANIFEST pkg query " %n: { version: \"%v\", origin: %o }" poudriere >> ${STAGEDIR}/+MANIFEST echo "}" >> ${STAGEDIR}/+MANIFEST
The benefit of pkg-query(8) is that it will format and output the correct information so one doesn’t have to triple-check for the correct info (trust me, I’ve been there). Now, shipping files inside the package requires another file, namely plist:
mkdir -p ${STAGEDIR}/usr/local/etc echo "# hello world" > ${STAGEDIR}/usr/local/etc/my.conf echo "/usr/local/etc/my.conf" > ${STAGEDIR}/plist
The last step uses pkg-create(8) to build a package:
pkg create -m ${STAGEDIR}/ -r ${STAGEDIR}/ -p ${STAGEDIR}/plist -o .
From here on out, you’ll be able to use the package archive file with pkg-add(8). In the next couple of posts, we’ll look deeper into pkg(8), e.g. how to create a custom package mirror, how to properly shield your build system using chroot(8), etc.
Hi Franco,
thanks for your blog posts including deep dive into pkg(ng). I am looking forward to your upcoming posts.
Personally I’m using poudriere for building my own package repo: https://github.com/freebsd/poudriere
Good blogposts for starting with poudriere: http://www.bsdnow.tv/tutorials/poudriere and http://blather.michaelwlucas.com/archives/1941
Oh, my download of opnsense finished.. ;)
Hi Oliver,
thanks for looking into this and OPNsense. :) The script(s) come from the OPNsense tools.git. I was going to write more tutorials on the stuff that is there and how to develop in the environment.
And, yeah, poudriere is a nice solution. I was looking at it once and it did all the things one could imagine, but in a way that is too closed-down in itself. It’s hard to explain. It would e.g. delete a custom git tree off of the build machine because it was “done building”. When you lose your ports tree and you don’t have access to the remote it’s kinda tricky….
I want to look at it again soon and maybe see if it can be tweaked/configured in that regard. :)