Wong's Cafe
2025-02-27
My FreeBSD is so beefy that I want it to build some of my custom Android OS, However, it's not that simple as on linux, so I ended up using a linux jail just for that.
Enable Linux ABI:
doas sysrc linux_enable="YES"
doas service linux start
A thin jail is needed to bootstrap a Debian Linux Distribution.
Follow the FreeBSD Handbook, as shown below:
# Jail template
doas fetch https://mirrors.ustc.edu.cn/freebsd/releases/amd64/amd64/14.2-RELEASE/base.txz -o /usr/local/jails/media/14.2-RELEASE-base.txz
doas tar -xf /usr/local/jails/media/14.2-RELEASE-base.txz -C /usr/local/jails/templates/14.2-RELEASE --unlink
# Set up dns and time zone
doas cp /etc/resolv.conf /usr/local/jails/templates/14.2-RELEASE/etc/resolv.conf
doas cp /etc/localtime /usr/local/jails/templates/14.2-RELEASE/etc/localtime
# Update the jail to next patch level
doas freebsd-update -b /usr/local/jails/templates/14.2-RELEASE/ fetch install
# Snapshot the template
doas zfs snapshot zroot/jails/templates/14.2-RELEASE@base
# Clone snapshot from template
doas zfs clone zroot/jails/templates/14.2-RELEASE@base zroot/jails/containers/debian
We stop at the configuration part, and then we configure the jail with a special linux configuration:
doas jail -cm \
name=debian \
host.hostname="debian.latinus.local" \
path="/usr/local/jails/containers/debian" \
interface="re0" \
ip4="inherit"\
exec.start="/bin/sh /etc/rc" \ exec.stop="/bin/sh /etc/rc.shutdown" \
mount.devfs \
devfs_ruleset=4 \
allow.mount \
allow.mount.devfs \
allow.mount.fdescfs \
allow.mount.procfs \
allow.mount.linprocfs \
allow.mount.linsysfs \
allow.mount.tmpfs \
enforce_statfs=1
The following output should be seen, which means the jail is successfully created.
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
32-bit compatibility ldconfig path: /usr/lib32
Updating motd:.
Creating and/or trimming log files.
Clearing /tmp (X related).
Updating /var/run/os-release done.
Starting syslogd.
Starting cron.
Thu Feb 27 15:16:25 CST 2025
Optionally, now you can change mirrors from /usr/local/jails/containers/debian
, see my article for more info.
su into the jail and bootstrap debian:
pkg install debootstrap
# Optionally append a mirror url, like https://mirrors.cernet.edu.cn/debian/
debootstrap stable /compat/ubuntu
After the command finish, the I: Base system installed successfully.
message should be displayed on the console.
Use exit
to leave the jail, and write the following :
debian {
# STARTUP/LOGGING
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.consolelog = "/var/log/jail_console_${name}.log";
# PERMISSIONS
allow.raw_sockets;
exec.clean;
mount.devfs;
devfs_ruleset = 4;
# HOSTNAME/PATH
host.hostname = "${name}";
path = "/usr/local/jails/containers/${name}";
# NETWORK
ip4 = inherit;
interface = em0;
# MOUNT
mount += "devfs $path/compat/debian/dev devfs rw 0 0";
mount += "tmpfs $path/compat/debian/dev/shm tmpfs rw,size=1g,mode=1777 0 0";
mount += "fdescfs $path/compat/debian/dev/fd fdescfs rw,linrdlnk 0 0";
mount += "linprocfs $path/compat/debian/proc linprocfs rw 0 0";
mount += "linsysfs $path/compat/debian/sys linsysfs rw 0 0";
mount += "/tmp $path/compat/debian/tmp nullfs rw 0 0";
# Share /home directory
# mount += "/home $path/compat/debian/home nullfs rw 0 0";
}
Stop the jail:
doas service jail onestop debian
Enable jail in rc.conf:
linux_enable="YES"
jail_enable="YES"
jail_parallel_start="YES"
And start the jail.
doas service jail start debian
Then, you can access the jail via:
doas jexec debian chroot /compat/debian /bin/bash
When running the following, the error occurs:
# Notice stop is used without arguments.
service jail stop
service jail start debian
Starting jails: cannot start jail "debian":
mount_nullfs: /usr/local/jails/containers/debian/compat/debian/tmp: Resource deadlock avoided
jail: debian: /sbin/mount -t nullfs -o rw /tmp /usr/local/jails/containers/debian/compat/debian/tmp: failed
This is because when stopping the jail, some mountpoints are not umount
ed, so, we need to manually umount:
Run the following with su is easier.
mount | grep -v zroot | grep debian
to see what needs to be u-mounted, then unmount them manually:
umount /usr/local/jails/containers/debian/compat/debian/dev/shm
umount /usr/local/jails/containers/debian/compat/debian/dev/fd
umount /usr/local/jails/containers/debian/compat/debian/dev
umount /usr/local/jails/containers/debian/compat/debian/proc
umount /usr/local/jails/containers/debian/compat/debian/sys
umount /usr/local/jails/containers/debian/compat/debian/tmp
umount /usr/local/jails/containers/debian/compat/debian/home
cd /usr/local/jails
# Make new dataset
doas zfs create zroot/jails/templates/debian
# Copy files there
doas rsync -av containers/debian/ templates/debian/
# Take snapshot
doas zfs snapshot zroot/jails/templates/debian@base
You should probably stop the original debian jail:
doas service jail stop debian
doas zfs clone zroot/jails/templates/debian@base zroot/jails/containers/debian_dev
And copy or move the debian jail to another one.
cd /etc/jail.conf.d
doas mv debian.conf debian_dev.conf
doas nvim $_
Then edit the debian name to something else, for this example, debian_dev
Then, start the jail:
doas service jail start debian_dev
Enter the jail
doas jexec debian_dev chroot /compat/debian /bin/bash
Install stuff, and set up a normal user account:
apt update
apt upgrade
apt install zsh sudo neovim man kitty-terminfo # Some stuff I found convenient
# Set up account
useradd --create-home --shell /bin/zsh android --groups sudo
Edit line 50 of /etc/sudoers
:
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
Add contrib branch for debian, edit /etc/apt/sources.list
deb https://mirrors.cernet.edu.cn/debian stable main contrib
Then refresh the apt cache:
apt update
Su into the new user, and install packages from lineageOS's wiki: [1]
su -l android
sudo apt install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf imagemagick lib32readline-dev lib32z1-dev libelf-dev liblz4-tool lz4 libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev
Also set the default python version:
sudo apt install python-is-python3
Some other dependencies:
sudo apt install repo android-sdk-platform-tools
Configure git:
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
Use a mirror for LineageOS pull: [2]
repo init -u https://mirrors.cernet.edu.cn/lineageOS/LineageOS/android.git -b lineage-21.0 --git-lfs
Then, follow along from either official documentation [3] or un-official ones [4].