On FreeBSD, what is the difference between installing software from the ports tree and installing it with pkg, and when is building from ports actually worth the time?
answer
- same catalogue, two delivery paths
- Makefiles versus prebuilt binaries
- default options are the whole difference
- custom options need your own repository
- quarterly is the default branch
basics
~20 sThe ports tree is a collection of build recipes you compile from source with your own options; pkg installs prebuilt binary packages that the project produced from those same recipes using default options. Most installs should use pkg.
solid answer
~50 sThey are two front ends to the same catalogue. The ports tree, usually at `/usr/ports`, is a directory per piece of software containing a `Makefile` and patches; `make install clean` fetches the source, applies the patches, builds it and registers the result. The FreeBSD project runs that same tree through its build cluster with **default** options and publishes the results as binary packages, which `pkg install` fetches in seconds. Ports are worth it when you need a non-default build option, a local patch, or a licence-restricted piece that cannot be redistributed as a binary — `make config` shows the option menu. The trap is mixing the two carelessly: a binary package's dependencies were compiled against default options, so a hand-built port with different options can collide with them. If you need custom options across a fleet, build your own binary repository with `poudriere` and let every machine install from that with `pkg`.
code
bash · 12 lines# Binary path: fast, default options, signed by the project
pkg install nginx
pkg info nginx
# Source path: same catalogue, your options
cd /usr/ports/www/nginx
make config
make install clean
# Either way, one database
pkg info | grep nginx
pkg audit -Fgo deeper
Know that pkg install fetches a prebuilt binary and is what you use day to day, while the ports tree is source recipes you compile yourself. Be able to name one real reason to compile: a build option the default package does not enable.
Explain that the binary packages are built from the very same ports tree with default options, and describe the mixing hazard — hand-built ports against binary dependencies — plus the quarterly versus latest repository choice.
Show the fleet answer: custom options are solved by building a signed repository with poudriere and installing from it everywhere, not by compiling on each host. Mention pkg audit and locking as part of the maintenance routine.
Own the supply-chain angle — who builds your binaries, how they are signed, how long a quarterly branch is patched, and what owning an internal repository costs in build infrastructure versus what it buys in reproducibility and audit.
## One catalogue, two delivery mechanisms FreeBSD keeps third-party software in the **ports tree** — historically fetched to `/usr/ports`, and nowadays obtained from the project's git repository. Each port is a small directory named by category and program, for example `www/nginx`, containing a `Makefile`, a checksum file, a list of files the port installs, and any patches FreeBSD applies on top of the upstream source. The Makefile declares the upstream distribution file, the dependencies, and the build options. Building from a port is a single command inside that directory: ```sh cd /usr/ports/www/nginx make config # curses menu of this port's build options make install clean ``` The framework fetches the tarball, verifies it, applies patches, configures, compiles, installs under `/usr/local` and registers the result — which matters: a port you build is registered in the same package database that `pkg` uses, so `pkg info` sees it and `pkg delete` removes it. **pkg** is the binary side. The FreeBSD project builds the entire ports tree on its own cluster, with each port's *default* options, and publishes the results as signed binary packages. `pkg install nginx` fetches the finished artefact and its dependencies: ```sh pkg install nginx pkg info nginx pkg delete nginx ``` The published repository comes in two flavours: a **quarterly** branch, which is the default and receives only build fixes and security updates for three months at a time, and a **latest** branch that tracks the ports tree continuously. The choice is a configuration file — the shipped default lives in `/etc/pkg/FreeBSD.conf` and is overridden by a file under `/usr/local/etc/pkg/repos/`. Quarterly gives a stable server; latest gives current versions on a workstation. ## When compiling is genuinely worth it 1. **You need a non-default option.** The binary package for a database or a web server is built with whatever the maintainer chose as sensible defaults. If you need a module the default build omits, or want to omit a dependency you refuse to install, the port is the only way to get it. 2. **You need a local patch.** Dropping a patch into the port's `files/` directory makes it part of every rebuild. 3. **Licence-restricted software.** Some ports cannot legally be redistributed as binaries, so no package exists and the port is the only route. 4. **You are the maintainer**, testing a change before it ships. Everything else is better served by `pkg`. Building a browser, a compiler toolchain or a desktop stack from source costs hours of CPU on every machine and every upgrade, and buys you a binary identical to the one you could have downloaded. ## The mixing hazard The common production failure is a hybrid system: mostly binary packages, with two or three ports built by hand with custom options. Those binary packages were linked against dependencies built with *default* options. A hand-built dependency with different options — or simply built at a different point in the ports tree's history — can present a different ABI or a different set of installed files, and the next `pkg upgrade` may want to replace your customised build with the stock one. Symptoms are missing symbols at start-up, or a package silently reverting to defaults after an upgrade. The supported way out is `poudriere`: it builds ports in clean jails and produces a signed binary repository of your own. You define the option set once, build once, and every machine in the fleet does an ordinary `pkg install` against your repository. You get custom builds *and* binary-package speed and consistency, which is why this is the standard answer for anything larger than a single box. ## Everyday hygiene `pkg audit -F` downloads the vulnerability database and lists installed packages with known issues — worth running from a periodic job. `pkg autoremove` drops dependencies nothing needs any more. `pkg check -d` verifies dependency completeness. `pkg lock` pins a package that must not move. None of these care whether the package arrived as a binary or was built from a port, because both register in the same database. ## What the interviewer is checking That you know these are not rival package managers but one catalogue with two delivery paths; that your default is the binary path; that you can state a concrete reason to compile; and, at any level above beginner, that you know the custom-build problem is solved at fleet scale by building your own repository rather than by compiling on each host.
- You need one package built with a non-default option on forty servers. Why not just build the port on each of them?Because you would pay the compile cost forty times, on every upgrade, and risk forty subtly different binaries built at different points in the ports tree's history. The supported approach is `poudriere`: build the option set once in clean jails, publish a signed binary repository, and point every machine's `pkg` at it. You get the custom build with binary-package speed and byte-identical results.
- What is the practical difference between the quarterly and latest pkg repository branches?Quarterly is a branch of the ports tree snapshotted every three months and given only security and build fixes, so versions stay put between snapshots — the sensible default for servers, and it is the shipped default. Latest follows the ports tree continuously, so you get new upstream versions as they land, which suits a workstation but means more churn and more frequent restarts on a server.
- If you build a port by hand, does pkg know about it?Yes. The ports framework registers what it installs in the same package database, so `pkg info` lists it and `pkg delete` removes it cleanly. That is also why a hand-built port can be replaced by the stock binary on the next `pkg upgrade` unless you lock it — the database does not record that you wanted different options.
saying these in an interview costs you the question
- Calls ports and pkg two competing package managers
- Believes compiling from ports gives better performance by default
- Mixes hand-built ports and binary packages without expecting conflicts
- Thinks a port built by hand is invisible to pkg
- Assumes the default pkg repository always has the newest versions