OpenBSD manages the base system and additional software separately. The base system belongs to the OpenBSD release; additional software is added through the package system. Official packages are cryptographically verified during installation.
System Configuration explains the basic configuration after installation. This article covers installing, querying, removing, and updating software with pkg_add, pkg_info, and pkg_delete.
Base System and Packages
The base system is not a collection of special packages, but part of the OpenBSD release. It includes the kernel, system utilities, libraries, daemons, documentation, and—depending on the selected installation—additional sets such as compilers or X11 components.
Software outside the base system is installed as a package:
/usr/bin/vi # Base system editor (included)
/usr/local/bin/vim # vim package (after installation)
/usr/sbin/httpd # Base system HTTP server (included)
/usr/local/sbin/nginx # nginx package (after installation)
Package files are located primarily under /usr/local. Depending on the package, files may also be added at other designated locations—for example, rc scripts under /etc/rc.d or runtime data under /var. OpenBSD records the installed package state under /var/db/pkg. The separation between the base system and packages is therefore an administrative boundary, not an absolute filesystem boundary.
The update strategy reflects this separation:
- sysupgrade updates the base system
- pkg_add -u updates installed packages
- No mixing of the two systems
base*.tgz, comp*.tgz, man*.tgz, and game*.tgz sets form the base system. Packages are installed later via pkg_add.
pkg_add - Installing Software
The pkg_add tool installs software from OpenBSD repositories. The installation downloads packages, verifies signatures, and installs dependencies automatically.
Basic Installation
Install a package:
$ doas pkg_add nginx
quirks-7.194 signed on 2026-06-10T19:46:25Z
nginx-1.30.2:bzip2-1.0.8p0: ok
nginx-1.30.2:pcre2-10.44: ok
nginx-1.30.2: ok
The following new rcscripts were installed: /etc/rc.d/nginx
See rcctl(8) for details.
New and changed readme(s):
/usr/local/share/doc/pkg-readmes/nginx
quirks contains special rules and compatibility knowledge for the package tools and is kept current by pkg_add. Dependencies such as bzip2 and pcre2 are installed automatically. The message about rcscripts shows the new service; details follow in the planned article Services and Daemons.
New and changed readme(s) points to package-specific notes under /usr/local/share/doc/pkg-readmes/.
Package with prompts:
$ doas pkg_add vim
quirks-7.194 signed on 2026-06-10T19:46:25Z
Ambiguous: choose package for vim
a 0: <None>
1: vim-9.2.357
2: vim-9.2.357-gtk3
3: vim-9.2.357-gtk3-lua
4: vim-9.2.357-gtk3-perl-python3-ruby
5: vim-9.2.357-gtk3-python3
6: vim-9.2.357-lua
7: vim-9.2.357-perl-python3-ruby
8: vim-9.2.357-python3
9: vim-9.2.357-ruby
Your choice: 1
vim-9.2.357:libsodium-1.0.22: ok
vim-9.2.357:libiconv-1.19: ok
vim-9.2.357:gettext-runtime-1.0: ok
vim-9.2.357: ok
Several variants exist—with different feature sets (GTK3 GUI, Lua, Python3, Ruby) or without X11 for servers. Selection is interactive or can be made using an explicit package name:
$ doas pkg_add vim-9.2.357-lua
Package Search
Search available packages:
$ pkg_info -Q rsync
debug-rsync-3.4.4
debug-rsync-3.4.4-minimal
rsync-3.4.4
rsync-3.4.4-minimal
The -Q option searches package names. Substring searches work—py, python, and python3 find corresponding packages.
Debug variants contain additional symbols for debugging and are not relevant for normal operation.
Detailed package information:
$ pkg_info -Q nginx
nginx-1.30.2 (installed)
nginx-cache_purge-1.30.2
nginx-headers-more-1.30.2
nginx-lua-1.30.2
nginx-stream-1.30.2
[... additional module variants ...]
The “(installed)” suffix identifies packages that are already installed.
Detailed information about a package is provided by pkg_info without the -Q option—see pkg_info - Listing Installed Software.
Installing Dependencies Automatically
The package manager resolves dependencies automatically:
$ doas pkg_add mariadb-server
quirks-7.194 signed on 2026-06-10T19:46:25Z
mariadb-server-11.4.10p0v1:lz4-1.10.0: ok
mariadb-server-11.4.10p0v1:xz-5.8.3: ok
mariadb-server-11.4.10p0v1:zstd-1.5.7p0: ok
mariadb-server-11.4.10p0v1:mariadb-client-11.4.10p0v1: ok
mariadb-server-11.4.10p0v1:coreutils-9.10: ok
mariadb-server-11.4.10p0v1:p5-DBI-1.648: ok
mariadb-server-11.4.10p0v1:p5-DBD-MariaDB-1.23: ok
mariadb-server-11.4.10p0v1:curl-8.20.0: ok
[... additional dependencies ...]
mariadb-server-11.4.10p0v1: ok
Running tags: ok
The following new rcscripts were installed: /etc/rc.d/mysqld
See rcctl(8) for details.
New and changed readme(s):
/usr/local/share/doc/pkg-readmes/mariadb-server
pkg_add determines the declared dependencies and installs any missing dependencies. Directly requested packages are considered manually installed; packages installed solely as dependencies are considered automatically installed. This distinction becomes important when cleaning up later with pkg_delete -a.
README notes under /usr/local/share/doc/pkg-readmes/ should be read before putting the software into operation.
Multiple Packages at Once
Install a list:
$ doas pkg_add git htop rsync curl
quirks-7.194 signed on 2026-06-10T19:46:25Z
git-2.53.0:cvsps-2.1p3: ok
git-2.53.0:gitwrapper-0.125: ok
git-2.53.0:p5-Error-0.17030: ok
git-2.53.0:p5-Time-TimeDate-2.33: ok
git-2.53.0:p5-Mail-Tools-2.21p0: ok
git-2.53.0: ok
htop-3.4.1:libb2-0.98.1v0: ok
htop-3.4.1:sqlite3-3.51.3: ok
htop-3.4.1:python-3.13.13: ok
[... additional dependencies ...]
htop-3.4.1: ok
Ambiguous: choose package for rsync
a 0: <None>
1: rsync-3.4.4
2: rsync-3.4.4-minimal
Your choice: 2
rsync-3.4.4-minimal: ok
Running tags: ok
The following new rcscripts were installed: /etc/rc.d/gitdaemon /etc/rc.d/rsyncd
See rcctl(8) for details.
New and changed readme(s):
/usr/local/share/doc/pkg-readmes/git
/usr/local/share/doc/pkg-readmes/glib2
Matching packages that are already installed do not need to be installed again. When multiple matching variants exist, a selection may be required. An error does not trigger a global rollback: packages or dependencies that were already installed successfully remain installed.
doas for privilege management. Regular users can install packages only with an appropriate doas.conf rule.
Repository Structure
OpenBSD uses official mirrors for package distribution. The mirror URL is read automatically from /etc/installurl:
$ cat /etc/installurl
https://cdn.openbsd.org/pub/OpenBSD
This file is created during installation using the selected installation server. It can be changed manually if a different mirror is to be used.
Mirror List
Official mirrors are documented on the OpenBSD website: https://www.openbsd.org/ftp.html ↗
German mirrors (selection):
https://ftp.spline.de/pub/OpenBSD/ # Berlin
https://ftp.halifax.rwth-aachen.de/pub/OpenBSD/ # Aachen
https://artfiles.org/openbsd/ # Hamburg
https://ftp.hostserver.de/pub/OpenBSD/ # Frankfurt
https://mirror.junda.nl/pub/OpenBSD/ # Falkenstein
Change the mirror:
$ echo "https://ftp.hostserver.de/pub/OpenBSD" | doas tee /etc/installurl
https://ftp.hostserver.de/pub/OpenBSD
$ cat /etc/installurl
https://ftp.hostserver.de/pub/OpenBSD
The pipe with tee writes the URL to the file with root privileges. The next package installation uses the new mirror. No cache clearing or system restart is necessary.
Package Structure in the Repository
Packages are located under snapshots or the release version number:
https://cdn.openbsd.org/pub/OpenBSD/7.9/packages/amd64/
The URL components:
- 7.9 - OpenBSD version (Current Release)
- packages - Binary packages (vs. sets)
- amd64 - Architecture (Intel/AMD 64-bit)
Snapshots use more current packages:
https://cdn.openbsd.org/pub/OpenBSD/snapshots/packages/amd64/
Snapshot packages belong to the snapshot branch and must be used together with a matching snapshot base system. Release packages and snapshot packages should not be mixed.
Signature Verification
Official packages carry a cryptographic signature. The package tools automatically verify this signature during installation using the appropriate public keys from /etc/signify. The verification ensures that the package comes from the expected signed source and has not been modified since it was signed.
Automatic Verification
Signature verification happens transparently:
$ doas pkg_add nginx
quirks-7.194 signed on 2026-06-10T19:46:25Z
nginx-1.30.2: ok
The visible signed on... line belongs to quirks here; not every package verification produces a separate line like this.
During normal operation, pkg_add does not accept packages without a trusted signature. However, explicitly provided exceptions exist for local or unsigned packages that are deliberately treated as trusted.
A valid signature proves origin and integrity, not the audit status of the contents. Because packages can perform actions with system privileges during installation, a trusted source remains essential.
Public Keys
Signature verification uses public keys from /etc/signify:
$ ls /etc/signify
openbsd-72-base.pub openbsd-75-base.pub openbsd-78-base.pub
openbsd-72-fw.pub openbsd-75-fw.pub openbsd-78-fw.pub
openbsd-72-pkg.pub openbsd-75-pkg.pub openbsd-78-pkg.pub
openbsd-72-syspatch.pub openbsd-75-syspatch.pub openbsd-78-syspatch.pub
[... older release versions ...]
openbsd-79-base.pub openbsd-80-base.pub
openbsd-79-fw.pub openbsd-80-fw.pub
openbsd-79-pkg.pub openbsd-80-pkg.pub
openbsd-79-syspatch.pub openbsd-80-syspatch.pub
The keys are release-specific:
- base.pub - Base system updates
- pkg.pub - Package signatures
- fw.pub - Firmware updates
- syspatch.pub - Security patches
OpenBSD releases include the keys for the next release in addition to the current ones. The existing openbsd-80-* keys therefore enable verification of correspondingly signed 8.0 artifacts and continue the chain of trust during an upgrade.
The presence of older keys does not mean that OpenBSD supports system downgrades.
Trust Model
The public keys under /etc/signify belong to the base system. For release files such as bsd.rd, SHA256.sig is verified with the appropriate base.pub key; the checksums it contains then verify the release files.
Packages use their own signature and the appropriate pkg.pub key. pkg_add performs this verification before installation.
Three different terms therefore need to be distinguished:
- Release signature: signed checksums for release artifacts
- Package signature: cryptographic signature of a package archive
- Update signature: technical identifier of a package used by the update logic; see
pkg_info -S
The keys enable verification of the corresponding artifacts; supported upgrade paths are independent of them.
pkg_info - Listing Installed Software
The pkg_info tool displays package information. Without a package name, it lists installed packages; with a name, it can also provide information about an available package from the repository.
All Installed Packages
List all installed packages:
$ pkg_info
bzip2-1.0.8p0 block-sorting file compressor, unencumbered
coreutils-9.10 file, shell and text manipulation utilities
curl-8.20.0 transfer files with FTP, HTTP, HTTPS, etc.
git-2.53.0 distributed version control system
htop-3.4.1 interactive process viewer
mariadb-client-11.4.10p0v1 multithreaded SQL database (client)
mariadb-server-11.4.10p0v1 multithreaded SQL database (server)
nginx-1.30.2 robust and small HTTP server and mail proxy server
python-3.13.13 interpreted object-oriented programming language
rsync-3.4.4-minimal mirroring/synchronization over low bandwidth links
vim-9.2.357 vi clone with many additional features
[... additional installed packages ...]
The output shows package names, versions, and short descriptions. Dependencies (such as libiconv and p5-* modules) appear as well.
Package Details
Detailed information about a package:
$ pkg_info nginx-1.30.2
Information for inst:nginx-1.30.2
Comment:
robust and small HTTP server and mail proxy server
Description:
This is the stable branch of nginx, as distributed by nginx.org.
nginx provides FastCGI and reverse HTTP proxying, with or without caching,
including simple load balancing and fault tolerance.
It has a modular architecture. Filters include gzipping, byte ranges,
chunked responses, and SSI. Multiple SSI inclusions within a single page
can be processed in parallel if they are handled by FastCGI or proxied
servers. SSL and TLS SNI are supported.
Maintainer: Robert Nagy <robert@openbsd.org>
WWW: https://nginx.org/
The output contains:
- Comment - Purpose of the package
- Description - Description
- Maintainer - Responsible port maintainer
- WWW - Upstream project URL
Package Size
Disk space used by an installed package:
$ pkg_info -s nginx
Information for inst:nginx-1.30.2
Size: 1395276
The size is given in bytes (approximately 1.4 MB here).
Update Signature
Display the update signature of an installed package:
$ pkg_info -S nginx
Information for inst:nginx-1.30.2
Signature: nginx-1.30.2,15,@pcre2-10.44,c.103.0,crypto.57.2,pcre2-8.0.7,ssl.60.2,z.7.2
pkg_info -S does not show a cryptographic signature, but the update signature: an identifier composed of the package version, runtime dependencies, and required shared-library versions. The package tools use it when selecting updates.
Listing Dependencies
Dependencies of an installed package:
$ pkg_info -f postgresql-server | grep @depend
@depend databases/postgresql,-main:postgresql-client-=18.4:postgresql-client-18.4
@depend textproc/icu4c,-main:icu4c-*:icu4c-78.3v0
@depend textproc/libxml:libxml-*:libxml-2.15.3
The package requires postgresql-client in the exact version (=18.4), and icu4c and libxml in any current version (-*).
Which packages require a specific package:
$ pkg_info -R mariadb-client
Information for inst:mariadb-client-11.4.10p0v1
Required by:
mariadb-server-11.4.10p0v1
p5-DBD-MariaDB-1.23
The output lists all packages that have mariadb-client as a dependency. Useful before uninstalling—it shows affected packages.
Files Belonging to a Package
List all files belonging to a package:
$ pkg_info -L nginx
Information for inst:nginx-1.30.2
Files:
/etc/rc.d/nginx
/usr/local/sbin/nginx
/usr/local/man/man8/nginx.8
/usr/local/share/nginx/nginx.conf
/usr/local/share/nginx/html/index.html
/usr/local/share/doc/pkg-readmes/nginx
[... additional files ...]
Shows all installed files, configurations, and documentation. Useful for checking where a package places files.
Mapping a File to a Package
Find out which package installed a file:
$ pkg_info -E /usr/local/bin/vim
/usr/local/bin/vim: vim-9.2.357
vim-9.2.357 vi clone with many additional features
The -E option searches for an exact path. It works only for files that are already installed.
The output shows the package name and description. Useful for unknown binaries or configuration files.
pkg_delete - Removing Software
The pkg_delete tool removes installed packages, including all their files. Configuration files can optionally be retained.
Removing a Single Package
Uninstall a package:
$ doas pkg_delete nginx
nginx-1.30.2: ok
Read shared items: ok
pkg_delete removes files based on the registered package state. Using stored checksums, it detects locally modified files and normally leaves them in place. Important configurations should still be backed up independently. Read shared items is part of checking shared package components.
Dependency Check
Uninstall a package with dependencies:
$ doas pkg_delete mariadb-client
can't delete mariadb-client-11.4.10p0v1 without deleting mariadb-server-11.4.10p0v1 p5-DBD-MariaDB-1.23
Delete them as well ? [y/N/a] a
p5-DBD-MariaDB-1.23:mariadb-server-11.4.10p0v1: ok
p5-DBD-MariaDB-1.23: ok
mariadb-client-11.4.10p0v1: ok
Read shared items: ok
--- -mariadb-server-11.4.10p0v1 -------------------
You should also run /usr/sbin/userdel _mysql
You should also run /usr/sbin/groupdel _mysql
The message shows dependent packages and asks whether they should be removed as well:
- y - Yes, delete these packages (if further conflicts occur, it asks again)
- N - No, abort without changes (default)
- a - All, automatically answer “yes” to these and all further conflicts
During normal removal, created system users or groups remain in place; the output lists the necessary cleanup steps. With pkg_delete -c, registered configuration files, users, and groups can also be removed.
Cleaning Up Orphaned Dependencies
Automatically installed dependencies remain after packages are uninstalled. Remove them with:
$ doas pkg_delete -a
p5-Clone-0.47:p5-DBI-1.648: ok
p5-Clone-0.47:p5-SQL-Statement-1.414: ok
p5-Clone-0.47: ok
lua-5.1.5p8:luajit-2.1.1772619647: ok
lua-5.1.5p8: ok
lzo2-2.10p2: ok
coreutils-9.10: ok
p5-Net-Daemon-0.49:p5-PlRPC-0.2020p0: ok
p5-Net-Daemon-0.49: ok
p5-Params-Util-1.102: ok
libxml-2.15.3: ok
findutils-4.10.0p0: ok
snappy-1.1.10p2: ok
p5-MLDBM-2.05p0: ok
p5-FreezeThaw-0.5001p0: ok
p5-Math-Base-Convert-0.11p0: ok
zstd-1.5.7p0: ok
lz4-1.10.0: ok
p5-Module-Runtime-0.018: ok
Running tags: ok
Read shared items: ok
--- -libxml-2.15.3 -------------------
You should also remove /var/db/xmlcatalog
pkg_delete -a removes automatically installed packages that are no longer required; manually installed packages remain installed. A package installed directly with pkg_add htop is considered manually installed, whereas pkg_add -a htop does not mark it as manually installed.
Some packages leave databases or catalog files behind that must be removed separately.
Updates and System Maintenance
OpenBSD distinguishes between base system updates and package updates. Both are handled separately using different tools.
Package Updates
Update all installed packages:
$ doas pkg_add -u
quirks-7.194 signed on 2026-06-10T19:46:25Z
The command checks quirks, then all installed packages. If no updates are available, it exits without further output.
If updates are available, they are installed automatically:
$ doas pkg_add -u
quirks-7.147 signed on 2025-12-14T12:31:29Z
nginx-1.26.3->1.28.0p1: ok
vim-9.1.1650->9.1.1706-no_x11: ok
(Example from OpenBSD 7.8 — version numbers and package names vary by release)
Update a single package:
$ doas pkg_add -u vim
The specified package and required dependencies are checked for suitable updates. In the process, pkg_add replaces the installed package with an appropriate successor in a controlled manner and takes the dependency graph into account.
Base System Updates
List available patches without installing them:
$ doas syspatch -c
002_smtpd
003_vmd
syspatch -c is also suitable for cron — it produces output only when patches are pending.
Install patches:
$ doas syspatch
Get/Verify syspatch79-002_smtpd.tgz 100% |***...***| 313 KB 00:00
Installing patch 002_smtpd
Get/Verify syspatch79-003_vmd.tgz 100% |***...***| 114 KB 00:00
Installing patch 003_vmd
Errata can be reviewed under /var/syspatch
The patches are downloaded, verified, and installed. For kernel patches, reboot to load the new kernel appears; the new kernel is not used until after a reboot. Userland files are replaced without a system reboot, but depending on the patch, running processes may require the affected service to be restarted.
Display installed patches:
$ doas syspatch -l
002_smtpd
003_vmd
System Upgrade Between Major Releases
OpenBSD provides several methods for major-release upgrades (7.8 → 7.9). The choice depends on the requirements for control and automation.
Automatic Upgrade with sysupgrade
The simplest method for system upgrades:
$ doas sysupgrade
sysupgrade downloads and verifies the files for the new release and prepares the automated upgrade run. After the reboot, the installer performs the upgrade and starts the new system.
After the reboot, continue with After the Upgrade.
Important: sysupgrade performs the upgrade with all installation sets, regardless of which sets were selected during the original installation.
If you want to retain a deliberately reduced set selection, you can instead perform an interactive upgrade using bsd.rd.
Interactive Upgrade Using bsd.rd
The interactive upgrade allows you to select the sets yourself and is therefore suitable when a deliberately reduced installation should be retained.
Preparation
1. Download the installer kernel and signature file:
The files are located on the OpenBSD mirrors. For amd64 systems:
$ cd /tmp
$ ftp https://cdn.openbsd.org/pub/OpenBSD/7.9/amd64/bsd.rd
$ ftp https://cdn.openbsd.org/pub/OpenBSD/7.9/amd64/SHA256.sig
For other architectures, select the appropriate platform (arm64, i386, etc.). The complete list of available architectures can be found at:
https://cdn.openbsd.org/pub/OpenBSD/7.9/ ↗
2. Verify bsd.rd:
The signature key for 7.9 is already present on the running system:
$ cd /tmp
$ signify -C -p /etc/signify/openbsd-79-base.pub -x SHA256.sig bsd.rd
Signature Verified
bsd.rd: OK
Continue only if verification succeeds. Failed verification indicates manipulated or corrupted files.
3. Copy the installer kernel to the root file system:
$ doas cp /tmp/bsd.rd /bsd.rd
Performing the Upgrade
Restart the system and load the installer kernel at the boot prompt:
boot> boot /bsd.rd
The OpenBSD installer starts and asks for the desired action. Select (U)pgrade for a system upgrade.
Set Selection
The installer guides you through familiar steps — keyboard layout, root disk, mirror selection. The process corresponds to the installation dialog; see Installation and First Steps. The relevant step is set selection:
Select sets by entering a set name, a file name pattern or 'all'.
De-select sets by prepending a '-', e.g.: '-game*'. Selected sets are
labelled '[X]'.
[X] bsd [X] base79.tgz [X] game79.tgz [X] xfont79.tgz
[X] bsd.mp [X] comp79.tgz [X] xbase79.tgz [X] xserv79.tgz
[X] bsd.rd [X] man79.tgz [X] xshare79.tgz
Set name(s)? (or 'abort' or 'done') [done]
[X] marks sets that will be installed, [ ] marks skipped sets.
For minimal server installations, deselect X11 and Games:
Set name(s)? -g* -x*
The sets change from [X] to [ ]. Confirm with done and the upgrade starts.
The installer downloads only the selected sets, verifies them, and installs them. This keeps the installed software scope limited to the deliberately selected sets.
After the Upgrade
On the first boot, OpenBSD processes changes to the base system configuration with sysmerge. If unresolved conflicts remain, a manual run may subsequently be required:
$ doas sysmerge
After a release upgrade, the release-specific upgrade notes for the new OpenBSD version must also be followed. These may include changed configurations, old files that need to be removed, or special package migrations.
The installed packages are then brought to the appropriate state for the new system:
$ doas pkg_add -u
quirks-7.147->7.194: ok
curl-8.16.0->8.20.0: ok
curl-8.20.0:ngtcp2-1.16.0->1.22.1: ok
python-3.12.11->3.13.13 forward dependencies:
| Dependency of py3-packaging-25.0 on python->=3.12,<3.13 doesn't match
| Dependency of glib2-2.84.4 on python->=3.12,<3.13 doesn't match
Merging py3-packaging-25.0->26.0 (ok)
Merging glib2-2.84.4->2.86.5 (ok)
[... additional updates ...]
vim-9.1.1706-no_x11->9.2.357: ok
Running tags: ok
Binary patches for the running release are managed independently with syspatch, as described in the section Binary Patches with syspatch.
Clean up packages that are no longer required:
During updates, old shared libraries may be retained in .libs-* stub packages as long as other packages still require them. These are not leftover files, but deliberately retained compatibility packages.
$ doas pkg_delete -a
.libs-libsodium-1.0.20: ok
.libs-python-3.12.11: ok
pkg_delete -a removes such compatibility packages only when they are no longer required.
Manual Upgrade
OpenBSD also documents a fully manual upgrade procedure. It provides extensive control but is more error-prone and therefore does not belong in the normal workflow of this fundamentals article.
The complete procedure can be found in the separate Manual System Upgrade article (planned).
Comparison of Methods:
- sysupgrade: automated standard method; upgrade with all sets
- Interactive upgrade using bsd.rd: installer-based upgrade method with custom set selection
- Manual upgrade: largely manual procedure for special requirements; higher risk of errors
For remote or critical systems, an upgrade procedure should be tested beforehand on a comparable system.
Information Used
This guide applies to:
- OpenBSD: 7.8, 7.9
- Architecture: amd64 (primarily); the general concepts apply to all platforms
- Context: Server and desktop installation
- As of: August 2026
The next article covers Security Architecture — pledge, unveil, and other security mechanisms of the system.