Keeping FreeBSD Up to Date with freebsd-update
How to patch the FreeBSD base system with freebsd-update, why it's separate from pkg upgrades, and how to automate security patch checks with cron.
17 January 2025 4 min read
FreeBSD splits its update story into two completely separate systems, and mixing them up is a common source of confusion. pkg updates the third-party software you’ve installed on top of the OS – we covered that in managing packages with pkg and the Ports Collection. freebsd-update is different: it patches the base system itself – the kernel, the standard userland utilities, and core libraries that ship as part of FreeBSD, not as packages. This post covers freebsd-update specifically.
What freebsd-update actually covers
freebsd-update fetches binary patches from FreeBSD’s official update servers and applies them to your installed base system. It’s how you get security fixes and errata patches without recompiling from source or reinstalling. It does not touch anything installed via pkg – your nginx, PostgreSQL, or Python installs are entirely outside its scope, and you’ll still need pkg update && pkg upgrade to keep those current.
You can also use freebsd-update to move between minor releases (e.g. 14.1 to 14.2), though that’s a heavier operation than routine patching and outside what we’re covering here – this post is about staying current within your existing release via security and errata patches.
Checking your current patch level
Before doing anything, check what you’re currently running:
freebsd-version -k
uname -a
freebsd-version -k shows the kernel’s version string, including any -pN patch level suffix (for example, 14.1-RELEASE-p5 means the fifth security/errata patch batch has been applied). uname -a shows what the currently running kernel reports, which can differ from freebsd-version -k immediately after a patch is installed but before you’ve rebooted – worth keeping in mind, since that mismatch is itself a signal that a reboot is pending.
Fetching and installing patches
The basic workflow is two commands. First, fetch available patches:
freebsd-update fetch
This downloads any patches that apply to your release and version, but doesn’t install anything yet – it just stages them locally so you can review what’s about to change. Then install them:
freebsd-update install
If there’s nothing staged, install will simply tell you there are no updates to install – that’s normal and means you’re already current.
Reboot when the kernel is patched
This is the detail that trips people up: if a patch touches the kernel, it isn’t actually running until you reboot. freebsd-update install replaces the files on disk, but the currently running kernel in memory is untouched until the next boot. If you only patch userland binaries and libraries, a reboot generally isn’t required – but for kernel security patches, it is.
After a kernel patch, plan a reboot:
shutdown -r now
On a production VPS, treat this like any other maintenance reboot – schedule it for a low-traffic window and confirm services come back up cleanly afterwards. You can re-check freebsd-version -k against uname -a post-reboot to confirm they now match.
Automating security patch checks with cron
freebsd-update has a dedicated cron subcommand designed specifically for scheduled, unattended checking. It’s worth understanding what it does and doesn’t do before wiring it up: freebsd-update cron checks for and downloads applicable patches, and emails root if any were found – it does not install them automatically. That’s a deliberate safety choice; applying kernel patches unattended and rebooting a production server without anyone reviewing what changed is generally not something you want on autopilot.
Add a crontab entry (as root, via crontab -e) to run it, say, once a day:
@daily root freebsd-update cron
Note that freebsd-update cron deliberately sleeps for a random interval (up to an hour) before actually checking, to spread load across FreeBSD’s update servers rather than everyone hitting them at exactly midnight – so don’t be surprised if it doesn’t run the instant the cron job fires.
Once patches have been fetched by the cron job, you can check whether anything is waiting to be applied with:
freebsd-update updatesready
and then run freebsd-update install yourself once you’ve had a chance to review what’s changed – ideally alongside a note in your calendar to reboot if it turns out to be a kernel patch.
A note on periodic(8)
FreeBSD’s periodic framework (the same system that runs your daily/weekly/monthly maintenance scripts and mails you the output) is a common place to also hook this in for visibility, but the crontab entry above calling freebsd-update cron directly is the standard, documented approach and is all you need for keeping on top of security patches.
Summary
freebsd-update fetch and freebsd-update install keep your FreeBSD base system patched – separately from pkg, which handles everything you’ve installed on top. Remember to reboot after a kernel patch, and consider a daily freebsd-update cron entry so you’re notified promptly when security patches land rather than finding out weeks later.