Package Update Workflow

A safe workflow for updating a FreeBSD system from any given state to using freebsd-update, PKGNG and Poudriere.

If you're suddenly handed a foreign and old system, you run into multiple problems:

The current FreeBSD toolsets are not available yet, or might be outdated and not working. Installed software will have changed considerably and you might find it impossible to do any 'straight' update to a recent version because of deadlocks.

"I can't update pkg because it needs a newer xz version which I could get around by using pkg-static which I can't extract. And if I make it work and try to upgrade it'll also change my gettext packages and then everything will be broken, but I don't have a that long downtime"

Often the easiest way will be to just set up a fresh system with recent versions of the applications and migrate piece by piece, then lovingly place the old system in a shredder.

This guide is for when the easiest way is not available.



A system using old FreeBSD release with ports, no central package config / authority.

The system would probably need to be no older than FreeBSD6.

This is for two reasons: It then would at least support using freebsd-update. Also FreeBSD6 is the oldest release with an available compat-6x package. (Those compat packages give you backwards binary compatibility which allows to cover up many issues during the update. Covering up issues is good in this case, it helps you avoid disruptions till you have newer packages in place)

I've gone as far as lifting FreeBSD 7.2 systems to FreeBSD 9.3 (with an easy way onward).

You can still make some use of my notes if you're even on older FreeBSD versions, but you'll need to be ready to manually create a new root disk on your system, where you set up the 'new' world.


Externally managed and updated System, running a new version, with ports built on a poudriere server.

Being able to update it at any given time without losing your custom package settings.



We'll put up the following restrictions on our goal - those are where it gets a little more tricky. Their benefit is leaving you with some safety when something goes wrong, and to make sure that the upgraded system actually still resembles what you had there in the first place. 

  • No hand-set option should be lost
  • PKG should not corrupt itself
  • Each step should have minimum impact
  • Be able to reproduce each state
  • Be able to reinstall / replace broken software at any state



There's some things we can't protect against:

User name changes (i.e. amavisd -> vscan). You'll run into issues caused by such changes.

PKG corruption. PKG can easily corrupt and turn into a steaming pile of shit. This workflow is trying to *lower* the risk, but i.e. port merges are not understood by pkg and it will kill itself happily. I've seen that happen with docbook and some other ports. We can run some consistency checks to reduce the risk of bad surprises, but in general I feel it's best to not worry about it in advance since it's so random.



Gather Info

Original system

Gather /var/db/ports - here you'll find all the important settings for your ports, and those will be fed to poudriere soon :)

Gather package listing (see portmaster --list-origins at )

Gather make.conf - This will be the base for your poudriere make.conf for this system's build.

Improve Configuration

Setup a /etc/freebsd-update.conf with proper ignorelists. Those allow you to use freebsd-update IDS and have meaningful results from it. It should only alert you on unwanted / malicious changes. By default it comes with a very limited ignorelist and will report hundreds of files.

Setup mergemaster.rc with proper ignorelists and merge settings. This will let mergemaster automerge the way it should always had, making the mergemaster run during freebsd-update a matter of a minute or less. You'll only be asked about files that matter to you and have meaningful changes. The classical unimportant things like updated file headers will be applied without asking.

Update make.conf. make.conf has seen a lot of changes since the early days, many options have been added and deprecated. If you don't have clearly stated settings you'll end up with ports mix-matching different versions of apache and similar. You don't want that and a clean make.conf is the way to sort this out.


Setup poudriere for "special" services

Create poudriere options directory

Create poudiere make.conf

Setup build for existing OS release and packages

If needed, setup outdated portstree from the original system


Apply changes


snapshot and backup your system

Run pkg consistency checks (but don't ever let it fix anything on its own)

Disable the FreeBSD pkg repo

get the existing state from poudriere

Run a build for existing OS release and packages and existing options

Point pkg at your new repository

Fetch and extract pkg-static from pkg-<version>.txz and use it to self-upgrade pkg

pkg upgrade / pkg -f install (reinstall to this state, if you just switched to pkg this might be interesting)

switch to stable branch (2015Q2, ...)

Build for existing OS release with "stable" packages and existing options

Update the pkg repo you're pointing at

pkg upgrade

switch the OS version keeping same package versions

Build for target OS release with "stable" packages and existing options

Update the pkg repo you're pointing at

Update the OS to target version

pkg upgrade / pkg -f install

Re-run consistency checks

You are done!