FreeBSD.software
Home/Guides/How to Run Linux Applications on FreeBSD
tutorial·2026-03-29·14 min read

How to Run Linux Applications on FreeBSD

Guide to running Linux applications on FreeBSD using the Linux compatibility layer (Linuxulator). Covers setup, CentOS/Ubuntu userlands, installing Linux packages, Flatpak, Wine, and limitations.

How to Run Linux Applications on FreeBSD

FreeBSD is not Linux. But it can run most Linux software, often without recompiling a single line of code. The mechanism behind this is the Linuxulator, a kernel-level compatibility layer that translates Linux system calls into their FreeBSD equivalents. It is not emulation. There is no virtual machine. Linux binaries execute directly on FreeBSD hardware at near-native speed.

This guide covers the full process: enabling the compatibility layer, installing a Linux userland, running popular applications like Spotify and Steam, and dealing with the edge cases that inevitably come up.

What Is the Linuxulator?

The Linuxulator is FreeBSD's Linux ABI (Application Binary Interface) compatibility layer. It has been part of FreeBSD since the mid-1990s and has matured considerably over the decades.

Here is what it does at a technical level:

  • Syscall translation. When a Linux binary makes a system call, the FreeBSD kernel intercepts it and maps it to the equivalent FreeBSD syscall. Most Linux syscalls have direct FreeBSD counterparts.
  • ELF branding. FreeBSD's kernel inspects the ELF header of a binary to determine whether it is a native FreeBSD executable or a Linux one. Linux-branded binaries are routed through the compatibility layer automatically.
  • Filesystem mapping. Linux binaries expect to find libraries and configuration files under paths like /lib, /usr/lib, and /etc. The Linuxulator maps these to a separate root under /compat/linux/, keeping Linux files isolated from the FreeBSD system.
  • Signal and thread handling. Linux-specific threading semantics (NPTL) and signal delivery mechanisms are handled within the kernel module.

The key point: this is not Wine, not QEMU, not a container. Linux binaries run as native processes visible in ps and top. They can interact with FreeBSD files, network sockets, and devices. The performance overhead is negligible -- typically under 2-3% for syscall-heavy workloads, and effectively zero for compute-bound tasks.

For a broader comparison of the two operating systems, see our FreeBSD vs Linux comparison.

Enabling Linux Compatibility

Step 1: Load the Kernel Module

The Linuxulator is implemented as a loadable kernel module. On a 64-bit FreeBSD system, load it immediately with:

bash
sudo kldload linux64

Verify it loaded:

bash
kldstat | grep linux

You should see linux64.ko in the output.

Step 2: Enable It at Boot

To load the module automatically on every boot, add this line to /etc/rc.conf:

bash
sudo sysrc linux_enable="YES"

Step 3: Mount Required Filesystems

Linux applications expect certain pseudo-filesystems to be available. Add the following entries to /etc/fstab:

shell
linprocfs /compat/linux/proc linprocfs rw 0 0 linsysfs /compat/linux/sys linsysfs rw 0 0 tmpfs /compat/linux/dev/shm tmpfs rw,mode=1777 0 0

Create the mount points and mount them:

bash
sudo mkdir -p /compat/linux/proc /compat/linux/sys /compat/linux/dev/shm sudo mount -a

Step 4: Configure DMA Buffer Access (Optional)

Some graphical Linux applications need access to /dev/shm for shared memory. The tmpfs entry above handles this. If you are running a FreeBSD desktop, this step is essential for GUI applications.

Installing a Linux Userland

The Linuxulator translates syscalls, but Linux binaries still need Linux shared libraries to link against. You need a Linux userland -- a minimal Linux root filesystem installed under /compat/linux/.

FreeBSD's package manager provides pre-built CentOS-based userland packages. This is the fastest and most well-tested approach:

bash
sudo pkg install linux_base-c7

This installs a CentOS 7 base system under /compat/linux/. It includes glibc, common shared libraries, and basic utilities.

For newer software that requires a more recent glibc, you can install the Rocky Linux 9 base instead (available on FreeBSD 14+):

bash
sudo pkg install linux_base-rl9

After installation, verify the setup:

bash
/compat/linux/usr/bin/uname -a

This should report a Linux kernel version, confirming the compatibility layer is working.

Option B: Ubuntu/Debian Userland via debootstrap

If you need Debian or Ubuntu packages (common for desktop applications), you can bootstrap an Ubuntu userland:

bash
sudo pkg install debootstrap sudo debootstrap --arch=amd64 jammy /compat/linux/ubuntu http://archive.ubuntu.com/ubuntu

After bootstrapping, you may need to set up the correct symlinks or adjust /compat/linux to point to this new root, depending on your needs. This approach requires more manual configuration but gives you access to the full Debian/Ubuntu package ecosystem.

Option C: Hybrid Approach

Many users install the CentOS base for core libraries and then layer additional libraries from other distributions as needed. The CentOS base provides a stable foundation, and you can manually add .deb-extracted libraries into /compat/linux/ for specific applications.

Installing Linux Packages Inside the Compat Layer

Once you have a Linux userland, you can install additional Linux packages within it.

Using yum (CentOS Userland)

Chroot into the Linux environment and use the native package manager:

bash
sudo chroot /compat/linux /bin/bash yum install -y <package-name> exit

For the CentOS 7 userland, you may need to configure repositories first:

bash
sudo chroot /compat/linux /bin/bash yum install -y epel-release yum update -y

Using apt (Ubuntu/Debian Userland)

If you bootstrapped an Ubuntu root:

bash
sudo chroot /compat/linux/ubuntu /bin/bash apt update apt install -y <package-name> exit

Manual Library Installation

Sometimes you only need one or two libraries for a specific application. You can extract them from a .deb or .rpm package and place them manually:

bash
# Download a .deb package wget http://archive.ubuntu.com/ubuntu/pool/main/libx/libxcb/libxcb1_1.14-3ubuntu3_amd64.deb # Extract it ar x libxcb1_1.14-3ubuntu3_amd64.deb tar xf data.tar.xz # Copy libraries to the compat layer sudo cp -a usr/lib/x86_64-linux-gnu/* /compat/linux/usr/lib64/

Run ldconfig inside the compat layer after adding libraries:

bash
sudo chroot /compat/linux /sbin/ldconfig

Running Common Linux Applications

Spotify

Spotify does not offer a native FreeBSD client. The Linux version works via the Linuxulator:

bash
# Install required dependencies in the Linux userland sudo chroot /compat/linux /bin/bash yum install -y alsa-lib libXScrnSaver gtk3 nss at-spi2-atk libdrm mesa-libgbm exit # Download and extract the Spotify .deb fetch https://repository-origin.spotify.com/pool/non-free/s/spotify-client/spotify-client_1.2.52.442_amd64.deb ar x spotify-client_*.deb tar xf data.tar.xz -C /compat/linux/ # Run it /compat/linux/usr/bin/spotify

Audio output requires PulseAudio or PipeWire to be configured on the FreeBSD side. More on audio troubleshooting below.

Discord

Similar to Spotify, Discord provides a Linux .deb package:

bash
fetch -o discord.deb "https://discord.com/api/download?platform=linux&format=deb" ar x discord.deb sudo tar xf data.tar.xz -C /compat/linux/ /compat/linux/usr/share/discord/Discord

Discord may require additional libraries like libappindicator and libnotify. Install them inside the chroot as needed.

Steam

Steam on FreeBSD requires both the Linux compatibility layer and 32-bit library support:

bash
sudo kldload linux sudo pkg install linux_base-c7 linux-steam-utils

The linux-steam-utils port handles much of the dependency management. Launch Steam with:

bash
steam

Game compatibility varies. Proton-based games (Valve's Wine fork) add another translation layer on top of the Linuxulator, which can introduce additional issues. Native Linux games generally work better.

Google Chrome

bash
sudo chroot /compat/linux /bin/bash yum install -y wget wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm yum localinstall -y google-chrome-stable_current_x86_64.rpm exit /compat/linux/usr/bin/google-chrome-stable --no-sandbox

The --no-sandbox flag is often required because Chrome's sandbox makes syscalls that the Linuxulator does not fully support. This is a known workaround, though it reduces browser security isolation.

Flatpak on FreeBSD

Flatpak provides sandboxed application distribution and has experimental FreeBSD support. It runs Linux applications in isolated environments with their own runtime libraries.

bash
sudo pkg install flatpak flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo

Install an application:

bash
flatpak install flathub com.spotify.Client flatpak run com.spotify.Client

Flatpak on FreeBSD relies on the Linuxulator under the hood. Support is still maturing. Some applications work perfectly, others have issues with sandboxing, D-Bus communication, or portal access. Check the FreeBSD wiki and forums for current application-specific compatibility notes.

The advantage of Flatpak is that each application bundles its own runtime libraries, avoiding dependency conflicts with the base Linux userland.

Wine for Windows Applications

Wine is separate from the Linuxulator -- it translates Windows API calls to POSIX calls. On FreeBSD, Wine runs natively (not through the Linux compat layer):

bash
sudo pkg install wine

For 32-bit Windows applications on a 64-bit system:

bash
sudo pkg install i386-wine

Run a Windows executable:

bash
wine /path/to/application.exe

Wine on FreeBSD is well-maintained and generally on par with the Linux version. For gaming, wine-proton or wine-staging may provide better compatibility:

bash
sudo pkg install wine-proton

Wine and the Linuxulator serve different purposes and can coexist on the same system. Wine handles Windows binaries; the Linuxulator handles Linux binaries.

Docker on FreeBSD

Docker does not run natively on FreeBSD. Docker depends on Linux-specific kernel features (cgroups v2, namespaces, overlayfs) that the Linuxulator does not implement.

Your options:

  1. Use FreeBSD jails. Jails are FreeBSD's native containerization and predate Docker by over a decade. Tools like bastille, pot, and iocage provide management interfaces. See our FreeBSD jails vs Docker comparison for details.
  1. Run Docker inside a Linux VM. Use bhyve (FreeBSD's hypervisor) to run a minimal Linux VM, then run Docker inside it. This is the most reliable approach if you need full Docker compatibility.
  1. Podman (experimental). There has been work on running Podman with FreeBSD support using jails as the container backend, but this remains experimental and limited.

The bottom line: if Docker is a hard requirement for your workflow, you will need a Linux VM. If your goal is containerization, FreeBSD jails are the native and more efficient solution.

Performance Considerations

The Linuxulator operates at the kernel level, translating syscalls in-kernel without context switches to userspace. This makes it significantly faster than traditional emulation.

Benchmarks in practice:

  • CPU-bound workloads (compilation, encoding, scientific computing): Effectively zero overhead. The binary code runs directly on the CPU.
  • I/O-bound workloads (file access, network operations): Minimal overhead from syscall translation, typically 1-3%.
  • Graphics-intensive workloads (games, GPU computing): Performance depends on GPU driver support. FreeBSD's DRM drivers have improved substantially. Applications using OpenGL or Vulkan through the Linuxulator may see slightly reduced performance compared to native FreeBSD applications.

Compared to running applications in a VM, the Linuxulator has a clear advantage: no memory overhead, no CPU virtualization penalty, no disk image management. Linux applications share the same kernel, filesystem, and network stack as native FreeBSD processes.

Memory usage is comparable to running the same application on Linux. The Linux userland libraries are loaded into memory as shared objects, same as they would be on a Linux system.

Known Limitations and Workarounds

Not everything works. Here are the most common issues:

Kernel Feature Gaps

Some Linux-specific kernel features are not implemented:

  • inotify: Partially supported. Some applications that rely on filesystem event monitoring may not work correctly. FreeBSD uses kqueue natively, but the Linuxulator provides an inotify shim that covers common use cases.
  • epoll: Supported and mapped to kqueue internally. Most applications work fine.
  • seccomp: Not supported. Applications that use seccomp sandboxing (Chrome, Flatpak) may need workarounds like --no-sandbox.
  • cgroups/namespaces: Not supported. Container runtimes (Docker, Podman) do not work.
  • io_uring: Not supported. Applications using this newer Linux I/O interface will fall back to older methods or fail.

32-bit Support

Running 32-bit Linux applications requires loading the linux module in addition to linux64:

bash
sudo kldload linux sudo kldload linux64

And installing 32-bit libraries:

bash
sudo pkg install linux_base-c7

GPU and Graphics

GPU acceleration through the Linuxulator works but requires proper DRM driver support on FreeBSD. Intel and AMD GPUs are best supported. NVIDIA support depends on the proprietary driver version.

For applications needing GPU access:

bash
# Ensure the Linux user has access to the DRI device sudo chmod 666 /dev/dri/card0 /dev/dri/renderD128

Networking

Linux applications running under the Linuxulator share FreeBSD's network stack. This generally works transparently. Applications that try to access /proc/net/ or make Linux-specific netlink socket calls may encounter issues.

Troubleshooting

Missing Shared Libraries

The most common error you will see:

shell
/compat/linux/usr/bin/app: error while loading shared libraries: libsomething.so.1: cannot open shared object file

Fix it by finding and installing the missing library:

bash
# Search for the library in available packages sudo chroot /compat/linux /bin/bash yum provides */libsomething.so.1 yum install -y <package-that-provides-it> exit

Or use ldd to check all dependencies:

bash
/compat/linux/usr/bin/ldd /compat/linux/path/to/application

Wrong Paths and Prefix Issues

Linux applications hardcode paths like /usr/lib or /etc. The Linuxulator redirects these to /compat/linux/usr/lib and /compat/linux/etc. But some applications use unusual paths that are not caught by the redirection.

Check what paths an application is trying to access:

bash
truss -f /compat/linux/usr/bin/application 2>&1 | grep "open\|stat"

Then create the necessary symlinks or copy files to the expected locations under /compat/linux/.

Audio Issues

Audio is the single most common problem with Linux applications on FreeBSD. FreeBSD uses OSS natively, while most Linux applications expect PulseAudio or ALSA.

Solution 1: PulseAudio bridge

Install PulseAudio on FreeBSD:

bash
sudo pkg install pulseaudio

Start the PulseAudio daemon:

bash
pulseaudio --start

Linux applications will connect to PulseAudio via the Unix socket at /var/run/pulse/. Make sure this path is accessible from within the compat layer:

bash
sudo mkdir -p /compat/linux/var/run/pulse sudo mount -t nullfs /var/run/pulse /compat/linux/var/run/pulse

Solution 2: PipeWire

PipeWire is increasingly replacing PulseAudio and offers better compatibility:

bash
sudo pkg install pipewire

PipeWire provides PulseAudio and ALSA compatibility layers, making it the best option for running Linux audio applications.

D-Bus Issues

Many Linux desktop applications require D-Bus. Install and enable it:

bash
sudo pkg install dbus sudo sysrc dbus_enable="YES" sudo service dbus start

Ensure the D-Bus socket is accessible from the compat layer:

bash
sudo mkdir -p /compat/linux/var/run/dbus sudo mount -t nullfs /var/run/dbus /compat/linux/var/run/dbus

Font Issues

Linux applications may complain about missing fonts. Install common font packages:

bash
sudo pkg install noto urwfonts webfonts

And symlink the font directory into the compat layer:

bash
sudo mkdir -p /compat/linux/usr/share/fonts sudo mount -t nullfs /usr/local/share/fonts /compat/linux/usr/share/fonts

Frequently Asked Questions

Is the Linuxulator the same as running Linux in a VM?

No. The Linuxulator runs Linux binaries directly on the FreeBSD kernel. There is no virtual machine, no hypervisor, no separate kernel. Linux processes are native FreeBSD processes with syscall translation. This means near-zero overhead and direct access to hardware, filesystems, and network interfaces. A VM, by contrast, runs a complete separate Linux kernel and requires dedicated memory and CPU resources.

Can I run any Linux application on FreeBSD?

Most Linux applications work. The compatibility is very good for command-line tools, server software, and many desktop applications. Applications that depend on Linux-specific kernel features not yet implemented in the Linuxulator (such as cgroups, namespaces, or io_uring) will not work. The majority of "standard" Linux software, including many commercial applications, runs without issues.

Does the Linuxulator support Linux kernel modules?

No. The Linuxulator translates userspace syscalls only. Linux kernel modules, device drivers, or anything that runs in kernel space cannot be loaded on FreeBSD. If an application requires a custom Linux kernel module, it will not work through the Linuxulator. You would need a full Linux VM for that use case.

How do I update the Linux userland?

For the CentOS base installed via pkg:

bash
sudo pkg upgrade linux_base-c7

For packages installed inside the chroot:

bash
sudo chroot /compat/linux /bin/bash yum update -y exit

Keep both the FreeBSD-provided base and the chroot packages updated for security and compatibility.

Can I run Linux and FreeBSD applications side by side?

Yes. Linux applications running under the Linuxulator are regular processes on the FreeBSD system. They can read and write the same files, listen on the same network ports (if not conflicting), and communicate via pipes, sockets, and shared memory with native FreeBSD applications. You can pipe output from a Linux tool into a FreeBSD tool and vice versa. They coexist transparently.

Is Linux compatibility available on FreeBSD ARM64?

Linux compatibility on ARM64 (aarch64) is under active development but is less mature than the x86_64 implementation. Basic functionality works on FreeBSD 14 and later, but many applications have not been tested. If you are running FreeBSD on ARM hardware, expect to encounter more rough edges than on x86_64.

Should I use the Linuxulator or just install the FreeBSD native version of software?

Always prefer the native FreeBSD version when one exists. Native packages are better integrated, better tested on FreeBSD, and avoid the small overhead of syscall translation. Use the Linuxulator for software that is only available as Linux binaries: proprietary applications, commercial software, or niche tools that have not been ported to FreeBSD.

Conclusion

The Linuxulator is one of FreeBSD's most practical features. It bridges the gap between FreeBSD's technical strengths and Linux's larger application ecosystem without requiring a VM or dual-boot setup. The setup takes about ten minutes, and once configured, most Linux applications just work.

Start with the CentOS base userland via pkg, add libraries as needed for specific applications, and keep truss handy for debugging path and library issues. For desktop use, get PulseAudio or PipeWire working early -- audio is the most common friction point.

FreeBSD is not trying to be Linux. But it does not force you to give up Linux software either. That pragmatism is one of the reasons FreeBSD remains a compelling choice for both servers and desktops.

Get more FreeBSD guides

Weekly tutorials, security advisories, and package updates. No spam.