Setup Local FreeBSD SUS (Software Update Server)

Why I Started Building a FreeBSD SUS?

If you have many FreeBSD servers, as I do, you know this problem well.
When you run updates, every server goes to the internet and downloads the same files again and again. This uses a lot of bandwidth. Sometimes your network becomes slow or stops working for other tasks.

Windows has a tool called WSUS (Windows Software Update Server).
WSUS lets you download all updates to one server and then share them with all computers on your network. This saves time and bandwidth.

I wanted something similar for FreeBSD.
So I started building my own FreeBSD SUS.
This is not a full update system yet, but it is the first step: a local server that stores FreeBSD system files. Your FreeBSD machines can install or update from your LAN instead of the Internet.

This guide shows how I built it.

Section 1: ZFS Setup for the FreeBSD SUS

To start building the FreeBSD SUS, we need a clean place to store all system files. I use ZFS because it is fast, safe, and easy to manage. My ZFS pool is named glacer, so I keep everything inside it.

We will store all FreeBSD files in:

/glacer/srv/freebsd/

This folder will hold two versions:

  • FreeBSD 15‑STABLE
  • FreeBSD 16‑CURRENT

Each version gets its own directory. This keeps everything clean and simple.

1.1 Create ZFS Datasets

Run these commands to create the folders inside the ZFS pool:

root@OF:/glacer # zfs create glacer/freebsd
root@OF:/glacer # zfs create glacer/freebsd/15
root@OF:/glacer # zfs create glacer/freebsd/15/amd64
root@OF:/glacer # zfs create glacer/freebsd/16-CURRENT
root@OF:/glacer # zfs create glacer/freebsd/16-CURRENT/amd64

These datasets will hold the system files for each FreeBSD version.

1.2 Set the Mountpoints

Now we tell ZFS where these datasets should appear in the filesystem:

root@OF:/glacer # zfs set mountpoint=/glacer/srv/freebsd glacer/freebsd
zfs set mountpoint=/glacer/srv/freebsd/16-CURRENT/amd64 glacer/freebsd/16-CURRENT/amd64
root@OF:/glacer # zfs set mountpoint=/glacer/srv/freebsd/15 glacer/freebsd/15
root@OF:/glacer # zfs set mountpoint=/glacer/srv/freebsd/15/amd64 glacer/freebsd/15/amd64
root@OF:/glacer # zfs set mountpoint=/glacer/srv/freebsd/16-CURRENT glacer/freebsd/16-CURRENT
root@OF:/glacer # zfs set mountpoint=/glacer/srv/freebsd/16-CURRENT/amd64 glacer/freebsd/16-CURRENT/amd64
root@OF:/glacer #

After this, your folder structure will look like:

root@OF:/glacer # ls -l srv/freebsd/
total 1
drwxr-xr-x  3 root wheel 3 Mar 16 11:28 15
drwxr-xr-x  3 root wheel 3 Mar 16 11:28 16-CURRENT
root@OF:/glacer #

This is where we will place the FreeBSD system files.

1.3 ZFS Settings (Simple and Safe)

These settings help ZFS work better with large files:

root@OF:/glacer # zfs set compression=zstd glacer/freebsd
root@OF:/glacer # zfs set atime=off glacer/freebsd
root@OF:/glacer # zfs set recordsize=1M glacer/freebsd
  • compression=zstd → saves space
  • atime=off → fewer writes
  • recordsize=1M → better for big files like base.txz

Do not use dedupe. It uses a lot of RAM and does not help with compressed files.

Section 2: Downloading FreeBSD Files

Now that the ZFS folders are ready, we can download the FreeBSD system files. These files are needed for installing or updating FreeBSD from your local network. We will download two versions:

  • FreeBSD 15‑STABLE
  • FreeBSD 16‑CURRENT

Each version has its own folder. This keeps everything clean and easy to manage.

2.1 Download FreeBSD 15‑STABLE Files

Go to the folder for FreeBSD 15:

root@OF:/glacer # cd /glacer/srv/freebsd/15/amd64
root@OF:/glacer/srv/freebsd/15/amd64 #

Now download the system files:

root@OF:/glacer/srv/freebsd/15/amd64 # fetch https://download.freebsd.org/snapshots/amd64/15.0-STABLE/base.txz
fetch https://download.freebsd.org/snapshots/amd64/15.0-STABLE/src.txz
base.txz                                               156 MB 8259 kBps    20s
root@OF:/glacer/srv/freebsd/15/amd64 # fetch https://download.freebsd.org/snapshots/amd64/15.0-STABLE/kernel.txz
kernel.txz                                              42 MB 7893 kBps    06s
root@OF:/glacer/srv/freebsd/15/amd64 # fetch https://download.freebsd.org/snapshots/amd64/15.0-STABLE/MANIFEST
MANIFEST                                              1044  B 1359 kBps    00s
root@OF:/glacer/srv/freebsd/15/amd64 # fetch https://download.freebsd.org/snapshots/amd64/15.0-STABLE/src.txz
src.txz                                                239 MB 8406 kBps    29s

These files are the same ones the FreeBSD installer uses. They are now stored on your LAN.

2.2 Download FreeBSD 16‑CURRENT Files

Go to the folder:

root@OF:/glacer/srv/freebsd/15/amd64 # cd /glacer/srv/freebsd/16-CURRENT/amd64
root@OF:/glacer/srv/freebsd/16-CURRENT/amd64 #

Download the system files:

root@OF:/glacer/srv/freebsd/16-CURRENT/amd64 # fetch https://download.freebsd.org/snapshots/amd64/16.0-CURRENT/base.txz
base.txz                                               164 MB 8075 kBps    21s
root@OF:/glacer/srv/freebsd/16-CURRENT/amd64 # fetch https://download.freebsd.org/snapshots/amd64/16.0-CURRENT/kernel.txz
kernel.txz                                              43 MB 6452 kBps    07s
root@OF:/glacer/srv/freebsd/16-CURRENT/amd64 # fetch https://download.freebsd.org/snapshots/amd64/16.0-CURRENT/MANIFEST
MANIFEST                                              1044  B 1300 kBps    00s
root@OF:/glacer/srv/freebsd/16-CURRENT/amd64 # fetch https://download.freebsd.org/snapshots/amd64/16.0-CURRENT/src.txz
src.txz                                                239 MB 8121 kBps    31s
root@OF:/glacer/srv/freebsd/16-CURRENT/amd64 #

Again, no ports.txz — ports are managed with Git.

Section 3: Installing and Setting Up Nginx (Placeholder)

NginX server configuration, add this to the nginx.conf:

server {
    listen 80;
    server_name sus.local;

    root /glacer/srv;

    autoindex on;
    sendfile on;

    location / {
        try_files $uri $uri/ =404;
    }
}

Section 4: Keeping Our FreeBSD SUS Up to Date

FreeBSD releases new snapshot files often. To keep your FreeBSD SUS fresh, you should update the files from time to time. Updating is simple: download the new files and overwrite the old ones.
So repeat steps from 2.1 and 2.2

4.2 Updating Ports (What You Need to Know)

If you used FreeBSD before version 14, you may remember the old portsnap tool and the ports.txz file. These are gone now. FreeBSD moved the entire ports system to Git, and this is the only supported method today.

Because of this change, the FreeBSD SUS does not include ports. Ports are not part of the installer and are not needed for system installation.

If you want to manage ports, build packages, or keep separate ports trees for FreeBSD 15 and 16, see our full guide:

“Managing Ports After FreeBSD 14”

That article explains everything in detail.

4.3 Auto‑Update the SUS Once a Week

You can make a simple script to update your SUS automatically.

Example script:

#!/bin/sh

# Update FreeBSD 15-STABLE
cd /glacer/srv/freebsd/15/amd64
fetch -o base.txz https://download.freebsd.org/snapshots/amd64/15.0-STABLE/base.txz
fetch -o kernel.txz https://download.freebsd.org/snapshots/amd64/15.0-STABLE/kernel.txz
fetch -o MANIFEST https://download.freebsd.org/snapshots/amd64/15.0-STABLE/MANIFEST
fetch -o src.txz https://download.freebsd.org/snapshots/amd64/15.0-STABLE/src.txz

# Update FreeBSD 16-CURRENT
cd /glacer/srv/freebsd/16-CURRENT/amd64
fetch -o base.txz https://download.freebsd.org/snapshots/amd64/16.0-CURRENT/base.txz
fetch -o kernel.txz https://download.freebsd.org/snapshots/amd64/16.0-CURRENT/kernel.txz
fetch -o MANIFEST https://download.freebsd.org/snapshots/amd64/16.0-CURRENT/MANIFEST
fetch -o src.txz https://download.freebsd.org/snapshots/amd64/16.0-CURRENT/src.txz

Save it as:

/usr/local/sbin/update-sus.sh

Make it executable:

chmod +x /usr/local/sbin/update-sus.sh

Add a weekly cron job:

0 3 * * 0 /usr/local/sbin/update-sus.sh

This runs every Sunday at 3 AM.