Skip to main content
The pkg module manages packages on BSD systems (FreeBSD, OpenBSD, NetBSD) using either pkg or pkg_* commands.
BSD package names are case-sensitive.

Functions

packages

Install, remove, or update BSD packages.
from pyinfra.operations import pkg

pkg.packages(
    name="Install essential tools",
    packages=["vim", "git"],
)
packages
str | list[str]
List of packages to ensure.
present
bool
default:true
Whether the packages should be installed.
pkg_path
str
The PKG_PATH environment variable to set for package installation.
This operation will use pkg ... where available (FreeBSD) and the pkg_* variants elsewhere (OpenBSD, NetBSD).

pkg_path Configuration

By default, pkg_path is autogenerated as follows (tested/working for OpenBSD):
http://ftp.<OS>.org/pub/<OS>/<VERSION>/packages/<ARCH>/
OpenBSD’s official mirrors only hold the latest two versions of packages.
NetBSD and FreeBSD use their own directory structures, so the default won’t work. You’ll need to specify pkg_path manually.

Example

from pyinfra.operations import pkg

pkg.packages(
    name="Install Vim and Vim Addon Manager",
    packages=["vim-addon-manager", "vim"],
)

Common Use Cases

FreeBSD Package Installation

from pyinfra.operations import pkg

# FreeBSD uses modern 'pkg' command
pkg.packages(
    name="Install web server",
    packages=[
        "nginx",
        "postgresql15-server",
        "redis",
    ],
)

OpenBSD Package Installation

from pyinfra.operations import pkg

# OpenBSD with auto-generated PKG_PATH
pkg.packages(
    name="Install development tools",
    packages=[
        "git",
        "vim--no_x11",
        "python3",
    ],
)

OpenBSD with Custom PKG_PATH

from pyinfra.operations import pkg

# Specify custom package mirror
pkg.packages(
    name="Install packages from custom mirror",
    packages=["bash", "curl"],
    pkg_path="https://cdn.openbsd.org/pub/OpenBSD/7.3/packages/amd64/",
)

NetBSD Package Installation

from pyinfra.operations import pkg

# NetBSD requires explicit PKG_PATH
pkg.packages(
    name="Install NetBSD packages",
    packages=["git", "vim"],
    pkg_path="http://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/amd64/9.0/All",
)

Development Environment

from pyinfra.operations import pkg

pkg.packages(
    name="Install development tools",
    packages=[
        "git",
        "vim",
        "tmux",
        "bash",
        "curl",
        "wget",
    ],
)

Web Server Stack

from pyinfra.operations import pkg

pkg.packages(
    name="Install LAMP stack",
    packages=[
        "nginx",
        "php",
        "mysql-server",
    ],
)

BSD-Specific Tips

OpenBSD packages can have different flavors (build options):
from pyinfra.operations import pkg

# Install vim without X11 support
pkg.packages(
    name="Install vim without X11",
    packages=["vim--no_x11"],
)

# Install python with different version
pkg.packages(
    name="Install Python 3.11",
    packages=["python%3.11"],
)
To find the correct PKG_PATH for your system:OpenBSD:
# Check /etc/installurl or use:
http://ftp.openbsd.org/pub/OpenBSD/$(uname -r)/packages/$(uname -m)/
NetBSD:
http://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/$(uname -m)/$(uname -r)/All
FreeBSD:
# FreeBSD doesn't need PKG_PATH, uses pkg command
from pyinfra.operations import pkg

pkg.packages(
    name="Install packages",
    packages=["nginx"],
)
Get information about installed packages:
from pyinfra.operations import server

# FreeBSD
server.shell(
    name="Show package info",
    commands=["pkg info nginx"],
)

# OpenBSD/NetBSD
server.shell(
    name="Show package info",
    commands=["pkg_info nginx"],
)
Update package repositories:
from pyinfra.operations import server

# FreeBSD
server.shell(
    name="Update package database",
    commands=["pkg update"],
)

# OpenBSD doesn't have a separate update command
# NetBSD
server.shell(
    name="Update pkgin database",
    commands=["pkgin update"],  # if using pkgin
)
Search for available packages:
from pyinfra.operations import server

# FreeBSD
server.shell(
    name="Search for packages",
    commands=["pkg search nginx"],
)

# OpenBSD
server.shell(
    name="Search for packages",
    commands=["pkg_info -Q nginx"],
)

Platform Detection

The pkg operation automatically detects the platform and uses the appropriate command:
from pyinfra import host
from pyinfra.facts.server import Which

# Checks if 'pkg' command exists
is_pkg = host.get_fact(Which, command="pkg")

if is_pkg:
    # FreeBSD: uses "pkg install -y"
    # FreeBSD: uses "pkg delete -y"
else:
    # OpenBSD/NetBSD: uses "pkg_add"
    # OpenBSD/NetBSD: uses "pkg_delete"

Important Notes

Package names and flavors differ between BSD variants. Always check the specific distribution’s package repository for the correct package name.
OpenBSD does not have a latest flag equivalent - packages are always installed at the version available in the repository for your OS version.
For OpenBSD, if /etc/installurl exists and is properly configured, you don’t need to specify pkg_path.

Build docs developers (and LLMs) love