Installing Alpine Linux in 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 into 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 in 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.20/releases/x86_64/alpine-minirootfs-3.20.2-x86_64.tar.gz
tar zxf alpine-minirootfs-3.20.2-x86_64.tar.gz
rm alpine-minirootfs-3.20.2-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.