Skip to main content

How to Configure Linux Binary Compatibility on FreeBSD?

Published on:
.
10 min read
.
For German Version

Binary compatibility exists between two distinct computing environments if source code compiled into a binary for one environment also executes flawlessly in the other environment. This indicates that the developer will not be required to recompile the code to effectively execute it in a different environment.

FreeBSD offers optional binary compatibility with Linux, enabling users to install and execute Linux binaries without modification. The architectures i386, amd64, and arm64 are supported.

Some Linux-specific operating system features are not yet implemented on FreeBSD. This is often the case with hardware-specific or system management-related capabilities, such as cgroups or namespaces.

After completing this tutorial, you will understand:

  • What is the Importance of Binary Compatibility

  • How to achieve binary compatibility with Linux on FreeBSD

  • How to install more shared libraries for Linux

  • How to install Linux programs on a FreeBSD operating system

  • The Linux compatibility implementation details in FreeBSD

What is the Importance of Binary Compatibility?

There are two ways to examine the importance of binary compatibility. If you are developing software for a single, specific purpose, you will want to avoid recompiling a large codebase to accommodate a change in the environment.

You may be using commercially available software that has been tested on a specific operating system, but which may or may not function on a variant of that operating system (such as another Linux distribution). You are unable to recompile the code, and your environment may differ from that in which the vendor tested the program.

What is the Disadvantage of Recompiling?

In some cases, recompiling may be a viable solution, but it may not be practicable when dealing with complex applications that must support multiple environments. In such situations, repetitive recompilation has the following drawbacks:

  • Time-consuming and difficult: When a distinct environment lacks binary compatibility, a number of issues may arise. These issues may involve files in separate locations or libraries with minor differences. Consequently, considerable time, effort, and knowledge are required to ensure that the new binary functions accurately in the new environment.

  • Necessitate specialized skills: Recompiling introduce new flaws or errors that were not present in the original version, particularly if the underlying architecture or platform has been modified. Moreover, recompiling can be costly, particularly for organizations that use in-house developed custom software solutions.

What is the Benefit of Binary Compatibility?

Having knowledge that an alternative environment is binary compatible provides assurance that compiled executables, whether developed in-house or provided by a vendor, will execute without issue in the target environment. Binary compatibility reduces the need for recompiling by allowing software updates to occur without modifying dependent code. This saves time and resources and streamlines the process of updating software.

Nonetheless, a number of circumstances can cast doubt on binary compatibility. For example, when a new version of an operating system is released, concerns arise about whether extant applications will continue to operate seamlessly, indicating if the OS is binary compatible.

Similarly, presume an organization's preferred operating system reaches its end-of-life stage. In such a circumstance, it is essential to have an alternative binary-compatible operating system available to avoid the need for recompilation or application switching. Therefore, it is essential to consider binary compatibility when evaluating the OS strategy of an organization.

What is Linux Binary Compatibility on FreeBSD?

Linux binary compatibility, sometimes known as Linuxulator, enables FreeBSD to execute unmodified Linux binaries. Linuxulator was first motivated by the desire to play Doom on FreeBSD. From its origins in FreeBSD 2.1 (1995, for those keeping track at home), the compatibility tool is currently used by desktop applications such as Steam, Tor, and Firefox, as well as server workloads such as databases, programming languages, and caches.

Linuxulator does not use virtual machines or emulation; rather, it delivers binaries with kernel interfaces equivalent to those of a genuine Linux kernel. Technically, it is comparable to the manner in which 32-bit FreeBSD binaries operate on 64-bit FreeBSD kernel.

There are two primary methods for using Linuxulator:

  • First, Linux software given as FreeBSD ports and packages are installed using the pkg command.

  • Second, LinuxJails offers a complete Debian/Ubuntu user space.

The former offers fewer apps but is more user-friendly. The second way is more laborious, but useful for development work. Both may be used simultaneously.

FreeBSD claims compatibility with Linux 3.2.0 in 12-STABLE and 4.4.0 in 14-CURRENT.

Here is a collection of Linux apps used to test linux(4) on amd64 under 13-STABLE and 14-CURRENT, often inside an Ubuntu chroot environment. In general, it contains bigger chunks of code, ideally those having an accessible test suite.

AppPackageArchDistributionNotes
adomadom_linux_ubuntu_64_3.3.3amd64Ubuntu 18.04.4 LTSInstalled from tarball
aptapt-1.6.12ubuntu0.1amd64Ubuntu 18.04.4 LTSNeed to add APT::Cache-Start 251658240; to /etc/apt/apt.conf.d/00aptitude.
Apache HTTPDapache2-2.4.29-1ubuntu4.13amd64Ubuntu 18.04.4 LTS"unsupported setsockopt level 6 optname 9" (TCP_DEFER_ACCEPT)
Bravebrave-browser-1.20.103 : chromium:88.0.4324.152amd64Ubuntu 20.04 LTSIt works. But, there're some warnings: getsockopt, socket AF_NETLINK. It was tested with following flags: --no-sandbox --no-zygote --test-type --v=0
BusyBoxbusybox-static-1:1.27.2-2ubuntu3.2amd64Ubuntu 18.04.4 LTS
BusyBoxbusybox-static-1:1.30.1-4ubuntu6arm64Ubuntu 20.04 LTS
Chromegoogle-chrome-stable-87.0.4280.88-1amd64Ubuntu 18.04.5 LTSRequires "--no-sandbox --no-zygote --in-process-gpu" options; "--no-zygote" required for Widevine.
Chromiumchromium-browser87.0.4280.66-0ubuntu0.18.04.1amd64Ubuntu 18.04.5 LTSRequires "--no-sandbox --no-zygote --in-process-gpu" options; "--no-zygote" required for Widevine
Dwarf Fortressdwarf-fortress-0.47.04-1amd64Ubuntu 20.04 LTSInstalled with "apt install dwarf-fortress"; the one from tarball has some problem with SDL libraries
Element messengerelement-desktop-1.7.21amd64Ubuntu 20.04 LTSIt works. But, there're some warnings: getsockopt, socket AF_NETLINK. It was tested with following flags: --no-sandbox --no-zygote --test-type --v=0
EMACSemacs25-25.2+1-6amd64Ubuntu 18.04.4 LTS
Firefoxfirefox-77.0.1+build1-0ubuntu0.18.04.1amd64Ubuntu 18.04.4 LTSWorks on 13-CURRENT since r367288
Firestorm ViewerPhoenix_Firestorm-Releasex64_x86_64_6.3.9.58205amd64Ubuntu 20.04.1 LTSWorks with Intel graphics. Does not work with Nvidia unless you can patch linux-nvidia-libs or something
glxgearsmesa-utils-8.4.0-1amd64Ubuntu 18.04.4 LTSRequires at least drm-devel-kmod-5.4.62.g20201109, otherwise crashes immediately
golanggolang-2:1.13~1ubuntu2amd64Ubuntu 20.04.3 LTSTo test: cd /usr/share/go/test && go run run.go -v
grepgrep-3.1-2build1amd64Ubuntu 18.04.4 LTS
irssiirssi-1.0.5-1ubuntu4.2amd64Ubuntu 18.04.4 LTS
Konsolekonsole-4:17.12.3-1ubuntu1amd64Ubuntu 18.04.4 LTSRequires /home and /net nullfs mounts; "ioctl fd=9, cmd=0x5441 ('T',65) is not implemented"
mcmc-3:4.8.19-1amd64Ubuntu 18.04.4 LTSioctl fd=0, cmd=0x541c ('T',28) is not implemented
MathematicaMathematica_12.1.1_LINUX.shamd64Ubuntu 18.04.4 LTS
MariaDBmariadb-server-10.1-1:10.1.44-0ubuntu0.18.04.1amd64Ubuntu 18.04.4 LTSLogs warnings about innodb_use_native_aio not being supported (missing io_setup(2)) and being unable to set thread nice (probably because Linux syscalls.master simply calls native setpriority(2), which doesn't look up Linux TIDs)
Mongomongodb-1:3.6.3-0ubuntu1.1amd64Ubuntu 18.04.4 LTSSeems to work fine, apart from a "Error checking directory '/sys/block': No such file or directory" in logs
MySQLmysql-server-5.7-5.7.30-0ubuntu0.18.04.1amd64Ubuntu 18.04.4 LTSLogs warnings (fallocate(32, FALLOC_FL_PUNCH_HOLE
nethacknethack-console-3.6.0-4amd64Ubuntu 18.04.4 LTS
nethacknethack-console-3.6.1-1arm64Ubuntu 20.04 LTS
ninjaninja-build-1.10.0-1build1arm64Ubuntu 20.04 LTSAll 362 tests pass
Node.jsnodejs-8.10.0~dfsg-2ubuntu0.4amd64Ubuntu 18.04.4 LTSSeems to work fine, however "make test" results are still TBD, at some point the googletest-based V8 regression tests seem to hang on epoll_wait(2) just after EnvironmentTest.ExitHandlerTest
OpenJDKopenjdk-11-jre-headless:amd64-11.0.7+10-2ubuntu2~18.04amd64Ubuntu 18.04.4 LTS
PostgreSQLpostgresql-12.3amd64Ubuntu 18.04.4 LTSInstalled from tarball, so that regression tests (make check) can be run; "All 192 tests passed."
PostgreSQLpostgresql-13.3arm64Ubuntu 20.04 LTSInstalled from tarball, so that regression tests (make check) can be run; "All 201 tests passed."
Pythonpython3-3.6.7-1~18.04amd64Ubuntu 18.04.4 LTS11 test failures, one hang; to test: apt install libpython3.6-testsuite && python3.6 -m test -vW -x test_socket; you will probably need to install missing Python modules as needed
Pythonpython3-3.8.2-1ubuntu1arm64Ubuntu 20.04 LTS387 tests OK, 12 tests failed, 22 tests skipped
Redisredis-5:5.0.7-2amd64Ubuntu 20.04 LTS
RipcordRipcord-0.4.26amd64Ubuntu 20.04 LTSNeed to unpack AppImage bundle but can run binary as expected
screenscreen-4.6.2-1ubuntu1amd64Ubuntu 18.04.4 LTS
Spotifyspotify-client-1:1.1.42.622.gbd112320-37amd64Ubuntu 18.04.5 LTSAlsaDriver Thread process consumes lots of CPU
Spotifyspotify-client-1.1.42.622.gbd112320amd64Ubuntu 20.04 LTSIt works. But, there're some warnings: getsockopt and socket AF_NETLINK
sshopenssh-client-1:7.6p1-4ubuntu0.3amd64Ubuntu 18.04.4 LTS
sshdopenssh-server-1:7.6p1-4ubuntu0.3amd64Ubuntu 18.04.4 LTSMissing keyctl(2), setfsgid(2); ioctl fd=4, cmd=0x5441 ('T',65) is not implemented
sudosudo-1.8.21p2-3ubuntu1.2amd64Ubuntu 18.04.4 LTS
tmuxtmux-2.6-3ubuntu0.2amd64Ubuntu 18.04.4 LTSThere is a weird interaction between FreeBSD and Linux instances running at the same time; ioctl fd=8, cmd=0x5441 ('T',65) is not implemented
Toontown Rewrittenttr-live-v2.6.8amd64Ubuntu 20.04.1 LTSWorks with Intel graphics, does not work with Nvidia unless we can get the linux-nvidia-libs port to work with Ubuntu userlands. AMD graphics are untested. Some things do not render correctly.
Vimvim-2:8.0.1453-1ubuntu1.3amd64Ubuntu 18.04.4 LTS
Vivaldivivaldi-stable_3.4.2066.106-1_amd64amd64Ubuntu 20.04.1 LTS
X-AIR-EditX-AIR-Edit_LINUX_V1.7amd64Ubuntu 20.04.01 LTSFixed around 7a718f293a1

Table 1. Linux Apps tested under FreeBSD 13-STABLE and 14-CURRENT

Get Started with Zenarmor Today For Free

How to Enable Linux Binary Compatibility?

Linux binary compatibility is not enabled on FreeBSD by default. To enable Linux binary compatibility at boot time, you must run the next command to add the line to /etc/rc.conf the configuration file:

echo 'linux_enable="YES"'  >>  /etc/rc.conf

After enabling Linux binary compatibility on your FreeBSD, you may start it without rebooting by running the next command:

service linux start

Under /compat/linux, the /etc/rc.d/linux script will load essential kernel modules and mount filesystems requested by Linux programs. It is sufficient for statically linked Linux binaries to function. They are launched similarly to native FreeBSD binaries. They perform almost identically to native processes and can be traced and debugged as normal.

This is analogous to how 32-bit binaries cannot use 64-bit native libraries. One may transfer these libraries from an existing Linux installation with the same architecture, install them from FreeBSD packages, or install them using debootstrap (from sysutils/debootstrap), among other methods.

How to Install CentOS Base System from FreeBSD Packages?

The simplest method for installing Linux libraries is to install the emulators/linux_base-c7 package or port, which sets the CentOS 7-derived base system in /compat/linux. You may follow the steps given below:

  1. Install the emulators/linux_base-c7 package by running next command :

    pkg install linux_base-c7

    You should see the output similar to the given below:

    Updating FreeBSD repository catalogue...
    Fetching packagesite.pkg: 100% 6 MiB 2.3MB/s 00:03
    Processing entries: 100%
    FreeBSD repository update completed. 32289 packages processed.
    All repositories are up to date.
    The following 1 package(s) will be affected (of 0 checked):
    New packages to be INSTALLED:
    linux_base-c7: 7.9.2009_1

    Number of packages to be installed: 1

    The process will require 232 MiB more space.
    35 MiB to be downloaded.

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

    [1/1] Fetching linux_base-c7-7.9.2009_1.pkg: 100% 35 MiB 2.5MB/s 00:15
    Checking integrity... done (0 conflicting)
    [1/1] Installing linux_base-c7-7.9.2009_1...
    [1/1] Extracting linux_base-c7-7.9.2009_1: 100%
    =====
    Message from linux_base-c7-7.9.2009_1:
    --
    Some programs need linprocfs mounted on /compat/linux/proc. Add the
    following line to /etc/fstab:

    linprocfs /compat/linux/proc linprocfs rw 0 0
    Then run "mount /compat/linux/proc".
    Some programs need linsysfs mounted on /compat/linux/sys. Add the
    following line to /etc/fstab:

    linsysfs /compat/linux/sys linsysfs rw 0 0

    Then run "mount /compat/linux/sys".

    Some programs need tmpfs mounted on /compat/linux/dev/shm. Add the
    following line to /etc/fstab:

    tmpfs /compat/linux/dev/shm tmpfs rw,mode=1777 0 0

    Then run "mount /compat/linux/dev/shm".
  2. You may add the following lines to /etc/fstab to support linprocfs, linsysfs, and tmpfs:

    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
  3. To mount linprocfs, linsysfs, and tmpfs run the next commands:

    mount /compat/linux/proc
    mount /compat/linux/sys
    mount /compat/linux/dev/shm

    FreeBSD offers packages for several binary Linux programs. You may execute the following command to install Sublime Text 4, along with all the Linux libraries it requires:

    pkg install linux-sublime-text4

    You may see the output similar to the following one:

    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    The following 90 package(s) will be affected (of 0 checked):

    New packages to be INSTALLED:
    adwaita-icon-theme: 40.1.1
    at-spi2-core: 2.44.1
    atk: 2.38.0
    ......................................
    wayland: 1.21.0
    xkeyboard-config: 2.34_2
    xorg-fonts-truetype: 7.7_1
    xorgproto: 2022.1

    Number of packages to be installed: 90

    The process will require 527 MiB more space.
    134 MiB to be downloaded.

    Proceed with this action? [y/N]: y
    [1/90] Fetching linux-c7-cairo-gobject-1.15.12_1.pkg: 100% 13 KiB 13.7kB/s 00:01
    [2/90] Fetching libxcb-1.15.pkg: 100% 1 MiB 1.1MB/s 00:01
    [3/90] Fetching linux-c7-libxkbcommon-0.7.1_1.pkg: 100% 159 KiB 163.0kB/s 00:01
    [4/90] Fetching linux-c7-cyrus-sasl-lib-2.1.26_5.pkg: 100% 170 KiB 174.1kB/s 00:01
    [5/90] Fetching libglvnd-1.6.0.pkg: 100% 343 KiB 351.3kB/s 00:01
    [6/90] Fetching libpthread-stubs-0.4.pkg: 100% 2 KiB 2.0kB/s 00:01
    [7/90] Fetching linux-c7-fribidi-1.0.2_1.pkg: 100% 79 KiB 80.5kB/s 00:01
    ......................
    [88/90] Extracting linux-c7-gtk3-3.22.30_4: 100%
    [89/90] Installing desktop-file-utils-0.26_1...
    [89/90] Extracting desktop-file-utils-0.26_1: 100%
    Building cache database of MIME types
    [90/90] Installing linux-sublime-text4-4142...
    [90/90] Extracting linux-sublime-text4-4142: 100%
    Building cache database of MIME types
    Compiling glib schemas
    No schema files found: doing nothing.
    Generating gdk-pixbuf modules cache
    Building the Shared MIME-Info database cache
    Running fc-cache to build fontconfig cache...
    Generating GIO modules cache
    Generating GTK icon cache for /usr/local/share/icons/hicolor
    Generating GTK icon cache for /usr/local/share/icons/Adwaita
    =====
    Message from wayland-1.21.0:
    --
    Wayland requires XDG_RUNTIME_DIR to be defined to a path that will
    contain "wayland-%d" unix(4) sockets. This is usually handled by
    consolekit2 (via ck-launch-session) or pam_xdg (via login).
    =====
    Message from linux-c7-dri-18.3.4_4:
    --
    This package needs linsysfs mounted on /compat/linux/sys. Add the
    following line to /etc/fstab:

    linsysfs /compat/linux/sys linsysfs rw 0 0

    Then run "mount /compat/linux/sys".
    =====
    Message from libxkbcommon-1.4.1:
    --
    If arrow keys don't work under X11 switch to legacy rules e.g.,

    For sh/bash/ksh/zsh run and (optionally) add into ~/.profile:
    export XKB_DEFAULT_RULES=xorg

    For csh/tcsh run and (optionally) add into ~/.login:
    setenv XKB_DEFAULT_RULES xorg
    =====
    Message from dejavu-2.37_1:

    --
    Make sure that the freetype module is loaded. If it is not, add the following line to the "Modules" section of your X Windows configuration file:

    Load "freetype"

    Add the following line to the "Files" section of X Windows configuration file:
    FontPath "/usr/local/share/fonts/dejavu/"

    Note: your X Windows configuration file is typically /etc/X11/XF86Config if you are using XFree86, and /etc/X11/xorg.conf if you are using X.Org.

How to Install Debian / Ubuntu Base System with debootstrap?

Using sysutils/debootstrap is an alternate method for delivering Linux shared libraries. This offers the benefit of a complete Debian or Ubuntu distribution.

Debootstrap is used to install Ubuntu on a machine without the need for an installation DVD, as well as run a different Ubuntu flavor under a chroot environment. This allows you to generate a complete (minimum) Ubuntu system for testing purposes. By executing SCRIPT, debootstrap bootstraps a minimal Ubuntu system of SUITE into TARGET from MIRROR.

You may follow the instructions to install Debian/Ubuntu base system on your FreeBSD 13 node:

  1. Enable Linux binary compatibility by running the following commands:

    echo 'linux_enable="YES"'  >>  /etc/rc.conf
  2. To make the Linux binary compatibility settings permanent configure the FreeBSD system bootstrap configuration file/boot/loader.conf as given below:

    linux_load="YES"
    linux64_load="YES"
    fdescfs_load="YES"
    linprocfs_load="YES"
    tmpfs_load="YES"
    linsysfs_load="YES"
  3. Write a command script for starting and stopping the Ubuntu basic system by running the next commands.

    touch /usr/local/etc/rc.d/ubuntu
    chmod +x /usr/local/etc/rc.d/ubuntu
    nano /usr/local/etc/rc.d/ubuntu
  4. Add the following shell script lines into the script:

    #!/bin/sh
    #
    # PROVIDE: ubuntu
    # REQUIRE: archdep mountlate
    # KEYWORD: nojail
    #
    . /etc/rc.subr
    name="ubuntu"
    desc="Ubuntu for FreeBSD Linux Binary Compatibility"
    rcvar="ubuntu_enable"
    start_cmd="${name}_start"
    stop_cmd=":"

    unmounted()
    {
    [ `stat -f "%d" "$1"` == `stat -f "%d" "$1/.."` -a `stat -f "%i" "$1"` != `stat -f "%i" "$1/.."` ]
    }

    ubuntu_start()
    {
    local _tmpdir
    load_kld -e 'linux(aout|elf)' linux
    case `sysctl -n hw.machine_arch` in
    amd64)
    load_kld -e 'linux64elf' linux64
    ;;
    esac
    if [ -x "/compat/ubuntu/sbin/ldconfigDisabled" ]; then
    _tmpdir=`mktemp -d -t linux-ldconfig`
    /compat/ubuntu/sbin/ldconfig -C ${_tmpdir}/ld.so.cache
    if ! cmp -s "${_tmpdir}/ld.so.cache" "/compat/ubuntu/etc/ld.so.cache"; then
    cat "${_tmpdir}/ld.so.cache" > "/compat/ubuntu/etc/ld.so.cache"
    fi
    rm -rf ${_tmpdir}
    fi
    load_kld pty
    if [ `sysctl -ni kern.elf64.fallback_brand` -eq "-1" ]; then
    sysctl kern.elf64.fallback_brand=3 > /dev/null
    fi
    if [ `sysctl -ni kern.elf32.fallback_brand` -eq "-1" ]; then
    sysctl kern.elf32.fallback_brand=3 > /dev/null
    fi
    sysctl compat.linux.emul_path="/compat/ubuntu"
    unmounted "/compat/ubuntu/dev" && (mount -o nocover -t devfs devfs "/compat/ubuntu/dev" || exit 1)
    unmounted "/compat/ubuntu/dev/fd" && (mount -o nocover,linrdlnk -t fdescfs fdescfs "/compat/ubuntu/dev/fd" || exit 1)
    unmounted "/compat/ubuntu/dev/shm" && (mount -o nocover,mode=1777 -t tmpfs tmpfs "/compat/ubuntu/dev/shm" || exit 1)
    unmounted "/compat/ubuntu/home" && (mount -t nullfs /home "/compat/ubuntu/home" || exit 1)
    unmounted "/compat/ubuntu/proc" && (mount -o nocover -t linprocfs linprocfs "/compat/ubuntu/proc" || exit 1)
    unmounted "/compat/ubuntu/sys" && (mount -o nocover -t linsysfs linsysfs "/compat/ubuntu/sys" || exit 1)
    unmounted "/compat/ubuntu/tmp" && (mount -t nullfs /tmp "/compat/ubuntu/tmp" || exit 1)
    unmounted /dev/fd && (mount -o nocover -t fdescfs fdescfs /dev/fd || exit 1)
    unmounted /proc && (mount -o nocover -t procfs procfs /proc || exit 1)
    true
    }

    load_rc_config $name
    run_rc_command "$1"
  5. You may create a ZFS dataset for the directory of Linux compatibility by running the next command. This step is optional. ZFS dataset enables the usage of snapshots, the safe deletion of files without crossing mountpoints, and, if required, the safe deletion of the whole volume.

    zfs create -o compression=on -o mountpoint=/compat zroot/compat
  6. Run the next command to create the Ubuntu operating system folders:

    mkdir -p /compat/ubuntu/{dev/fd,dev/shm,home,proc,sys,tmp}
  7. Enable Ubuntu chroot jail and make it automatically enabled at boot time by running next command:

    sysrc ubuntu_enable=YES
  8. To start Ubuntu base system in its chroot jail run the following command:

    service ubuntu start

    This will display the following output:

    compat.linux.emul_path: /compat/linux -> /compat/ubuntu
  9. To install debootstrap that will be used to download and install Ubuntu base systems by specifying the Ubuntu target, such as jammy for Jammy Jellyfish, which is version 22.04 LTS of Ubuntu, run the next command:

    pkg install debootstrap

    You should see the output similar to the given below:

    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    The following 18 package(s) will be affected (of 0 checked):
    New packages to be INSTALLED:
    bash: 5.2.15
    debootstrap: 1.0.128
    gmp: 6.2.1
    gnugrep: 3.8
    gnupg: 2.3.8
    gnutls: 3.7.8_1
    libassuan: 2.5.5
    libgcrypt: 1.9.4_1
    libgpg-error: 1.46
    libksba: 1.6.2
    libtasn1: 4.19.0
    nettle: 3.8.1
    npth: 1.6
    p11-kit: 0.24.1_1
    pinentry: 1.2.1
    pinentry-curses: 1.2.1
    sqlite3: 3.40.1,1
    ubuntu-keyring: 2021.03.26

    Number of packages to be installed: 18

    The process will require 54 MiB more space.
    12 MiB to be downloaded.

    Proceed with this action? [y/N]:
    [1/18] Fetching pinentry-curses-1.2.1.pkg: 100% 32 KiB 33.0kB/s 00:01
    [2/18] Fetching gnugrep-3.8.pkg: 100% 250 KiB 255.9kB/s 00:01
    -----------
    [17/18] Installing gnupg-2.3.8...
    [17/18] Extracting gnupg-2.3.8: 100%
    [18/18] Installing debootstrap-1.0.128...
    [18/18] Extracting debootstrap-1.0.128: 100%
    =====
    Message from debootstrap-1.0.128:
    --
    To successfully create an installation of Debian or Ubuntu debootstrap requires the following kernel modules to be loaded:

    linux64 fdescfs linprocfs linsysfs tmpfs

    To install Ubuntu 18.04 LTS (Bionic Beaver) into /compat/ubuntu, run as root:

    debootstrap bionic /compat/ubuntu
  10. Run the following command to download and install Ubuntu 22.04 base system into Linux compatibility directory:

    debootstrap --arch=amd64 --no-check-gpg jammy /compat/ubuntu

    You should see the following lines at the bottom of output:

    I: Configuring python3-yaml...
    I: Configuring netplan.io...
    I: Configuring ubuntu-advantage-tools...
    I: Configuring networkd-dispatcher...
    I: Configuring kbd...
    I: Configuring console-setup-linux...
    I: Configuring console-setup...
    I: Configuring ubuntu-minimal...
    I: Configuring libc-bin...
    I: Configuring ca-certificates...
    I: Base system installed successfully.
    tip

    If you get an Permission denied error, try to run chmod 744 /usr/local/sbin/debootstrap to fix the bug.

  11. Restart Ubuntu chroot jail by running the following command:

    service ubuntu restart

    You should see the following output:

    compat.linux.emul_path: /compat/ubuntu -> /compat/ubuntu
  12. Enter the chroot jail to confine further operations to the Ubuntu base filesystem by running the next command. If Ubuntu displays a notification about a missing group ID, you may just disregard it. You'll notice that the prompt has changed.

    chroot /compat/ubuntu /bin/bash
  13. You may set time zone by running the nxt command:

    echo "%b\n" "0.0 0 0.0\n0\nUTC" >> /etc/adjtime
    dpkg-reconfigure tzdata
  14. To fix apt package manager, run the next command:

    printf "APT::Cache-Start 251658240;" > /etc/apt/apt.conf.d/00aptitude
  15. You may add repositories by running the following command:

    echo "deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse" >> /etc/apt/sources.list
  16. To update Ubuntu packages you may run the following commands:

    apt update
    apt list --upgradable
    apt upgrade
    apt autoremove
    apt clean
  17. To exit the Ubuntu chroot jail run the next command:

    exit

You have now enabled Linux Binary Compatibility in FreeBSD and installed Ubuntu on its base system. You may install Ubuntu and Debian applications and binaries by entering the Ubuntu chroot jail and using the apt package manager.

It is possible to debootstrap into /compat/linux, however it is advised to prevent file clashes with FreeBSD ports and packages. Rather, derive the directory name from the name of the distribution or version, such as /compat/ubuntu. If the bootstrapped instance is meant to offer Linux shared libraries without explicitly using chroot or jails, the kernel may be pointed to it by modifying the compat.linux.emul_path sysctl and adding the following line to /etc/sysctl.conf:

compat.linux.emul_path="/compat/ubuntu"

This sysctl regulates the path translation mechanism of the kernel. Please note that altering it might create issues for Linux programs installed from FreeBSD packages since many of these apps are still 32-bit while Ubuntu seems to be deprecating 32-bit library support.

How to Remove Ubuntu base system and Linux Binary Compatibility from FreeBSD?

The Ubuntu base system in FreeBSD's Linux Binary Compatibility may be securely erased if required by first deactivating the automatic start of Ubuntu base system, then restarting FreeBSD, and then removing the Ubuntu base system directory or destroying the ZFS volume. For added safety, it is advised removing without crossing mountpoints. FreeBSD will crash and FreeBSD disk-related services will core dump if the Ubuntu base system is running while trying to erase it.

  1. Disable Linux binary compatibility by editing /etc/rc.conf:

    linux_enable="NO"
  2. Remove the following lines added for enabling linux bina from /boot/loader.conffile.

    linux_load="YES"
    linux64_load="YES"
    fdescfs_load="YES"
    linprocfs_load="YES"
    tmpfs_load="YES"
    linsysfs_load="YES"
  3. Reboot the FreeBSD node:

    reboot
  4. Delete the Ubuntu base system by running the next commands:

    cd /compat
    rm -rf ubuntu

What is the Advanced Linux Compatibility Topics?

The Linux compatibility layer is still under development on FreeBSD. Some programs need the mounting of particular filesystems. This is handled by the /etc/rc.d/linux script by default, but is deactivated by adding the following line to /etc/rc.conf:

linux_mounts_enable="NO"

Filesystems mounted by the rc script will not function for Linux processes under chroots or jails; configure them in /etc/fstab if necessary:

devfs /compat/linux/dev devfs rw,late 0 0
tmpfs /compat/linux/dev/shm tmpfs rw,late,size=1g,mode=1777 0 0
fdescfs /compat/linux/dev/fd fdescfs rw,late,linrdlnk 0 0
linprocfs /compat/linux/proc linprocfs rw,late 0 0
linsysfs /compat/linux/sys linsysfs rw,late 0 0

Since the Linux binary compatibility layer now supports both 32-bit and 64-bit Linux binaries (on 64-bit x86 hosts), it is no longer viable to statically link emulation features into a custom kernel.

How to Install Additional Libraries Manually?

After establishing Linux binary compatibility, if a Linux program complains about missing shared libraries, discover which shared libraries the Linux binary requires and install them manually.

ldd may be used from a Linux system with the same CPU architecture to discover which shared libraries a program requires. For instance, to see which shared libraries linuxdoom requires, use the following command on a Linux system with Doom installed:

ldd linuxdoom
libXt.so.3 (DLL Jump 3.1) => /usr/X11/lib/libXt.so.3.1.0
libX11.so.3 (DLL Jump 3.1) => /usr/X11/lib/libX11.so.3.1.0
libc.so.4 (DLL Jump 4.5pl26) => /lib/libc.so.4.6.29

Then, copy all the files in the last column of the Linux system's output into /compat/linux on the FreeBSD machine. Create symbolic connections to the names in the first column after copying them. This example will generate the following FreeBSD system files:

/compat/linux/usr/X11/lib/libXt.so.3.1.0
/compat/linux/usr/X11/lib/libXt.so.3 -> libXt.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3 -> libX11.so.3.1.0
/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -> libc.so.4.6.29

If a Linux shared library with a major revision number that matches the first column of the ldd output already exists, it does not need to be transferred to the file mentioned in the final column, since the existing library should function. However, it is recommended to copy the shared library if it is a newer version. If the symbolic link refers to the new one, the old one may be deleted.

These libraries, for instance, already exist on the FreeBSD system:

/compat/linux/lib/libc.so.4.6.27
/compat/linux/lib/libc.so.4 -> libc.so.4.6.27

ldd indicates that a binary needs a newer version:

libc.so.4 (DLL Jump 4.5pl26) -> libc.so.4.6.29

Given that the current library is just one or two versions behind, the application should still function with the somewhat outdated version. However, it is safe to replace the current libc.so file with the updated file:

/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -> libc.so.4.6.29

In most cases, only the first few times a Linux software is installed on FreeBSD would it be necessary to locate the shared libraries on which Linux binaries rely. After some time, the system will have a sufficient collection of Linux shared libraries to execute freshly installed Linux binaries without further effort.

How to Brand Linux ELF Binaries?

The FreeBSD kernel utilizes many techniques to detect whether the binary to be run is a Linux binary:

  • it examines the brand in the ELF file header

  • searches for known ELF interpreter routes,

  • examines ELF notes.

By default, unbranded ELF executables are believed to be Linux. If all of these approaches fail, executing the binary may result in an error message:

% ./my-linux-elf-binary
ELF binary type not known
Abort

brandelf enables the FreeBSD kernel to differentiate between a FreeBSD ELF binary and a Linux binary. You may run the next command for this purpose:

brandelf -t Linux my-linux-elf-binary

How to Install a Linux RPM Based Application?

Install the archivers/rpm4 package or port before installing an RPM-based Linux application. Once installed, root may install .rpm files with the following commands:

cd /compat/linux
rpm2cpio < /path/to/linux.archive.rpm | cpio -id

Use brandelf for the installed ELF binaries if required. This will hinder a clean uninstallation.

How to Configure the Hostname Resolver?

If DNS does not function or if the following error occurs:

resolv+: "bind" is an invalid keyword resolv+:
"hosts" is an invalid keyword

You may configure /compat/linux/etc/host.conf as follows:

order hosts, bind
multi on

This indicates that /etc/hosts is searched first, followed by DNS. Linux apps utilize /etc/host.conf when /compat/linux/etc/host.conf does not exist and complain about the incompatible FreeBSD syntax. Remove bind if /etc/resolv.conf is not set with a name server.