Here I'm republishing an old blog post of mine originally from August 2017. The article has been slightly improved.
This article references a graphical FreeBSD-based OS that has long been discontinued: TrueOS. When the article was originally written the project was still very much alive.
FreeBSD is a server operating system popular among more experienced administrators. It's also often used in appliances or embedded products and it makes a nice desktop, too, if you are a bit more proficient with it. Sure, you don't read about it all the time. This is because of two things: 1) Linux is usually absorbing most of the attention 2) FreeBSD just silently and reliably does its job. FreeBSD is also the basis of some special-purpose open source operating systems.
Are you new to FreeBSD? You've picked a good time to take a look: _Version 11.1_ has been released recently and a lot of people who have wanted to give it a spin for a while are getting an ISO and try it out. Also _OPNsense 17.7_, a popular router/firewall OS has been released, also not too long ago.
If you're coming e.g. from OPNsense, you have a nice Web UI at your hands that makes controlling and maintaining it easy. That does not mean that you wouldn't benefit from knowing more about how to do package management by hand, however. OPNsense is built on top of FreeBSD which means that you have all the power of that operating system available if you know what to do if the Web UI doesn't provide a simple option to do it!
If you're using a FreeBSD-based project like _OPNsense_ or a desktop spin like _GhostBSD_ or _TrueOS_, it's located in _/usr/local/sbin/pkg_. With vanilla FreeBSD it's almost certainly in the same place of course, if you've been using the system for a while. What do I mean by that? Well, in the previous post about the history of *nix package management I made the claim that modern FreeBSD comes without a package manager. And that's actually true! Take a look at the path mentioned above. See what I mean?
The history of *nix package management
FreeBSD uses the directory tree under _/usr/local_ for programs that are installed as add-on packages, i.e. software that is not part of the base system. Yes, that means that even the package manager is a package! How does that work? Well, there's also _/usr/sbin/pkg_, which is part of the base system. If _pkg_ is not present on the system, it's able to bootstrap it as the first package on the system. If the package manager is already installed, it simply acts as a wrapper (thanks to its location and the default PATH variable it takes precedence over the actual pkg). Bootstrapping is as easy as pressing 'y', so we don't really need to cover it beyond this.
Sounds a bit strange, right? Yes, but there's a good reason for this. Pkg's life began as _pkg-ng_ when FreeBSD still used the old pkg_* tools, so it made sense to develop it outside of the base system. But why wasn't it imported into the base system when the old tools were retired? Actually, FreeBSD maintains ABI stability for the base system for the life-cycle of a release (e.g. 11). The last point release of the 10 branch, FreeBSD 10.4, is just about a month away from now. If pkg had been part of base, that would have meant the new release would have to ship with pkg 1.2 (since 1.2.4 was the version available when 10.0 was released)! The 11 branch would ship with 1.8, as 1.8.7 was the current version when FreeBSD 11.0 was released. Either that or no ABI changes would be allowed for pkg.
That would have meant slower progress, since no package would have been allowed to depend on features introduced after 1.2 until 10.4 went EOL - which might be as far away as somewhere near the end of 2019! Fortunately pkg is a package and thus could be improved rapidly: All versions of FreeBSD have pkg 10.1 today instead of 1.8 - or even 1.2.
If you have no idea how to use pkg, you can use *pkg help*. This will show a list of supported options and commands. And if you want to know even more, you can always type *man pkg*. There are also man pages for most of the pkg commands, usually named pkg-_command_. As a shortcut to those, you could also type *pkg help command* which will display the correct man page.
On the long run it's not a bad idea to read a bit more about pkg, but if you are just getting started, all the possibilities might overwhelm you. So let's discuss a few practical examples to get you up to speed easily and quickly, shall we?
As long as you just use pkg to gather information, you can run it as any user. Modifying anything needs root privileges, of course.
By default pkg operates on a remote _repository_. A _repo_ (common abbreviation) is simply a place where packages are stored and kept accessible together with an index file. To be of any use, pkg needs that index and (with the default configuration) will fetch (or update if it deems the local copy too old) it before performing any action you might want it to do. If you just want to get/update the index, you can run *pkg update*:
# pkg update
Updating FreeBSD repository catalogue...
Fetching meta.txz: 100% 944 B 0.9kB/s 00:01
Fetching packagesite.txz: 100% 6 MiB 548.9kB/s 00:11
Processing entries: 100%
FreeBSD repository update completed. 26602 packages processed.
All repositories are up to date.
Assuming you can connect to the repo, this will fetch the latest index and process it. Pkg uses a local sqlite database created from the index so that it can quickly and simply get information from it.
To see if a package in any configured repository is available for installation, use *pkg search*:
% pkg search bash
bash-4.4.12_2 GNU Project's Bourne Again SHell
bash-completion-2.5,1 Programmable completion library for Bash
bash-static-4.4.12_2 GNU Project's Bourne Again SHell
bashc-3.2.33.0_1 GNU bash shell extended with visual two-panel file browser
checkbashisms-2.15.10 Check for the presence of bashisms
erlang-mochiweb-basho-2.9.0p2 Erlang library for building lightweight HTTP servers (Basho fork)
mybashburn-1.0.2_4 Ncurses CD burning bash script
p5-Bash-Completion-0.008_1 Extensible system to provide bash completion
p5-Term-Bash-Completion-Generator-0.02.8_1 Generate bash completion scripts
Pkg returns a list of hits, each with package name and version as well as a short comment to give you an idea what the package actually is. If you know either the package name or part of the name, searching is easy enough.
Now let's assume you are looking for a light-weight web browser but you forgot the name! Since it's not very likely that the package's name contains "browser", how do you search for it? You could simply search the comments e.g. for "web browser", but that would lead to quite a list. Do you remember anything else about the browser? Let's say we know that it uses the FLTK toolkit. Let's see if we can find that package:
% pkg search -c "web browser" | grep -i FLTK
dillo-3.0.5 Fast, small graphical Web browser built upon fltk
There we are, the browser's name is _dillo_! If even searching in the comments doesn't yield what you are searching for, you might resort to *pkg search -D _keyword_*. This will search in the detailed description that each package comes with. Just be prepared for a lot of hits and a wall of text if you're using common keywords.
In many cases it's not a bad idea to use a web-based search. That is what the site FreshPorts provides among other things.
If you're trying to get into FreeBSD, this is a site that you might want to bookmark. Quite possibly it'll come in handy rather often. Also spend a little while exploring what it offers. Getting familiar with it is in fact time well spent.
To install a package, just issue *pkg install _pkgname_*:
# pkg install chocolate-doom
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 7 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
chocolate-doom: 2.3.0
sdl_net: 1.2.8_3
doom-data: 1.0_1
sdl_mixer: 1.2.12_12
smpeg: 0.4.4_14
timidity: 0.2i_1
libmikmod: 3.3.8
Number of packages to be installed: 7
The process will require 22 MiB more space.
11 MiB to be downloaded.
Proceed with this action? [y/N]:
Just answer _y_ to make pkg fetch and install those packages (any PC without DooM installed just isn't complete after all - I still stick to that even though I haven't found time to actually fire up that game in years!).
To query the package database, use *pkg info*. Without any further arguments this will return a list of all installed packages (so you probably want to pipe it into a pager like _less_). Searching for a specific package? You can definitely do that using your standard Unix tools, but hold that _grep_ right now! There's a better way:
% pkg info -x mate-t
ghostbsd-mate-themes-1.4
mate-terminal-1.18.1
mate-themes-3.22.12
The _-x_ switch enables searching with regular expressions. The search in my example shows all packages that contain "mate-t". You may even want to get used to adding -i, too, which enables case-insensitive search - just in case (there aren't that many packages in FreeBSD that contain uppercase letters, but some do).
If you found your package, just use *pkg info [packagename]* (without the square brackets, of course) to get a whole lot of information about the package! But that's probably more than you wanted and it makes sense to know a few more switches that just give you some specific information.
A nice one is _-D_. Forgot what that post-install message was that told you how to actually get your package to work? This option prints it again:
% pkg info -D chromium
chromium-60.0.3112.101:
Always:
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
[...]
Use _-d_ to query information about a package's dependencies:
% pkg info -d galculator
galculator-2.1.4:
pango-1.40.6
gtk3-3.22.15
gtk-update-icon-cache-2.24.29
gdk-pixbuf2-2.36.6
cairo-1.14.8_1,2
glib-2.50.2_4,1
gettext-runtime-0.19.8.1_1
atk-2.24.0
With _-l_ you can list all the files that a package installed in your filesystem:
% pkg info -l mksh
mksh-56_1:
/usr/local/bin/mksh
/usr/local/man/man1/mksh.1.gz
/usr/local/share/examples/mksh/dot.mkshrc
/usr/local/share/licenses/mksh-56_1/ISCL
/usr/local/share/licenses/mksh-56_1/LICENSE
/usr/local/share/licenses/mksh-56_1/ML
/usr/local/share/licenses/mksh-56_1/catalog.mk
The last one of the basic operations is removing packages. Here in my example I spotted a package called "tracker", a filesystem indexer that comes with GNOME. If you don't use that desktop and find it on your system: Kill it with fire! Nuke it from the system with *pkg delete*:
# pkg delete tracker
Checking integrity... done (0 conflicting)
Deinstallation has been requested for the following 2 packages (of 0 packages in the universe):
Installed packages to be REMOVED:
tracker-1.6.1_9
nautilus-3.18.5
Number of packages to be removed: 2
The operation will free 21 MiB.
Proceed with deinstalling packages? [y/N]: y
Deinstalling this package will also get rid of Nautilus as well (since tracker is a dependency for that). But as the GNOME team pretty much ruined that once decent file manager, I'm not going to shed any tears over that loss and press enter. Pkg will then delete all the files associated with the package and un-register it in the package database.
That's it for the basics in my opinion. The next post will show off a few of the more advanced features that Pkg offers.