How to Configure Linux Binary Compatibility on FreeBSD?
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.
App | Package | Arch | Distribution | Notes |
---|---|---|---|---|
adom | adom_linux_ubuntu_64_3.3.3 | amd64 | Ubuntu 18.04.4 LTS | Installed from tarball |
apt | apt-1.6.12ubuntu0.1 | amd64 | Ubuntu 18.04.4 LTS | Need to add APT::Cache-Start 251658240; to /etc/apt/apt.conf.d/00aptitude. |
Apache HTTPD | apache2-2.4.29-1ubuntu4.13 | amd64 | Ubuntu 18.04.4 LTS | "unsupported setsockopt level 6 optname 9" (TCP_DEFER_ACCEPT) |
Brave | brave-browser-1.20.103 : chromium:88.0.4324.152 | amd64 | Ubuntu 20.04 LTS | It works. But, there're some warnings: getsockopt, socket AF_NETLINK. It was tested with following flags: --no-sandbox --no-zygote --test-type --v=0 |
BusyBox | busybox-static-1:1.27.2-2ubuntu3.2 | amd64 | Ubuntu 18.04.4 LTS | |
BusyBox | busybox-static-1:1.30.1-4ubuntu6 | arm64 | Ubuntu 20.04 LTS | |
Chrome | google-chrome-stable-87.0.4280.88-1 | amd64 | Ubuntu 18.04.5 LTS | Requires "--no-sandbox --no-zygote --in-process-gpu" options; "--no-zygote" required for Widevine. |
Chromium | chromium-browser87.0.4280.66-0ubuntu0.18.04.1 | amd64 | Ubuntu 18.04.5 LTS | Requires "--no-sandbox --no-zygote --in-process-gpu" options; "--no-zygote" required for Widevine |
Dwarf Fortress | dwarf-fortress-0.47.04-1 | amd64 | Ubuntu 20.04 LTS | Installed with "apt install dwarf-fortress"; the one from tarball has some problem with SDL libraries |
Element messenger | element-desktop-1.7.21 | amd64 | Ubuntu 20.04 LTS | It works. But, there're some warnings: getsockopt, socket AF_NETLINK. It was tested with following flags: --no-sandbox --no-zygote --test-type --v=0 |
EMACS | emacs25-25.2+1-6 | amd64 | Ubuntu 18.04.4 LTS | |
Firefox | firefox-77.0.1+build1-0ubuntu0.18.04.1 | amd64 | Ubuntu 18.04.4 LTS | Works on 13-CURRENT since r367288 |
Firestorm Viewer | Phoenix_Firestorm-Releasex64_x86_64_6.3.9.58205 | amd64 | Ubuntu 20.04.1 LTS | Works with Intel graphics. Does not work with Nvidia unless you can patch linux-nvidia-libs or something |
glxgears | mesa-utils-8.4.0-1 | amd64 | Ubuntu 18.04.4 LTS | Requires at least drm-devel-kmod-5.4.62.g20201109, otherwise crashes immediately |
golang | golang-2:1.13~1ubuntu2 | amd64 | Ubuntu 20.04.3 LTS | To test: cd /usr/share/go/test && go run run.go -v |
grep | grep-3.1-2build1 | amd64 | Ubuntu 18.04.4 LTS | |
irssi | irssi-1.0.5-1ubuntu4.2 | amd64 | Ubuntu 18.04.4 LTS | |
Konsole | konsole-4:17.12.3-1ubuntu1 | amd64 | Ubuntu 18.04.4 LTS | Requires /home and /net nullfs mounts; "ioctl fd=9, cmd=0x5441 ('T',65) is not implemented" |
mc | mc-3:4.8.19-1 | amd64 | Ubuntu 18.04.4 LTS | ioctl fd=0, cmd=0x541c ('T',28) is not implemented |
Mathematica | Mathematica_12.1.1_LINUX.sh | amd64 | Ubuntu 18.04.4 LTS | |
MariaDB | mariadb-server-10.1-1:10.1.44-0ubuntu0.18.04.1 | amd64 | Ubuntu 18.04.4 LTS | Logs 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) |
Mongo | mongodb-1:3.6.3-0ubuntu1.1 | amd64 | Ubuntu 18.04.4 LTS | Seems to work fine, apart from a "Error checking directory '/sys/block': No such file or directory" in logs |
MySQL | mysql-server-5.7-5.7.30-0ubuntu0.18.04.1 | amd64 | Ubuntu 18.04.4 LTS | Logs warnings (fallocate(32, FALLOC_FL_PUNCH_HOLE |
nethack | nethack-console-3.6.0-4 | amd64 | Ubuntu 18.04.4 LTS | |
nethack | nethack-console-3.6.1-1 | arm64 | Ubuntu 20.04 LTS | |
ninja | ninja-build-1.10.0-1build1 | arm64 | Ubuntu 20.04 LTS | All 362 tests pass |
Node.js | nodejs-8.10.0~dfsg-2ubuntu0.4 | amd64 | Ubuntu 18.04.4 LTS | Seems 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 |
OpenJDK | openjdk-11-jre-headless:amd64-11.0.7+10-2ubuntu2~18.04 | amd64 | Ubuntu 18.04.4 LTS | |
PostgreSQL | postgresql-12.3 | amd64 | Ubuntu 18.04.4 LTS | Installed from tarball, so that regression tests (make check) can be run; "All 192 tests passed." |
PostgreSQL | postgresql-13.3 | arm64 | Ubuntu 20.04 LTS | Installed from tarball, so that regression tests (make check) can be run; "All 201 tests passed." |
Python | python3-3.6.7-1~18.04 | amd64 | Ubuntu 18.04.4 LTS | 11 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 |
Python | python3-3.8.2-1ubuntu1 | arm64 | Ubuntu 20.04 LTS | 387 tests OK, 12 tests failed, 22 tests skipped |
Redis | redis-5:5.0.7-2 | amd64 | Ubuntu 20.04 LTS | |
Ripcord | Ripcord-0.4.26 | amd64 | Ubuntu 20.04 LTS | Need to unpack AppImage bundle but can run binary as expected |
screen | screen-4.6.2-1ubuntu1 | amd64 | Ubuntu 18.04.4 LTS | |
Spotify | spotify-client-1:1.1.42.622.gbd112320-37 | amd64 | Ubuntu 18.04.5 LTS | AlsaDriver Thread process consumes lots of CPU |
Spotify | spotify-client-1.1.42.622.gbd112320 | amd64 | Ubuntu 20.04 LTS | It works. But, there're some warnings: getsockopt and socket AF_NETLINK |
ssh | openssh-client-1:7.6p1-4ubuntu0.3 | amd64 | Ubuntu 18.04.4 LTS | |
sshd | openssh-server-1:7.6p1-4ubuntu0.3 | amd64 | Ubuntu 18.04.4 LTS | Missing keyctl(2), setfsgid(2); ioctl fd=4, cmd=0x5441 ('T',65) is not implemented |
sudo | sudo-1.8.21p2-3ubuntu1.2 | amd64 | Ubuntu 18.04.4 LTS | |
tmux | tmux-2.6-3ubuntu0.2 | amd64 | Ubuntu 18.04.4 LTS | There 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 Rewritten | ttr-live-v2.6.8 | amd64 | Ubuntu 20.04.1 LTS | Works 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. |
Vim | vim-2:8.0.1453-1ubuntu1.3 | amd64 | Ubuntu 18.04.4 LTS | |
Vivaldi | vivaldi-stable_3.4.2066.106-1_amd64 | amd64 | Ubuntu 20.04.1 LTS | |
X-AIR-Edit | X-AIR-Edit_LINUX_V1.7 | amd64 | Ubuntu 20.04.01 LTS | Fixed around 7a718f293a1 |
Table 1. Linux Apps tested under FreeBSD 13-STABLE and 14-CURRENT
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:
-
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". -
You may add the following lines to
/etc/fstab
to supportlinprocfs
,linsysfs
, andtmpfs
: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 -
To mount
linprocfs
,linsysfs
, andtmpfs
run the next commands:mount /compat/linux/proc
mount /compat/linux/sys
mount /compat/linux/dev/shmFreeBSD 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:
-
Enable Linux binary compatibility by running the following commands:
echo 'linux_enable="YES"' >> /etc/rc.conf
-
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" -
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 -
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" -
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
-
Run the next command to create the Ubuntu operating system folders:
mkdir -p /compat/ubuntu/{dev/fd,dev/shm,home,proc,sys,tmp}
-
Enable Ubuntu chroot jail and make it automatically enabled at boot time by running next command:
sysrc ubuntu_enable=YES
-
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
-
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 -
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.tipIf you get an
Permission denied
error, try to runchmod 744 /usr/local/sbin/debootstrap
to fix the bug. -
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
-
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
-
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 -
To fix
apt
package manager, run the next command:printf "APT::Cache-Start 251658240;" > /etc/apt/apt.conf.d/00aptitude
-
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
-
To update Ubuntu packages you may run the following commands:
apt update
apt list --upgradable
apt upgrade
apt autoremove
apt clean -
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.
-
Disable Linux binary compatibility by editing
/etc/rc.conf
:linux_enable="NO"
-
Remove the following lines added for enabling linux bina from
/boot/loader.conf
file.linux_load="YES"
linux64_load="YES"
fdescfs_load="YES"
linprocfs_load="YES"
tmpfs_load="YES"
linsysfs_load="YES" -
Reboot the FreeBSD node:
reboot
-
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.