Build Your Own Pkg-Repository With Poudriere

Updated on November 21, 2023
Build Your Own Pkg-Repository With Poudriere header image

Since version 9.2, FreeBSD has introduced a new tool to replace the old pkg_*-commands - pkg, also known as pkgng. It's very similar to Debian's apt or Fedora's yum but has some very cool features. One of those is the possibility to easily use your own, private repository of packages.

Why would you want to do that? The official pkg-repositories are built out of FreeBSD's ports tree with a very limited set of options. For example, the official package for PHP lacks support for MySQL. Another reason might be that you want to have two repositories, one with X11 enabled - for your desktop - and one with X11 disabled - for your servers. There are a lot of options and possibilities, and this tutorial will show you how to build your own repository with Poudriere, a tool for mass-building packages.

I assume that you have a fresh VPS with FreeBSD 10 x64 installed. First of all, you need the ports-tree on your system:

cd /usr
portsnap fetch extract

Then, you need to install Poudriere from source (The default options are fine!):

cd /usr/ports/ports-mgmt/poudriere
make install clean

Next, create a basic configuration file:

cp /usr/local/etc/poudriere.conf.sample /usr/local/etc/poudriere.conf

... and edit it according to your needs. The following is a good start:

FREEBSD_HOST=http://ftp.freebsd.org
RESOLV_CONF=/etc/resolv.conf
BASEFS=/usr/local/poudriere
POUDRIERE_DATA=$/data
USE_PORTLINT=no
USE_TMPFS=yes
DISTFILES_CACHE=/usr/ports/distfiles
CHECK_CHANGED_DEPS=yes
# Edit this according to your VPS' CPU.
PARALLEL_JOBS=1
NOLINUX=yes

Instead of using the regular portstree of your system, Poudriere uses its own copy. You must obtain it with the following command:

poudriere ports -c

Now, create a jail for the builder to run within:

poudriere jail -c -j testjail -v 10.0-RELEASE -a amd64

Before you can start to build packages, you will actually have to tell Poudriere what it should build. Open up your favorite text editor and add some packages:

www/firefox
im/pidgin
sysutils/tmux
editors/vim

... and save the file under /usr/local/etc/buildlist. If you don't want the default options, then you can configure the options for each package in that file. This is done by issuing the following command:

poudriere options -cf /usr/local/etc/buildlist

Otherwise, you can start building:

poudriere bulk -f /usr/local/etc/buildlist -j testjail

The amount of time this operation takes will vary based on the CPU speed of your VPS. After the process has finished, your fresh packages can be found, sorted by build-jail, in /usr/local/poudriere/data/packages/.

Now, you need a webserver to actually serve those packages to your other machines. I chose Nginx since it's efficient and lightweight. Install it via ports (The default options are fine!):

cd /usr/ports/www/nginx
make install clean

After the installation process is done, you need to configure Nginx to serve the packages directory. To do that, edit /usr/local/etc/nginx/nginx.conf with your favorite text editor:

server {
    listen       80;
    server_name  localhost;
    root /usr/local/poudriere/data/packages/testjail-default;
    location / {
            autoindex on;
    }
}

Finally, make sure the webserver starts at boot:

echo "nginx_enable=YES" >> /etc/rc.conf

... and start the server:

/usr/local/etc/rc.d/nginx start

The possibilities with Poudriere are huge. You can learn more about Poudriere by reading the manpage entry. If you plan on using a setup like this in a production environment, it would be in your best interest to also read about package signing, and to consider securing the connection to your webserver with TLS. But for now, you are ready to rock!

To activate the repository on the client, run these commands on the client machine:

mkdir -p /usr/local/etc/repos
vi /usr/local/etc/repos/myrepo.conf

Populate myrepo.conf with the following content. You can use any name for this file, providing that it has the .conf suffix.

poudriere: {
  url: "http://yoururl"
  mirror_type: "http",
  enabled: yes
}

Next, update the package database with the command:

pkg update

You can now install packages out of your new repository!