Cookie Consent by TermsFeed

Installing Alpine Linux on a FreeBSD Jail

Installing Alpine Linux on a FreeBSD Jail

Installing Alpine Linux on a FreeBSD Jail

Alpine Linux is one of my favorite Linux distributions, particularly for specialized purposes. I recently faced the task of moving an Alpine Linux-based VPS onto a FreeBSD host and considered two approaches:

1. Moving the VPS to bhyve on FreeBSD

The simplest and more conventional method involves transferring the VPS to the FreeBSD host and running it on bhyve. This solution is proven and stable. However, bhyve doesn’t support memory ballooning. The assigned and unused memory - used by the Alpine VPS for caching but rendered unnecessary since FreeBSD performs its own caching - led me to explore another method.

2. Using Linuxulator

With the Linuxulator, I thought about creating a jail and copying Alpine Linux into it, attempting to run all necessary services (not many, but complex enough to initially discourage a direct migration to FreeBSD). This approach wasn’t pioneering, as it’s been used by others (and myself in other situations), but I had never applied it to Alpine Linux before.

The Implementation

I won’t describe the entire process of what I did - it turned out to be straightforward: I prepared a Linux jail, configured it, performed an rsync of the entire filesystem of the original VPS, fixed a few things, and started it up. However, I will explain how I create and use Alpine Linux jails on FreeBSD hosts without any jail management software (like BastilleBSD, iocage, ezjail, etc.). Many aren’t aware that managing the entire jail lifecycle is already integrated into FreeBSD and that these tools are helpful but not strictly necessary.

Enabling Linuxulator

First, enable and start the Linuxulator on the FreeBSD server:

service linux enable
service linux start

This loads all necessary modules for executing Linux-compiled executables.

Setting Up the Jail

Choose the path for installing the jail. There’s no need to use ZFS for this type of setup; UFS is sufficient.

Create the path, for example, /var/jails, and the path for the individual jail, such as /var/jails/alpine01:

mkdir -p /var/jails/alpine01

Download the Alpine Linux base filesystem directly from the Alpine Linux website and decompress it in the newly created directory.

cd /var/jails/alpine01
fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/x86_64/alpine-minirootfs-3.19.0-x86_64.tar.gz
tar zxf alpine-minirootfs-3.19.0-x86_64.tar.gz
rm alpine-minirootfs-3.19.0-x86_64.tar.gz

In theory, the base system is already functional, but some services might complain about missing configurations. It’s advisable to create the file /etc/network/interfaces:

echo "auto lo" > /var/jails/alpine01/etc/network/interfaces

And if you want to use openrc:

touch /var/jails/alpine01/run/openrc/softlevel

Starting the Jail

The jail is now ready to be launched. There are two approaches: include its configuration in /etc/jail.conf of the FreeBSD server or create a separate file and launch it manually. The latter allows for interesting possibilities: everything related to the jail lives in the /var/jails directory, which could be on a different device, even NFS or external. This approach is also applicable for FreeBSD jails and is convenient for portable jails or those used from encrypted/separated devices.

Following this second approach, create a file named /var/jail/alpine01.conf containing:

alpine01 {
    host.hostname = "${name}";
    #exec.consolelog = "/var/log/jail_console_${name}.log";
    ip4.addr= 192.168.1.111;
    interface = vtnet0;
    path="/var/jails/${name}";
    allow.raw_sockets=1;
    #exec.start='/sbin/openrc';
    exec.start='/bin/true';
    exec.stop='/bin/true';
    persist;
    mount.fstab="/var/jails/${name}.fstab";
}

I intentionally left the console log lines and the start of openrc commented out (not everyone wants them), and openrc is currently not present in the jail.

Adjust the assigned IP and interface based on your configuration.

Create the jail’s fstab, /var/jail/alpine01.fstab:

devfs           /var/jails/alpine01/dev      devfs           rw                      0       0
tmpfs           /var/jails/alpine01/dev/shm  tmpfs           rw,size=1g,mode=1777    0       0
fdescfs         /var/jails/alpine01/dev/fd   fdescfs         rw,linrdlnk             0       0
linprocfs       /var/jails/alpine01/proc     linprocfs       rw                      0       0
linsysfs        /var/jails/alpine01/sys      linsysfs        rw                      0       0

Launching and Testing the Jail

To launch the jail:

jail -crm -f alpine01.conf

For testing:

jexec alpine01 login -f root

Welcome to your new Alpine Linux jail. Once in the jail, don’t forget to add the nameserver in /etc/resolv.conf, or the jail won’t be able to perform DNS resolutions:

echo "nameserver 1.1.1.1" > /etc/resolv.conf

To simulate a real Alpine Linux boot as closely as possible, I suggest installing openrc:

apk add openrc

Then you can modify the alpine01.conf file. Exit the jail and adjust as follows:

#exec.start='/bin/true';
exec.start='/sbin/openrc';

Now, you can restart the jail and see openrc start services (currently, none) inside the jail:

jail -r alpine01
jail -crm -f alpine01.conf

The jail is now ready.

The Linuxulator can’t emulate all Linux syscalls, so some things might not work or only work partially. However, it’s more than adequate for many uses. The same approach can also be used for other distributions. A convenient method to download the root file systems of various distributions is to look for those already created for LXC, freely downloadable as regular files.

FreeBSD jail's embrace,
Alpine's freedom finds its place,
Unix worlds in grace.

See also