This site runs on FreeBSD 15.1 — a Next.js app on Node 22 from the FreeBSD package repository, kept alive by PM2. It's the same setup I've written about behind nginx and behind Caddy.
In September I tried to move its build to Bun. The build died with this:
error: Unable to resolve @typescript/typescript-linux-x64. Either your platform is unsupported, or you are missing the package on disk.That one line says more about FreeBSD versus Linux in 2026 than most comparison tables do, and it isn't in any of the ones I've read. They cover licenses and init systems — and they should, so this one does too. But the difference most likely to cost you an afternoon today sits a level above the kernel. The software you build with is increasingly native code, compiled for Linux, macOS and Windows first, and FreeBSD gets whatever is left over. Sometimes that's a native build. Sometimes it's a WebAssembly fallback. And sometimes it's a Linux binary that runs just well enough to make the wrong decisions.
So here's the comparison I'd want before choosing: the structural differences, where each system genuinely wins, and then the native-binary problem in detail, with evidence from this site's production server.
FreeBSD vs Linux at a glance
| FreeBSD | Linux | |
|---|---|---|
| What it is | A complete OS — kernel, userland, docs and releases from one project | A kernel; the OS you run is a distribution (Debian, Ubuntu, RHEL, Alpine…) |
| License | BSD 2-Clause (permissive) | GPLv2 kernel (copyleft) |
| Current release | 15.1-RELEASE (June 16, 2026); 14.5 on the older branch | Set by your distribution |
| Support window | Four years per major branch — 15.x until December 31, 2029 | Set by your distribution (Ubuntu LTS: five years standard; RHEL: ten) |
| Init and services | rc.d scripts, configured in /etc/rc.conf |
systemd on most major distributions |
| Packages | pkg for binaries, the Ports tree for source builds |
apt, dnf, pacman, apk — one per distribution family |
| Filesystems | UFS, or OpenZFS in the base system | ext4, XFS, Btrfs; ZFS only as an out-of-tree module |
| Isolation | Jails (since 2000); OCI containers via Podman, still experimental | Namespaces and cgroups — the native home of Docker and Kubernetes |
| Firewall | pf or ipfw | nftables (iptables on older systems) |
| Tracing | DTrace | eBPF and bpftrace |
| Hardware | Strong on servers; Wi-Fi and GPU drivers increasingly ported from Linux | The broadest driver support of any free OS |
One system versus a kernel
When FreeBSD says "15.1", it means a specific kernel, a specific C library, a specific ls and a specific set of manual pages — all built from one source tree, tested together and released together. Third-party software installs into /usr/local through pkg, so the base system and your packages never overwrite each other. That separation is most of why FreeBSD upgrades are predictable, and why the FreeBSD Handbook can describe your system exactly rather than approximately.
Linux, strictly, is the kernel at kernel.org. Everything around it — the C library (usually glibc, sometimes musl), the core utilities, the init system, the package manager — is chosen and assembled by a distribution. That's why "FreeBSD vs Linux" is slightly the wrong question. The comparison you're actually making is FreeBSD versus Debian, or FreeBSD versus Ubuntu.
Is FreeBSD a Linux distribution? No. FreeBSD descends from BSD Unix, the Berkeley line; Linux was written from scratch in 1991 and descends from neither. They feel alike because both are Unix-like, and they differ in the details you notice on day two: rc.conf instead of systemd units, pkg instead of apt, ifconfig instead of ip, and BSD sed and find flags instead of GNU ones. sed -i is the classic trap — BSD sed wants a backup-suffix argument, even an empty one.
The licenses explain who builds on each. BSD 2-Clause lets anyone ship FreeBSD inside a closed product without publishing their changes, which is why it sits underneath things you've used without knowing: the Netflix Open Connect appliances that deliver its video, Sony's PlayStation system software, NetApp's storage OS, and the pfSense and OPNsense firewalls. Linux's GPLv2 requires anyone distributing a modified kernel to publish those changes — one reason so much industry work lands upstream in Linux.
Where FreeBSD genuinely wins
ZFS without asterisks
OpenZFS is part of the FreeBSD base system, and the installer will put your root filesystem on it. That gets you checksummed storage, cheap snapshots and boot environments, which turn a failed upgrade into a reboot:
bectl create pre-upgrade # save the running system as a boot environment
# ...run the upgrade...
bectl activate pre-upgrade # if it went wrong, boot back into the saved one
shutdown -r nowOn Linux, ZFS comes with an asterisk. OpenZFS is licensed under the CDDL, which is widely considered incompatible with the kernel's GPLv2, so it can't be merged into Linux. Ubuntu ships it anyway; most other distributions build it as an out-of-tree module, which means a kernel update can arrive before a matching ZFS module does. Btrfs is the in-kernel alternative. If storage is the job, this difference alone can decide it — I've covered ZFS on FreeBSD in depth and building a NAS on it.
Jails, and an honest word about containers
Jails have isolated workloads on FreeBSD since 2000: their own filesystem root, users and processes — and with VNET, their own network stack — all enforced by the kernel. Backed by ZFS clones, a new jail is nearly free in both time and disk. My jails guide walks through the setup.
Containers in the Docker sense are another matter. FreeBSD now publishes OCI container images, and the Handbook's container chapter covers running them with Podman, using the ocijail runtime to map containers onto jails. Two things stop that from being "Docker on FreeBSD." The runtime is still experimental, and a FreeBSD image needs a FreeBSD kernel — it won't run on Docker Desktop or on a Linux Kubernetes cluster. Linux images can run through the Linuxulator, but only partially: anything that leans on Linux-only kernel interfaces breaks.
pf, and a base system you can hold in your head
pf's rules read like sentences, and a web server's entire ruleset fits on one screen — see setting up pf for a web server. More broadly, the FreeBSD base system is small enough to understand completely, and its man pages describe the exact userland you're running. When something breaks, man is often the fastest answer, rather than a forum thread about a different distribution's build of the same tool.
Support you can put in a calendar
Starting with FreeBSD 15, every major branch has an explicit four-year support period counted from its .0 release, and the FreeBSD security page publishes every date. As of October 2026:
| Release | Released | Supported until |
|---|---|---|
| 15.1-RELEASE | June 16, 2026 | March 31, 2027 |
| 14.5-RELEASE | September 8, 2026 | June 30, 2027 |
| 14.4-RELEASE | March 10, 2026 | December 31, 2026 |
| 15 branch | — | December 31, 2029 |
| 14 branch | — | November 30, 2028 |
FreeBSD 15.0 reached end of life on September 30, 2026. If a server is still on it, move it to 15.1 — the freebsd-update workflow is the same one I walked through in the 14.x to 15.0 upgrade guide.
15.0 also started the biggest change to FreeBSD maintenance in years: the base system can now be installed and updated with pkg — "pkgbase" — instead of freebsd-update. The installer asks which you want. Per the 15.0 announcement, pkgbase is a technology preview throughout 15.x but already the default for FreeBSD's VM and cloud images, and distribution sets are planned for removal in FreeBSD 16, with freebsd-update supported for the life of the 15 branch. Choose deliberately at install time, because the two paths don't mix. Run freebsd-update on a pkgbase system and it refuses:
freebsd-update is incompatible with the use of packaged base. Please see
https://wiki.freebsd.org/PkgBase for more information.On Linux, support belongs to the distribution rather than the project: Ubuntu LTS releases get five years of standard support, RHEL ten. Both are excellent. You're simply choosing a vendor's lifecycle instead of the project's.
Where Linux genuinely wins
Hardware
Linux has the broadest driver support of any free operating system, and the clearest evidence is FreeBSD itself. Its Wi-Fi and graphics drivers increasingly are Linux drivers, compiled against a compatibility layer called LinuxKPI. The 15.1 announcement says it plainly: "The iwlwifi(4) and other LinuxKPI based wireless networking drivers are now based on Linux v7.0." That's good news for FreeBSD on laptops. It also tells you where driver development happens first.
Containers, Kubernetes and the cloud default
Docker and Kubernetes are built on Linux namespaces and cgroups. If your deployment unit is a container image and your platform is Kubernetes, Linux isn't one option among several — it's the substrate. FreeBSD's OCI work is real and improving, but it's a parallel ecosystem, not a compatible one.
Beyond that, every cloud provider's default image, every vendor's supported-platforms list and most Stack Overflow answers assume Linux. That isn't a technical advantage, but it's an operational one you'll feel. It's also why products move. In 2024 iXsystems put TrueNAS CORE, its FreeBSD edition, into a sustaining-engineering phase and moved new development to the Debian-based edition, stating simply that it had "no plans for a FreeBSD 14-based TrueNAS" (The Register).
Desktop, gaming and GPU compute
FreeBSD makes a perfectly usable desktop — KDE Plasma, GNOME and Xfce are a pkg install away — but it's still more assembly than Ubuntu or Fedora. Gaming belongs to Linux: Valve's Steam client and Proton target Linux, not FreeBSD. So does GPU compute. NVIDIA's CUDA toolkit supports Linux and Windows, which on its own rules FreeBSD out of most machine-learning work.
The difference comparison tables miss: native binaries
Here's the part I only understood after it broke.
The fast parts of modern developer tooling are native code. Next.js compiles with SWC and bundles with Turbopack, both written in Rust. TypeScript 7's compiler is written in Go. Tailwind's engine, Lightning CSS and Rolldown are Rust. Bun is written in Zig. Each ships a prebuilt binary per platform, picked at install time from process.platform and process.arch, and most of them build for Linux, macOS and Windows first.
On FreeBSD, each of those tools lands in one of three buckets. All three are present in this site's production node_modules:
| What happens on FreeBSD | Examples on this site's server |
|---|---|
| A native FreeBSD build exists — works exactly as it does on Linux | TypeScript 7 (@typescript/typescript-freebsd-x64), Tailwind's Oxide engine, Lightning CSS, Rolldown, unrs-resolver |
| A WebAssembly fallback — works, usually slower, sometimes with features missing | Next.js's SWC compiler, sharp (@img/sharp-freebsd-wasm32) |
| A Linux binary running through the Linuxulator — works until it makes a platform decision | Bun |
The WebAssembly bucket, and why this site builds with --webpack
Next.js publishes native SWC binaries for macOS, Linux and Windows only — npm view next optionalDependencies lists all eight, and none is for FreeBSD. FreeBSD is on Next's explicit list of WebAssembly-first platforms (x86_64-unknown-freebsd sits in knownDefaultWasmFallbackTriples in its binding loader), so on FreeBSD it downloads the WebAssembly build of SWC instead. You can watch them pile up in the build user's cache, one per Next.js version:
$ ls ~/.cache/next-swc/ | grep wasm | tail -3
swc-wasm-nodejs-16.3.5.tgz
swc-wasm-nodejs-16.3.6.tgz
swc-wasm-nodejs-16.4.0.tgzThat part just works. What doesn't is Turbopack, which Next.js 16 uses by default for both next dev and next build. It requires native bindings, and Next's binding loader spells it out — this is the error it throws on FreeBSD:
Turbopack is not supported on this platform (freebsd/x64) because native bindings are not available. Only WebAssembly (WASM) bindings were loaded, and Turbopack requires native bindings. Use the --webpack flag instead.So this site builds with next build --webpack, and will keep doing so unless Next starts shipping a FreeBSD binary. sharp, which Next.js uses for image optimization, takes the same route through a FreeBSD-specific WebAssembly package — and loads fine.
The Linuxulator bucket: how Bun broke my build
The Linuxulator is FreeBSD's Linux binary compatibility layer. It implements the Linux system-call interface inside the FreeBSD kernel — no virtual machine, no CPU emulation. A Linux ELF binary runs natively, and when it asks the kernel for something, the kernel answers the way Linux would. On my server the linux and linux64 kernel modules were already loaded, which is exactly what made this failure so quiet.
The Bun on my server was the Linux build. The official installer is one easy way to end up there. It picks a build by matching uname -ms:
# abridged from https://bun.sh/install
case $platform in
'Darwin x86_64') target=darwin-x64 ;;
'Darwin arm64') target=darwin-aarch64 ;;
# ...
'Linux x86_64' | *) target=linux-x64 ;;
esacOn FreeBSD, uname -ms prints FreeBSD amd64. Nothing matches it, so it falls through to the * default and installs the Linux x64 build. bun upgrade then keeps you on whichever build you started with — I upgraded mine to 1.4.2 and it stayed Linux.
It runs, and nothing tells you. bun --version prints a version. Only file gives it away:
$ file ~/.bun/bin/bun
/home/pm2/.bun/bin/bun: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, ...It reports the wrong platform. process.platform is baked into a runtime when it's compiled. Node from FreeBSD's packages says freebsd; a Linux build of Bun says linux — on the same machine:
$ node -p process.platform
freebsd
$ bun -e 'console.log(process.platform)'
linuxThen the two disagree about node_modules. yarn install ran under Node, so it installed FreeBSD binaries, including @typescript/typescript-freebsd-x64. Then bun --bun next build --webpack ran under Bun, and TypeScript 7, resolving its native compiler from process.platform, went looking for the Linux one:
error: Unable to resolve @typescript/typescript-linux-x64. Either your platform is unsupported, or you are missing the package on disk.
at getExePath (node_modules/typescript/lib/getExePath.js:53:23)
Bun v1.4.2 (Linux x64)Next.js hit the same mismatch and quietly papered over it: convinced it was on Linux, it downloaded @next/swc-linux-x64-gnu into the cache mid-build. TypeScript has no such fallback, so the build stopped there. My deploy script moves the live build aside and restores it when a build fails, so the site never went down — if yours deletes .next before building, fix that first.
The rule I took away: a Linux binary that only runs is fine under the Linuxulator. A Linux binary that installs, resolves or builds things is dangerous, because every platform decision it makes assumes Linux — against a dependency tree that was installed for FreeBSD.
The twist: Bun already ships for FreeBSD
Bun has published native FreeBSD builds since v1.3.14, released May 13, 2026. bun-freebsd-x64.zip and bun-freebsd-aarch64.zip have been on every release page since; the installer just doesn't pick them. A native build reports process.platform as freebsd, and would resolve the @typescript/typescript-freebsd-x64 package that was already sitting on disk.
To be clear about what I have and haven't tested: I haven't yet re-run this site's build on the native FreeBSD Bun, so I won't tell you it works end to end. What I can tell you is that this failure belongs to the Linux binary, not to Bun on FreeBSD — and that checking which one you have takes five seconds:
file "$(command -v bun)" # want an ELF built for FreeBSD, not GNU/Linux
bun -e 'console.log(process.platform)' # want: freebsdCheck before you commit a project to FreeBSD
The same check generalizes. Before you choose FreeBSD for a project, look at which of its native dependencies publish FreeBSD builds. npm will tell you:
$ npm view @tailwindcss/oxide optionalDependencies | grep freebsd
'@tailwindcss/oxide-freebsd-x64': '4.3.3',
$ npm view next optionalDependencies | grep freebsd
$Then, on the FreeBSD machine after an install, find node_modules -maxdepth 3 -type d -iname '*freebsd*' lists everything that got a native build. Anything native that isn't on that list either fell back to WebAssembly or isn't there, and the build log will tell you which.
Performance and security: the honest answer
Is FreeBSD faster than Linux? Not in general — and neither is Linux. Results swing with workload, hardware, drivers and tuning. FreeBSD's network stack is good enough that Netflix delivers its video from FreeBSD-based appliances; Linux runs most of the public cloud. For a typical web application the operating system is rarely your bottleneck. Your database and your code are.
Is FreeBSD more secure than Linux? Neither is more secure in the abstract. FreeBSD offers a smaller, centrally maintained base system, jails, Capsicum and securelevels, with security advisories that cover the whole system at once — the May 2026 batch shows how that looks in practice. Linux offers SELinux, AppArmor and seccomp, a larger attack surface, and far more scrutiny. What actually decides how secure your server is: how fast you patch and how little you expose. Locking down SSH is a good place to start.
So which should you choose?
Choose FreeBSD when:
- Storage is the job — ZFS in the base system and boot environments are hard to beat.
- You're building a firewall, router or network appliance, where pf shines.
- You want a small, coherent server you can understand completely, with support dates you can put in a calendar.
- Jails cover your isolation needs.
- You've checked that your toolchain has FreeBSD builds or WebAssembly fallbacks.
Choose Linux when:
- Your deployment unit is a container image and your platform is Kubernetes.
- You need particular hardware: the newest GPUs, specific Wi-Fi chipsets, or CUDA.
- It's a desktop you also game on.
- You need vendor certification or commercial support for the operating system.
- Your toolchain ships Linux binaries and nothing else.
This site is staying on FreeBSD. Node from the package repository, Next.js built with --webpack, and PM2 make a boring stack in the best sense — and the one time it bit me, it bit me at build time while the previous build kept serving.
The part worth remembering
The FreeBSD-versus-Linux argument used to be about kernels: schedulers, network stacks, filesystems. In 2026 the more practical difference sits one level up. The software you build with is increasingly native code, and most projects' build matrices stop at Linux, macOS and Windows.
FreeBSD is doing better inside that constraint than its reputation suggests — TypeScript, Tailwind, Lightning CSS and Rolldown all ship FreeBSD binaries, and Bun started this year. But the Linuxulator means that when a native build is missing, FreeBSD will often run the Linux one rather than fail. A tool that refuses to start is easy to debug. A tool that is quietly wrong about which operating system it's on is not.
So check what you're running. It takes five seconds, and it's the most FreeBSD-specific advice in this whole comparison.
FreeBSD release and support details are from the FreeBSD security page and the 15.0 and 15.1 release announcements, checked October 7, 2026. Server observations are from this site's production host: FreeBSD 15.1-RELEASE-p1 on amd64, Node 22.23.2, Next.js 16.3.5.