🡅 up First steps with pkgbase

First steps with pkgbase

If you've been running FreeBSD for some time, you must have come across freebsd-update(8), the currently offical method of updating your FreeBSD installation. If you ever ran this to do a major release upgrade, you'll also have noticed speed is not one of its strengths... updating a system can easily take half an hour.

(Perhaps a 3.5 kLoC shell script spawning sha256(1) for each changed file is not the royal way to upgrade a system installation...)

Luckily, other people realized this too, and also saw that FreeBSD contains a perfectly cromulent binary package manager already, namely pkg(8).

Thus the pkgbase project was created, which aims to provide the FreeBSD base system as pkg binary packages, so you can install and update the base system as easily as the rest.

This has other benefits as well: you can remove parts of the system you never use, and also easily install e.g. debugging packages after the basic install (try that using freebsd-update!).

As of FreeBSD 14.0 the pkgbase repository is officially maintained, so let's give this a spin. The mechanism is not considered fit for production environments yet, thus we try this in a VM instead.

Basic setup

We start off by using the official release VM image FreeBSD-14.0-RELEASE-amd64.qcow2. Usually we'd bring it up to date first using freebsd-update, but we can skip this as we want to do the update using pkg.

Since the VM image fits only 4 GB by default, we need to remove /usr/lib/debug at first to have enough space for switching to pkg.

The steps are documented in the wiki, so I won't repeat them here.

Since we don't want to install debugging symbols and also only need a generic kernel, we save some space using:

# pkg install -r base $(pkg search -r base -q '.*' | grep -v -e dbg- -e mmccam)

This will should be pretty quick now.

The "problem" using pkg to install this way is that it will create a .pkgsave for every single file that is being installed that existed before (so, almost every file).

We need to get rid of these .pkgsave files quickly, which can be done using:

# find / -name '*.pkgsave' -delete

It would be really beneficial if pkg had an option to not create these .pkgsave files, at least for the initial installation.

Usage

Now, keeping your FreeBSD base system up to date is as easy as running

# pkg update && pkg upgrade

After rebooting, we now can check our system is up to date:

# uname -a
FreeBSD pkgbasetest 14.0-RELEASE-p4 FreeBSD 14.0-RELEASE-p4 releng/14.0-n265400-4edf3b80733 GENERIC amd64
# pkg version -Un FreeBSD-ssh
FreeBSD-ssh-14.0p4                 =

So we got the latest kernel and also the last security announcement.

Let's say we found a bug in yp(8), then we can simply install the debugging symbols for these programs only:

# pkg install FreeBSD-yp-dbg
# pkg list FreeBSD-yp-dbg
/usr/lib/debug/bin/domainname.debug
/usr/lib/debug/usr/bin/ypcat.debug
/usr/lib/debug/usr/bin/ypmatch.debug
/usr/lib/debug/usr/bin/ypwhich.debug
/usr/lib/debug/usr/libexec/ypxfr.debug
/usr/lib/debug/usr/sbin/rpc.yppasswdd.debug
/usr/lib/debug/usr/sbin/rpc.ypupdated.debug
/usr/lib/debug/usr/sbin/rpc.ypxfrd.debug
/usr/lib/debug/usr/sbin/yp_mkdb.debug
/usr/lib/debug/usr/sbin/ypbind.debug
/usr/lib/debug/usr/sbin/ypldap.debug
/usr/lib/debug/usr/sbin/yppoll.debug
/usr/lib/debug/usr/sbin/yppush.debug
/usr/lib/debug/usr/sbin/ypserv.debug
/usr/lib/debug/usr/sbin/ypset.debug

Likewise, if you get compelled into debugging the kernel, you can just use

# pkg install FreeBSD-kernel-generic-dbg

and kgdb etc. will work.

Caveats

I didn't do a major upgrade yet, but you need to take care yourself to install the new kernel first and then update the userland.

Updating to a snapshot

Actually, we can do a system update, as snapshot release are provided via pkgbase as well. Let's flip the repo url in /usr/local/etc/pkg/repos/base.conf to pkg+https://pkg.freebsd.org/${ABI}/base_latest.

We immediately hit a version mismatch, which we accept:

# pkg update
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating base repository catalogue...
pkg: Repository base has a wrong packagesite, need to re-create database
Fetching meta.conf: 100%    163 B   0.2kB/s    00:01    
Fetching packagesite.pkg: 100%   40 KiB  41.2kB/s    00:01    
Processing entries:   0%
Newer FreeBSD version for package FreeBSD-vi-man:
To ignore this error set IGNORE_OSVERSION=yes
- package: 1400501
- running kernel: 1400097
Ignore the mismatch and continue? [y/N]: y
Processing entries: 100%
base repository update completed. 524 packages processed.
All repositories are up to date.

However, pkg upgrade will do nothing. The problem is that the snapshot versions are considered to be behind the release versions; I'm not sure that's intentional, but we can force install the kernel and notice pkg(8) considers this a downgrade:

# pkg install -f FreeBSD-kernel-generic
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating base repository catalogue...
base repository is up to date.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):

Installed packages to be DOWNGRADED:
  FreeBSD-kernel-generic: 14.0p4 -> 14.snap20240111062527 [base]

Number of packages to be downgraded: 1

After accepting this too and rebooting, we find ourselves in a snapshot kernel of the STABLE branch:

# uname -a
FreeBSD pkgbasetest 14.0-STABLE FreeBSD 14.0-STABLE stable/14-n266270-b4d11915c73f GENERIC amd64

To update (well "downgrade") the rest of the system, we go on as above, but with force:

# pkg install -f -r base $(pkg search -r base -q '.*' | grep -v -e dbg- -e mmccam)

pkg will complain a bit because new *-man packages have been created which conflict with the old packages where manpages were included, but it can figure out how to fix this itself.

There are also new src and sys-src packages which you may want to ignore as well. But using pkg(8) to keep the source tree up to date is also nifty. ;)

Issues

Snapshot versions probably should use .99.snapshotYYYYMMDD, so upgrading to a snapshot is really an upgrade.

There is a naming clash between FreeBSD-ftpd from base and freebsd-ftpd from ports... but pkg happily installs both and then can only remove both at once again... huh?

pkg supports package annotations which contain additional metadata; e.g. for the ports packages, we have:

# pkg info screen
...
Annotations    :
  FreeBSD_version: 1400097
  build_timestamp: 2024-01-05T11:04:30+0000
  built_by       : poudriere-git-3.4.0
  cpe            : cpe:2.3:a:gnu:screen:4.9.1:::::freebsd14:x64:1
  port_checkout_unclean: no
  port_git_hash  : 8659dcf7d1
  ports_top_checkout_unclean: no
  ports_top_git_hash: a8c72eab47
  repo_type      : binary
  repository     : FreeBSD

Unfortunately, the pkgbase packages don't contain some of the fields here that would be useful, like build_timestamp or top_git_hash.

Still, pkgbase is a definitive improvement over the status quo and I hope it gains more traction and becomes the offcial method for updating.