FreeBSD package management with Pkg (2/2)

The previous article covered basic operations with FreeBSD’s Pkg tool. This second part will deal with some more advanced (or rather intermediate, actually) functionality.

Good code travels well

My previous two articles have been linked to from the DragonFly Digest (a very valuable resource for topics in BSD and the IT in general that I’ve been reading for years now and would like to say “thanks!”) again. Justin Sherrill pointed out that everything applies to DragonFlyBSD as well – they have adopted Pkg quite a while ago. And in fact you benefit from knowing your way around with Pkg in a lot of places:

FreeBSD obviously and a lot of FreeBSD-derived operating systems like OPNsense and HardenedBSD as well as desktop-oriented offspring like GhostBSD and TrueOS.

But as mentioned before, DragonFlyBSD uses it, too. And thanks to the new (and extremely exciting, IMO!) Ravenports project it has already come to Linux and will be available on even more platforms in the future! So getting familiar with it is certainly not a waste of time.

Package versioning

Before we start updating packages, let’s take a look at the versioning scheme. The way FreeBSD versions its packages can be a bit confusing if you first see it. Here’s a sample package with a rather complicated version string:

# pkg search opensmtpd | grep OpenBSD
opensmtpd-5.9.2p1_3,1          Security- and simplicity-focused SMTP server from OpenBSD

opensmtpd-5.9.2p1_3,1 – what does that all mean? Well, first we have the package name: opensmtpd, followed by a minus. Then there’s the upstream version of the program, 5.9.2p1 in this case.

Then there’s the underscore and another number: _3 in this case. This indicates our package is “revision 3”. Any new package starts with a revision of 0. If a port is revised (probably to correct a mistake, add more configure options, etc), the revision number is bumped. So this port has been revised three times without changing the actual upstream version.

And finally, separated by a comma, we have what is called the “epoch”. It is used in such cases where the upstream versioning changes. Any package with an epoch of 1 is considered newer than a package without any epoch. Even higher epoch numbers are considered even newer but this is rare. When do you need this? Let’s assume some project released a version of 7.2017 but decided that it would be a good idea to release the next version as 5.0. For Pkg it looks like the first one is newer (as it has a higher version number). In such a case you’d set an epoch to make Pkg understand that in fact the other one is the more up-to-date package.

Updating packages

I covered updating the repository information before. Update the actual packages with pkg upgrade:

# pkg upgrade
Updating Synth repository catalogue...
Synth repository is up to date.
All repositories are up to date.
Checking for upgrades (30 candidates): 100%
Processing candidates (30 candidates): 100%
Checking integrity... done (0 conflicting)
The following 30 package(s) will be affected (of 0 checked):

Installed packages to be UPGRADED:
        xinit: 1.3.4,1 -> 1.3.4_1,1
        xerces-c3: 3.1.4 -> 3.2.0_2
        virtualbox-ose: 5.1.26 -> 5.1.26_1
        vim: 8.0.0962 -> 8.0.1035
        sudo: 1.8.20p2_3 -> 1.8.21p1
        sqlite3: 3.20.0_2 -> 3.20.1
        rubygem-net-ssh: 4.1.0,2 -> 4.2.0,2
        rubygem-multi_json: 1.12.1 -> 1.12.2
        ruby23-gems: 2.6.12 -> 2.6.13
        pulseaudio: 10.0_4 -> 11.0
        pciids: 20170727 -> 20170825
        p11-kit: 0.23.7 -> 0.23.8
        open-vm-tools: 10.1.5_1,2 -> 10.1.10,2
        nano: 2.8.6 -> 2.8.7
        mesa-libs: 17.1.7 -> 17.1.8
        mesa-dri: 17.1.7 -> 17.1.8
        libreoffice: 5.3.5_1 -> 5.3.6
        libidn2: 2.0.3 -> 2.0.4
        libgcrypt: 1.8.0 -> 1.8.1
        libdrm: 2.4.82,1 -> 2.4.83,1
        hunspell: 1.6.1_1 -> 1.6.2
        harfbuzz-icu: 1.4.8 -> 1.5.1
        harfbuzz: 1.4.8 -> 1.5.1
        gdk-pixbuf2: 2.36.6 -> 2.36.9
        e2fsprogs: 1.43.5 -> 1.43.5_1
        doas: 6.0p0 -> 6.0p1
        chromium: 60.0.3112.101 -> 60.0.3112.113
        atril: 1.18.0_1 -> 1.18.1

Installed packages to be REINSTALLED:
        keybinder-0.3.1 (options changed)
        apache-xml-security-c-1.7.3 (needed shared library changed)

Number of packages to be upgraded: 28
Number of packages to be reinstalled: 2

The process will require 2 MiB more space.

Proceed with this action? [y/N]:

The packages to be UPGRADED section is pretty obvious: There’s a newer version available. But there are also two packages in this example that are being reinstalled even though no new version is available. Pkg gives the reason for this in parentheses:

Keybinder will be reinstalled because it was compiled with other compile-time options than before (more about this in the next post). The second one depends on xerces-c3, a package in the list of upgradable packages, which is why apache-xml-security-c was rebuilt against the new version of the library.

There are other reasons that packages are to be reinstalled; if you upgraded your OS from one major version to another, the reason might be “ABI has changed”. It’s also possible that some packages will be deinstalled for an upgrade. This is usually because they conflict with another package that is to be installed. This also means: Do look at what the update is going to do! There is the chance that it would do something that you didn’t intend to.

Will this update cause me trouble?

You can never know for sure. But there is a means to learn about known issues beforehand. For your important applications it is a good idea to read the so-called “UPDATING information”. This is a short text (or some of them) which might contain a heads-up that can be critical to know. To view it, use pkg updating. Here’s an old example showing how bad it could be to have missed it:

# pkg updating apache22                 
20140713:                                          
  AFFECTS: users of www/apache22                   
  AUTHOR: ohauer@FreeBSD.org                       
                                                   
  The default version was changed from www/apache22 to www/apache24,                                   
  pre-build apache modules and web applications will also reflect this!                                
                                                   
  In case ports are build by yourself and apache22 is required                                         
  use the following command to keep apache22 as default.                                               
                                                   
  # echo "DEFAULT_VERSIONS+=apache=2.2" >> /etc/make.conf

Having missed that one would have had very bad effects… For such reasons it’s good practice to read the UPDATING info. You don’t actually have to read it and will probably get away with it for quite some time. But it’s there for your benefit. So if you choose to ignore it, don’t complain if an update finally bites when it finds you off guard!

Blocking updates

Let’s stick to the previous example and say that we want to do the update – but LibreOffice should not be touched because we’re working on an important document currently and don’t want to risk layout breakage (minor updates should be no problem but bigger updates are known to sometimes cause trouble). What to do in that case?

Let’s lock the package using pkg lock:

# pkg lock libreoffice
libreoffice-5.3.5_1: lock this package? [y/N]: y
Locking libreoffice-5.3.5_1

Attempting the upgrade again, Pkg should now show only 27 candidates and leave LibreOffice alone. There are a few good reasons to lock a package – and a lot of bad ones. Resort to locking packages when necessary but don’t trifle with it because you’re effectively cutting yourself off from updates on some packages. Those could have dependencies. Probably dependencies that they share with other packages. You can see how this gets a lot bigger than “just that one package” rather quickly.

Also if you decide to use locking, make sure to look for locked packages now and then and think over if the lock is still needed! If not, release the lock. But how to find out which packages are locked? Pkg info can help us out:

# pkg info -k -a | grep yes             
libreoffice-5.3.5_1            yes

Unlocking works just like you’d probably expect it to:

# pkg unlock libreoffice                                                                                                                                                                           
libreoffice-5.3.5_1: unlock this package? [y/N]: y
Unlocking libreoffice-5.3.5_1

Package comments

We’ve locked LibreOffice above – but how do we remember in four months or so why it was locked? This is what we can use an annotation for. Set one with pkg annotate:

# pkg annotate -A libreoffice locked-pkgs "This package was locked on 09/10 until I finally finish the manuscript for my fantasy novel!"                                                           
libreoffice-5.3.5_1: Add annotation tagged: locked-pkgs with value: This package was locked on 09/10 until I finally finish the manuscript for my fantasy novel!? [y/N]: y
libreoffice-5.3.5_1: added annotation tagged: locked-pkgs

The argument “-A” is to set an annotation to the following package. “locked-pkgs” is a tag – you could call it whatever you want. And finally the last field is the actual comment string.

Using pkg info and the package name will display the comment among a lot of other information. But it might make more sense to look for all packages that have an annotation with a certain tag:

# pkg annotate -a -S locked-pkgs
libreoffice-5.3.5_1: Tag: locked-pkgs Value: This package was locked on 09/10 until I finally finish the manuscript for my fantasy novel!

If you no longer need the annotation, delete it like this:

# pkg annotate -D libreoffice locked-pkgs                                                                                                                                                          
libreoffice-5.3.5_1: Delete annotation tagged: locked-pkgs? [y/N]: y
libreoffice-5.3.5_1: Deleted annotation tagged: locked-pkgs

Are those updates important?

Some updates mean new features, others mean fixing of critical security holes. How are you supposed to know? The easy way is to ask Pkg! Use pkg audit and it will tell you about known vulnerabilities of the software installed on your system:

pkg audit
libgcrypt-1.8.0 is vulnerable:
libgcrypt -- side-channel attack vulnerability
CVE: CVE-2017-0379
WWW: https://vuxml.FreeBSD.org/freebsd/22f28bb3-8d98-11e7-8c37-e8e0b747a45a.html

chromium-60.0.3112.101 is vulnerable:
chromium -- multiple vulnerabilities
CVE: CVE-2017-5120
CVE: CVE-2017-5119
CVE: CVE-2017-5118
CVE: CVE-2017-5117
CVE: CVE-2017-5116
CVE: CVE-2017-5115
CVE: CVE-2017-5114
CVE: CVE-2017-5113
CVE: CVE-2017-5112
CVE: CVE-2017-5111
WWW: https://vuxml.FreeBSD.org/freebsd/e1100e63-92f7-11e7-bd95-e8e0b747a45a.html
[...]

No way back?

Are you not feeling completely confident about an update? Does your customer demand “a way back” in case something goes wrong? You can use pkg create to package already installed software:

# pkg create chromium-60.0.3112.101
Creating package for chromium-60.0.3112.101

In this example I’ve packaged Chromium before updating so that I could reinstall the old version. Keep in mind, though, that this is just an example. If dependencies changed as well, you might not be able to use the old version, even when you reinstalled it! If you want to be really, really cautious, you can use pkg create -a to create packages of all the software currently installed on your system!

The package(s) is/are created in the current directory. I just deinstalled Chromium after creating the package and now want it back. To install software directly from a package (and not a repo), use pkg add:

# pkg add chromium-60.0.3112.101.txz
Installing chromium-60.0.3112.101...
Extracting chromium-60.0.3112.101: 100%
Message from chromium-60.0.3112.101:
For correct operation, shared memory support has to be enabled
in Chromium by performing the following command as root :

sysctl kern.ipc.shm_allow_removed=1

To preserve this setting across reboots, append the following
to /etc/sysctl.conf :

kern.ipc.shm_allow_removed=1

Finding the package a file belongs to

In many cases you can probably tell from the path and name of a file which package it belongs to. But sometimes you may wonder: Where does this come from? This is where pkg which is really helpful. Let’s pick a file with a non-obvious name and pretend we don’t know what it is. We better ask pkg where it belongs:

% pkg which /usr/local/etc/drirc     
/usr/local/etc/drirc was installed by package mesa-dri-17.1.7

Ah, mesa! We better leave that one alone.

Repositories

If you looked closely at the output of my upgrade command, you have seen mention of a repo called Synth. I’ll cover that in a later post. But there is something you might want to know about the ordinary repos, too. Modern FreeBSD provides two package repositories: quarterly and latest. The later always holds the newest packages, the former gets version updates every three months and only security fixes in-between. The quarterly repository is a good choice for people who don’t want the newest software at all times but prefer a slower-moving environment. Since version 10.2 quarterly is the default.

If you want to use the packages from latest, you have to configure pkg to use it. Take a look at the file /etc/pkg/FreeBSD.conf to get an idea of how repo configuration looks like. Then create the necessary directory and another configuration file to overwrite the default:

# mkdir -p /usr/local/etc/pkg/repos
# vi /usr/local/etc/pkg/repos/FreeBSD.conf

Put the following lines in that file:

FreeBSD: {
  url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest"
}

Now use pkg update to refresh the repository database.

What’s next?

There’s a lot more that Pkg can do – and we haven’t even touched its main configuration! But the two posts were just meant to introduce you to FreeBSD package management (and chances are that you already know more now than many admins who occasionally use FreeBSD). I might or might not write about more features of Pkg in the future. But next stop now: The ports tree.

Edit: I got the patch level wrong with the version schema as leper pointed out in the comments. The wrong claim was removed.

7 thoughts on “FreeBSD package management with Pkg (2/2)

  1. Actually 5.9.2p1 is the upstream version in “opensmtpd-5.9.2p1_3,1”. This is something that is quite common for OpenBSD originating packages (OpenSSH, LibreSSL, sudo (maintained by an OpenBSD dev)), where the ‘p’ indicates a portable version and the number afterwards indicates how many portable versions of the corresponding OpenBSD version (5.9.2 in the example) have been published.

    1. Hi leper! Thanks a lot for your comment about how there’s nothing special about that ‘p’ as far as FreeBSD is concerned! I’ve corrected my mistake it in the main article.

      1. Happy to help.

        Also looking forward to more articles, as I’m totally not planning on stealing some more ideas for my own router/bouncer/whatnot box.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.