CFEngine is a fantastic tool for managing configuration files and packages
across heterogeneous environments. I figured I could use it to maintain a
basic set of installed packages across my Debian, OpenBSD and FreeBSD systems.
Except that the FreeBSD package_method promises in the cfengine standard
They use FreeBSD packages, and unless you have a box building your own sets of
FreeBSD packages…packages suck. They are built with all of the bells and
whistles, ergo they pull in a ton of shit you probably don’t need on your
So I wrote a package_method promise that instead uses portmaster to install
and remove packages. Here’s the code:
The only interesting thing about the body of the promise is that I’m using
package_file_repositories in a way that it was never intended to be used.
Since the port names needed to be provided to portmaster in a
/ format, I'm leveraging a cfengine trick to kind of fake
that. If you provide a package\_file\_repositories clause, cfengine will
prepend a variable called $(firstrepo) to the name of every package that it
adds to the package\_add\_command line.
Armed with this knowledge, we just add a package\_file\_repositories entry for
each port category directory, and the problem's been solved.