FreeBSD.software
Home/Blog/How to Update FreeBSD: System and Packages Guide
tutorial2026-03-29

How to Update FreeBSD: System and Packages Guide

Complete guide to updating FreeBSD. Covers freebsd-update for the base system, pkg upgrade for packages, major version upgrades, boot environments for safe rollback, and automating updates.

# How to Update FreeBSD: System and Packages Guide

Keeping a FreeBSD system up to date is the single most important task in system administration. Security patches, bug fixes, and performance improvements all arrive through updates. Miss them, and you are running a system with known vulnerabilities.

FreeBSD splits updates into two distinct tracks: the **base system** (kernel, userland, libraries) and **third-party packages** (everything installed via pkg or ports). Each track has its own tools, its own schedule, and its own failure modes. This guide covers both, from routine patch application to full major version upgrades, with real commands and practical rollback strategies.

If you are setting up a fresh server, start with our [FreeBSD VPS setup guide](/blog/freebsd-vps-setup/) first, then come back here to establish your update workflow.

Update Strategy Overview

Before running any update command, understand what you are updating and why.

**Base system updates** come from the FreeBSD project itself. They include:

- Kernel patches (security fixes, driver updates)

- Userland utilities (ls, cp, fetch, ssh, etc.)

- System libraries (libc, libz, libssl, etc.)

- Configuration file changes

**Package updates** come from the FreeBSD ports tree, compiled into binary packages. They include everything you installed with pkg install -- web servers, databases, programming languages, and their dependencies.

**When to update:**

- **Security advisories**: Immediately. FreeBSD publishes security advisories (SA) and errata notices (EN). Subscribe to freebsd-security-notifications@freebsd.org.

- **Patch-level updates** (e.g., 14.2-RELEASE-p1 to p2): Weekly or biweekly. These are low-risk.

- **Minor version upgrades** (e.g., 14.1 to 14.2): Within a month of release, after reading the release notes.

- **Major version upgrades** (e.g., 14.x to 15.0): Plan and test. These can break things.

- **Package updates**: Weekly on production, daily on development.

The golden rule: always update the base system first, then packages.

Updating the Base System with freebsd-update

The freebsd-update utility handles binary updates for RELEASE versions of FreeBSD. It downloads patches, verifies them cryptographically, and applies them to your running system.

Fetch and Install Security Patches

The basic two-step process:

sh

# Fetch available updates

freebsd-update fetch

Output looks like this:


Looking up update.FreeBSD.org mirrors... 3 mirrors found.

Fetching metadata signature for 14.2-RELEASE from update2.freebsd.org... done.

Fetching metadata index... done.

Inspecting system... done.

Preparing to download files... done.

The following files will be updated as part of updating to

14.2-RELEASE-p4:

/bin/freebsd-version

/lib/libc.so.7

/usr/lib/libssl.so.30

/usr/sbin/sshd

...

Review the list. Then apply:

sh

# Install fetched updates

freebsd-update install


Installing updates...

Restarting sshd after update... done.

If kernel files were updated, you need to reboot:

sh

# Check if a reboot is needed

freebsd-version -k # running kernel version

freebsd-version -r # installed release version

uname -r # currently booted kernel

If the versions differ, reboot:

sh

shutdown -r now

After rebooting, run freebsd-update install again. Some updates require a second pass to update userland components that depend on the new kernel.

Checking Your Current Patch Level

sh

freebsd-version


14.2-RELEASE-p4

The -p4 suffix indicates patch level 4. Compare this against the latest advisories on [freebsd.org/security/advisories](https://www.freebsd.org/security/advisories/) to confirm you are current.

Updating Packages with pkg

Third-party packages are managed separately from the base system. The pkg tool handles binary package management.

Update the Package Repository Catalog

sh

pkg update


Updating FreeBSD repository catalogue...

FreeBSD repository is up to date.

All repositories are up to date.

This fetches the latest package index. It does not install anything.

Upgrade Installed Packages

sh

pkg upgrade


Updating FreeBSD repository catalogue...

Checking for upgrades (42 candidates): 100%

Processing candidates (42 candidates): 100%

The following 38 package(s) will be affected (of 0 checked):

Installed packages to be UPGRADED:

curl: 8.9.1 -> 8.11.0

nginx: 1.26.1 -> 1.26.2

openssl: 3.3.1 -> 3.3.2

python311: 3.11.9 -> 3.11.11

...

Number of packages to be upgraded: 38

The process will require 12 MiB more space.

18 MiB to be downloaded.

Proceed with this action? [y/N]: y

Type y to proceed. Each package is downloaded, verified, and installed.

Dry Run Before Upgrading

To see what would change without actually changing anything:

sh

pkg upgrade -n

This is useful in scripts and before applying updates on production systems.

Clean Up After Upgrading

sh

# Remove packages that were installed as dependencies but are no longer needed

pkg autoremove


Checking for autoremovable packages... done.

The following 4 package(s) will be affected:

Installed packages to be REMOVED:

libiconv-1.17

libffi-3.4.6

...

Proceed with deinstalling these packages? [y/N]: y

Then clean the local package cache:

sh

# Remove old cached package files

pkg clean


The cleanup will free 847 MiB.

Proceed with cleaning the cache? [y/N]: y

For a deeper comparison of binary packages versus building from source, see our [pkg vs ports guide](/blog/freebsd-pkg-vs-ports/).

Locking Packages

If a specific package must stay at its current version (compatibility reasons, known regressions), lock it:

sh

# Prevent nginx from being upgraded

pkg lock nginx


nginx-1.26.1: lock this package? [y/N]: y

Locking nginx-1.26.1

To unlock later:

sh

pkg unlock nginx

List all locked packages:

sh

pkg lock -l

Major Version Upgrades

Major upgrades move you from one FreeBSD release to another. This is more involved than routine patching.

Minor Version Upgrade (e.g., 14.1 to 14.2)

sh

# Fetch upgrade files for the target release

freebsd-update -r 14.2-RELEASE upgrade


Looking up update.FreeBSD.org mirrors... 3 mirrors found.

Fetching metadata signature for 14.2-RELEASE from update1.freebsd.org... done.

Fetching metadata index... done.

...

The following files will be added as part of updating to 14.2-RELEASE:

/usr/lib/debug/boot/kernel/zfs.ko.debug

...

The following files will be updated as part of updating to 14.2-RELEASE:

...

To install the downloaded upgrades, run "freebsd-update install".

Then install in stages:

sh

# Stage 1: Install kernel updates

freebsd-update install

# Reboot into the new kernel

shutdown -r now

# Stage 2: Install userland updates (after reboot)

freebsd-update install

# Stage 3: Rebuild ports/packages, then run install one final time

pkg-static upgrade -f

freebsd-update install

Major Version Upgrade (e.g., 14.x to 15.0)

The process is identical, but the risk is higher. Configuration file merges are more likely. freebsd-update will present three-way merges for modified config files -- review each one carefully.

sh

freebsd-update -r 15.0-RELEASE upgrade

Before a major upgrade:

1. Read the release notes thoroughly.

2. Back up the entire system. A [ZFS snapshot](/blog/zfs-freebsd-guide/) is ideal.

3. Test the upgrade on a non-production system first.

4. Make a list of all installed packages (pkg info > /root/pkg-list-pre-upgrade.txt).

5. Plan for downtime.

After the upgrade completes and all stages of freebsd-update install are done:

sh

# Reinstall all packages for the new ABI

pkg-static install -f $(pkg query '%n' | tr '\n' ' ')

Using Boot Environments for Safe Updates

If your system uses ZFS (and it should -- see our [ZFS guide](/blog/zfs-freebsd-guide/)), boot environments let you snapshot the entire OS before an update and roll back instantly if something breaks.

Create a Boot Environment Before Updating

sh

# List existing boot environments

bectl list


BE Active Mountpoint Space Created

default NR / 3.42G 2025-09-15 10:22

Create a snapshot before updating:

sh

# Create a new boot environment as a safety net

bectl create pre-upgrade-14.2-p4

sh

# Verify it was created

bectl list


BE Active Mountpoint Space Created

default NR / 3.42G 2025-09-15 10:22

pre-upgrade-14.2-p4 - - 8K 2026-03-29 09:15

Now proceed with freebsd-update fetch install or pkg upgrade. If the update goes wrong:

Rolling Back

sh

# Activate the pre-update boot environment

bectl activate pre-upgrade-14.2-p4

# Reboot into the clean state

shutdown -r now

After rebooting, you are back to exactly the state before the update. No damage done. To remove a boot environment you no longer need:

sh

bectl destroy pre-upgrade-14.2-p4

Boot environments cost almost no disk space (ZFS copy-on-write), so create one before every significant change.

Handling Kernel Updates and Reboots

Not every update requires a reboot. Here is how to tell:

sh

# Compare booted kernel to installed kernel

BOOTED=$(uname -r)

INSTALLED=$(freebsd-version -k)

if [ "$BOOTED" != "$INSTALLED" ]; then

echo "Reboot required: running $BOOTED, installed $INSTALLED"

else

echo "No reboot needed"

fi

When a reboot is required:

1. Notify users or drain connections (if running a web server or database).

2. Stop services gracefully: service nginx stop, service postgresql stop.

3. Reboot: shutdown -r now.

4. After reboot, verify the new kernel is running: uname -r.

5. Run freebsd-update install again if prompted (second-stage userland updates).

6. Restart services and verify they are healthy.

For high-availability setups, update one node at a time behind a load balancer. See our [FreeBSD load balancing guide](/blog/freebsd-load-balancing/) for architecture details.

Checking for Security Vulnerabilities

Audit Installed Packages

sh

pkg audit -F


Fetching vuln.xml.xz: 100%

chromium-128.0.6613.137 is vulnerable:

chromium -- multiple vulnerabilities

CVE: CVE-2024-8636

WWW: https://vuxml.freebsd.org/freebsd/...

1 problem(s) in 1 installed package(s) found.

The -F flag fetches a fresh vulnerability database before scanning. Run this regularly -- daily via cron is ideal.

Intrusion Detection with freebsd-update

freebsd-update can verify the integrity of installed base system files:

sh

freebsd-update IDS

This compares every file in the base system against known-good hashes. Any modified file is reported. It is not a replacement for a full IDS like AIDE or OSSEC, but it catches tampering with core system binaries.


/etc/rc.conf: SHA256 hash mismatch # Expected: you edited this file

/usr/sbin/sshd: SHA256 hash mismatch # NOT expected: investigate immediately

Any unexpected mismatch on a binary file is a serious red flag.

Automating Updates

Using periodic.conf

FreeBSD's periodic system can fetch updates automatically. Edit /etc/periodic.conf:

sh

# /etc/periodic.conf

# Fetch base system updates (does NOT install them)

daily_freebsd_update_enable="YES"

# Audit packages for known vulnerabilities

daily_pkg_audit_enable="YES"

# Send output to root's email

daily_output="/var/log/daily.log"

This fetches updates daily but does not install them. You still apply manually after review.

Cron-Based Package Updates

For non-critical systems (development, staging), you can automate package upgrades:

sh

# /etc/cron.d/pkg-update

# Update packages every Sunday at 3 AM

0 3 * * 0 root /usr/sbin/pkg update -q && /usr/sbin/pkg upgrade -y -q >> /var/log/pkg-upgrade.log 2>&1

For production, never auto-install updates without testing. Instead, automate the fetch-and-notify step:

sh

#!/bin/sh

# /usr/local/bin/update-check.sh

# Fetch base system updates

freebsd-update fetch --not-running-from-cron | tail -1

# Check for package upgrades

UPGRADES=$(pkg upgrade -n 2>/dev/null | grep "Number of packages")

if [ -n "$UPGRADES" ]; then

echo "Package updates available: $UPGRADES" | \

mail -s "$(hostname): Updates Available" admin@example.com

fi

# Audit for vulnerabilities

VULNS=$(pkg audit -F 2>/dev/null | tail -1)

if echo "$VULNS" | grep -q "problem(s)"; then

echo "$VULNS" | mail -s "$(hostname): Vulnerable Packages" admin@example.com

fi

Add to cron:

sh

# Run update check daily at 6 AM

0 6 * * * root /usr/local/bin/update-check.sh

Updating Ports and Custom-Built Packages

If you build packages from the ports tree instead of using binary packages, the update process differs. For a full comparison of both approaches, see our [pkg vs ports guide](/blog/freebsd-pkg-vs-ports/).

Updating the Ports Tree

sh

# Using git (recommended as of FreeBSD 14+)

git -C /usr/ports pull

Or, if you used portsnap in the past (deprecated in FreeBSD 14):

sh

# Legacy method -- use git instead

portsnap fetch update

Rebuilding Ports with portmaster

sh

# Install portmaster if not already installed

pkg install portmaster

# Check for outdated ports

portmaster -L | grep "New version"

# Upgrade all outdated ports

portmaster -a

Rebuilding Ports with poudriere

For larger deployments, poudriere builds packages in a clean jail and serves them via a local repository. This is the professional approach:

sh

# Update the ports tree inside poudriere

poudriere ports -u -p default

# Build all packages in your list

poudriere bulk -j 14amd64 -p default -f /usr/local/etc/poudriere.d/pkglist

# Point your servers at the poudriere repo and run pkg upgrade

This guarantees reproducible, clean builds without polluting the host system.

Post-Update Checklist

After every update, run through this list before closing the maintenance window.

**1. Verify the system version:**

sh

freebsd-version

uname -r

**2. Check that all services are running:**

sh

service -e

This lists all enabled services. Compare against your expected list.

**3. Test critical applications:**

sh

# Web server responding?

curl -I http://localhost

# Database accepting connections?

psql -c "SELECT 1;" postgres

# SSH still working? (test from another terminal BEFORE closing your current session)

ssh user@your-server hostname

**4. Review system logs for errors:**

sh

# Check for post-boot errors

dmesg | grep -i error

# Check system messages

tail -100 /var/log/messages

# Check service-specific logs

tail -50 /var/log/nginx/error.log

**5. Verify package consistency:**

sh

# Check for broken shared library dependencies

pkg check -d -a


Checking all packages: 100%

If broken dependencies are found:

sh

# Reinstall packages with missing dependencies

pkg install -f

**6. Run a security audit:**

sh

pkg audit -F

**7. Clean up:**

sh

pkg autoremove

pkg clean -a

**8. Update your documentation.** Record the date, what was updated, and any issues encountered. Future-you will thank present-you.

Troubleshooting Failed Updates

freebsd-update Fails to Fetch


No mirrors remaining, giving up.

Check DNS resolution and network connectivity:

sh

host update.FreeBSD.org

fetch https://update.FreeBSD.org/

If your system is behind a proxy:

sh

export HTTP_PROXY=http://proxy.example.com:3128

freebsd-update fetch

freebsd-update Reports "No updates available" When There Should Be

Verify your release and architecture:

sh

uname -rp

Check /etc/freebsd-update.conf:

sh

grep -E "^(KeyPrint|ServerName|Components)" /etc/freebsd-update.conf

If you are running a CURRENT or STABLE branch, freebsd-update does not support it. You must build from source.

pkg upgrade Fails Mid-Way

If interrupted, the package database may be in an inconsistent state:

sh

# Force-update the repository catalog

pkg update -f

# Check database integrity

pkg check -B -a

# Retry the upgrade

pkg upgrade

If a specific package refuses to install due to conflicts:

sh

# Remove the conflicting package first

pkg delete

# Then upgrade

pkg upgrade

Shared Library Errors After Update

If applications crash with "Shared object not found":

sh

# Find which package owns the missing library

pkg which /usr/local/lib/libfoo.so.3

# Reinstall that package

pkg install -f

# Or force-reinstall everything (nuclear option)

pkg upgrade -f

Kernel Panic After Update

If the system fails to boot after a kernel update:

1. At the FreeBSD boot loader menu, press 2 to select "Boot Single User."

2. Mount the filesystem: mount -u / then mount -a.

3. If using boot environments: bectl activate and reboot.

4. If not using boot environments: freebsd-update rollback will undo the last update.

sh

# Roll back the last freebsd-update

freebsd-update rollback

This restores the previous kernel and userland. Always create boot environments or ZFS snapshots before updating to make this situation trivial to recover from.

Frequently Asked Questions

How often should I update my FreeBSD server?

Apply security patches within 24-48 hours of an advisory. Run pkg upgrade weekly on production systems. Check for updates daily with pkg audit -F and freebsd-update fetch. Schedule major version upgrades during planned maintenance windows, typically within a month of a new release reaching maturity.

Can I update FreeBSD without rebooting?

Yes, for most package updates and some base system patches (userland-only fixes). Kernel updates always require a reboot. After running freebsd-update install, compare uname -r with freebsd-version -k. If they match, no reboot is needed. If they differ, a reboot is required to load the new kernel.

What is the difference between freebsd-update and pkg upgrade?

freebsd-update handles the **base operating system** -- the kernel, core utilities, and system libraries shipped by the FreeBSD project. pkg upgrade handles **third-party packages** -- everything you installed after the OS (nginx, Python, PostgreSQL, etc.). They are completely independent tools managing separate sets of files. Always run freebsd-update first, then pkg upgrade.

How do I upgrade from FreeBSD 14 to FreeBSD 15?

Use freebsd-update -r 15.0-RELEASE upgrade. This is a multi-stage process: fetch the upgrade, install kernel updates, reboot, install userland updates, rebuild all packages with pkg-static upgrade -f, and run a final freebsd-update install. Read the release notes first, back up with a ZFS snapshot or boot environment, and test on a non-production system. Expect configuration file merge prompts for files you have customized.

Is it safe to run pkg upgrade on a production server?

Binary packages from the official FreeBSD repository are well-tested, but any update can introduce regressions. Best practices: run pkg upgrade -n first to preview changes, create a boot environment with bectl create before upgrading, test the upgrade on staging first, and keep a rollback plan. Lock critical packages with pkg lock if you need version stability.

How do I know if my FreeBSD system has known vulnerabilities?

Run pkg audit -F to check all installed packages against the FreeBSD VuXML vulnerability database. For the base system, subscribe to the freebsd-security-notifications mailing list and compare your patch level (freebsd-version) against the latest advisories. Automate both checks via daily_pkg_audit_enable="YES" in /etc/periodic.conf.

What should I do if freebsd-update rollback does not fix a broken update?

If freebsd-update rollback fails or is insufficient, boot into single-user mode from the loader menu. If you created a boot environment beforehand, activate it with bectl activate and reboot. If you have a ZFS snapshot, roll back the dataset. As a last resort, boot from a FreeBSD installer USB, mount your filesystems, and manually restore from backup. This scenario is exactly why boot environments and regular backups are non-negotiable.

Summary

Keeping FreeBSD updated is a disciplined process, not a single command. The workflow looks like this:

1. Create a boot environment (bectl create).

2. Fetch and install base system patches (freebsd-update fetch install).

3. Reboot if kernel files changed.

4. Run freebsd-update install again after reboot.

5. Update packages (pkg update && pkg upgrade).

6. Audit for vulnerabilities (pkg audit -F).

7. Verify services, check logs, test applications.

8. Clean up (pkg autoremove && pkg clean).

Do this consistently, and your FreeBSD systems will stay secure, stable, and predictable. Skip it, and you will learn the hard way why update hygiene matters.