Synopsis #
OpenBSD binary packages are the preferred way to install third-party software. Use the ports tree to build a maintained port with a documented flavor, test a local patch, or develop a port. It is not a general substitute for supported packages.
This guide builds one existing port from a ports tree that matches the installed OpenBSD branch. Building arbitrary upstream source outside the ports framework bypasses OpenBSD package metadata, patches, dependency tracking, and update handling.
Confirm that a Ports Build Is Necessary #
Search the available binary packages first:
pkg_info -Q example
# Search available binary package names
pkg_info -a
# Review installed packages and versions
example is a placeholder. Use the actual software stem. Prefer pkg_add when the required package and flavor already exist.
Do not mix release packages with a -current ports tree or build release ports on a snapshot system. The base system, packages, and ports tree must follow a compatible branch.
Prepare the Build Host #
Install all required OpenBSD file sets, including comp, and allocate enough space for distfiles, work directories, packages, and dependencies. Large ports can require tens of gigabytes and long build times.
Keep the build host updated within its selected branch. Record:
uname -r
# Identify the running OpenBSD release
df -h /usr /tmp
# Confirm capacity for the ports tree and build work
mount
# Confirm filesystem layout and mount options
Do not change kernel limits or filesystem mount options until a documented port requirement or reproduced failure establishes the need.
Obtain a Matching Ports Tree #
Use either the signed ports.tar.gz from the matching release directory or an official AnonCVS server and branch. The current Handbook version is OpenBSD 8.0. In commands, replace OPENBSD_X_Y with the corresponding release branch name shown by the official AnonCVS documentation.
For an AnonCVS checkout, create the conventional directory and grant the wsrc group write access. Add the fetching account to wsrc only while preserving its other intended supplementary groups, then start a new login session:
doas install -d -o root -g wsrc -m 775 /usr/ports
Example AnonCVS checkout:
cd /usr
# Place the tree at the conventional path
cvs -qd anoncvs@ANONCVS_SERVER:/cvs checkout -r OPENBSD_X_Y -P ports
# Fetch the matching release branch from a selected official server
ANONCVS_SERVER and OPENBSD_X_Y are placeholders. Select a listed server and the branch that exactly matches the installed release. A -current system normally tracks the current ports tree instead.
When starting from the release archive on a release system, verify the signed checksum before extraction:
cd /tmp
# Select a temporary download directory
release=$(uname -r)
# Identify the installed release
ftp https://cdn.openbsd.org/pub/OpenBSD/$release/ports.tar.gz
# Download the matching release archive
ftp -o ports.SHA256.sig https://cdn.openbsd.org/pub/OpenBSD/$release/SHA256.sig
# Download the release-wide signed manifest
signify -C -p /etc/signify/openbsd-$(echo "$release" | tr -d .)-base.pub -x ports.SHA256.sig ports.tar.gz && \
doas tar xzf /tmp/ports.tar.gz -C /usr
# Verify the archive and extract it only when verification succeeds
Use an empty /usr/ports destination. Do not overlay an unrelated checkout. To update a release archive to the matching stable branch, specify an official repository explicitly:
cd /usr/ports
# Enter the extracted tree
release_tag="OPENBSD_$(uname -r | tr . _)"
# Select the stable branch for a release kernel
doas cvs -qd anoncvs@anoncvs.fr.openbsd.org:/cvs update -r "$release_tag" -Pd
# Update from the selected official mirror
Check the server’s SSH fingerprint against the Anonymous CVS mirror list
on the first connection. The explicit repository overrides the repository recorded in the archive. These commands are not for -current kernels.
Inspect the Port #
Change to the intended port directory and inspect metadata:
cd /usr/ports/category/example
# Enter the selected port directory
make show=PKGNAME
# Display the package name produced by the default build
make show=FLAVORS
# Display supported flavors
make show=MULTI_PACKAGES
# Display available subpackages
category/example is a placeholder. Use a pkgpath from the matching ports tree. Do not invent a flavor from an upstream build option; only values reported by the port are valid.
Read the port’s pkg/DESCR, patches, and maintainer comments before building. Review the estimated dependency and package impact with the available show targets documented by ports(7)
.
Configure Build Privilege Separation #
The ports infrastructure can fetch and build as dedicated unprivileged users while reserving package installation for root. Configure PORTS_PRIVSEP, writable object, distfile, and package directories, and the required narrowly scoped doas rules according to the current bsd.port.mk(5)
manual.
Do not copy an old doas.conf block. Build users, environment requirements, and ports infrastructure can change. Confirm the complete configuration with one small port before a long build.
Build and Install One Port #
With privilege separation configured, build the default package as the designated unprivileged builder and install the result as root:
cd /usr/ports/category/example
# Enter the verified port directory
make package
# Fetch, patch, configure, build, and create package files
doas make install
# Install the resulting package through the package tools
A small example is sysutils/tree. On a build host with the prerequisites above, remove an already-installed tree package before building the same package, then run:
cd /usr/ports/sysutils/tree
# Select the port
doas make install
# Build and install the package
tree /var/empty
# Confirm that the installed command works
Inspect dependencies with make show=RUN_DEPENDS and make show=BUILD_DEPENDS. These values are ports metadata, not a package list to pass to pkg_add.
For a documented flavor:
env FLAVOR="selected_flavor" make package
# Build the selected supported flavor
doas env FLAVOR="selected_flavor" make install
# Install the package built with the same flavor selection
Replace both placeholders. Preserve the same flavor environment for related build targets.
The ports framework uses _pfetch and _pbuild for configured privilege separation. Follow the current ports(7)
and bsd.port.mk(5)
guidance rather than adding broad doas rules from an old blog post.
Verify the Result #
Confirm that the installed package records the expected pkgpath and version:
pkg_info -S installed-package
# Display the package update signature
pkg_info -L installed-package
# Inspect the installed file list
Replace installed-package with the actual installed package name. Read any package installation messages and /usr/local/share/doc/pkg-readmes/ entry before enabling services.
Clean Build Objects #
After preserving required logs and package artifacts, clean the selected port and its dependencies according to ports(7) :
make clean=all
Confirm the current directory before running a clean target. Do not delete /usr/ports, distfiles, packages, or work directories recursively as a substitute for the infrastructure’s cleanup targets.
Maintain the Installed Package #
Once installed, the result is an OpenBSD package and should be tracked through package metadata. A locally built flavor may not have a compatible binary update on the configured mirror. Record the pkgpath, flavor, local patches, source branch, build date, and package artifact needed to reproduce it.
Do not use make update as a general replacement for pkg_add(1)
. Review the current ports caveats and rebuild in a controlled environment. For many packages or repeatable repositories, use dpb(1)
rather than looping over individual make invocations.
See Managing Software: Packages and Ports for routine package management and Update and Upgrade OpenBSD for base-system, firmware, package, and release updates.