2023-05-06
Since aarch64
moved to Tier-1 for FreeBSD, it’s a good
idea to also test your ports on that architecture. But if you don’t own
hardware for that, you will quickly run into limitations with the
qemu-user-static
plus native-xtools
approach
for cross-building. Some ports just won’t work with this.
One possible solution is to subscribe to the Oracle Cloud. They offer some resources as “always free”; you can use them to configure one aarch64 machine with specs good enough for occassional ports testing.
At the moment, you can pick one FreeBSD RELEASE image, which will
give you a root partition with UFS. For ports testing with
poudriere
, you will need ZFS to do it efficiently, and you
should run -CURRENT
to also test that. This
document describes the steps needed to get there.
If you don’t use Oracle Cloud at the moment, register there. You will need to trust them with your credit card info, even if you will only use “always free” resources.
In their portal, look for “compute instances”. You can create an “Ampere” virtual machine there. I won’t describe the full process, it should be more or less obvious anyways and might change in details. Just a few hints:
root
.After first login, check the partition table with
gpart show
. For me, it looked like this:
$ gpart show
=> 3 419430389 da0 GPT (200G)
3 66584 1 efi (33M)
66587 2097152 2 freebsd-swap (1.0G)
2163739 417266653 3 freebsd-ufs (199G)
So, in all the following text, I assume the system partition is
da0p3
and the swap partition is da0p2
.
Make sure to adapt the following commands if your machine has
different partition numbers!
We will first abuse the swap partition to install a temporary system,
so we can then create a zpool on da0p3
in the next step.
Execute the following commands:
$ pkg install git-tiny
$ cd /usr/src
$ git clone https://git.freebsd.org/src.git .
$ cat - >/etc/src.conf
WITHOUT_ACCT=yes
WITHOUT_ACPI=yes
WITHOUT_APM=yes
WITHOUT_ASSERT_DEBUG=yes
WITHOUT_AT=yes
WITHOUT_ATM=yes
WITHOUT_AUDIT=yes
WITHOUT_AUTOFS=yes
WITHOUT_BHYVE=yes
WITHOUT_BLACKLIST=yes
WITHOUT_BLUETOOTH=yes
WITHOUT_BOOTPARAMD=yes
WITHOUT_BOOTPD=yes
WITHOUT_BSDINSTALL=yes
WITHOUT_BSNMP=yes
WITHOUT_CALENDAR=yes
WITHOUT_CAPSICUM=yes
WITHOUT_CCD=yes
WITHOUT_CLANG_FULL=yes
WITHOUT_CUSE=yes
WITHOUT_CXBGETOOL=yes
WITHOUT_DEBUG_FILES=yes
WITHOUT_DICT=yes
WITHOUT_EXAMPLES=yes
WITHOUT_FINGER=yes
WITHOUT_FMTREE=yes
WITHOUT_FREEBSD_UPDATE=yes
WITHOUT_FTP=yes
WITHOUT_GAMES=yes
WITHOUT_GNU_DIFF=yes
WITHOUT_GPIO=yes
WITHOUT_HAST=yes
WITHOUT_HTML=yes
WITHOUT_INETD=yes
WITHOUT_IPFILTER=yes
WITHOUT_IPFW=yes
WITHOUT_ISCSI=yes
WITHOUT_LLVM_ASSERTIONS=yes
WITHOUT_LLVM_COV=yes
WITHOUT_LLVM_TARGET_ALL=yes
WITHOUT_LOCATE=yes
WITHOUT_LPR=yes
WITHOUT_MAIL=yes
WITHOUT_MLX5TOOL=yes
WITHOUT_NDIS=yes
WITHOUT_NETCAT=yes
WITHOUT_NIS=yes
WITHOUT_NTP=yes
WITHOUT_OFED=yes
WITHOUT_OPENMP=yes
WITHOUT_PF=yes
WITHOUT_PMC=yes
WITHOUT_PORTSNAP=yes
WITHOUT_PPP=yes
WITHOUT_PROFILE=yes
WITHOUT_RBOOTD=yes
WITHOUT_ROUTED=yes
WITHOUT_SHAREDOCS=yes
WITHOUT_TALK=yes
WITHOUT_TCP_WRAPPERS=yes
WITHOUT_TCSH=yes
WITHOUT_TELNET=yes
WITHOUT_TESTS=yes
WITHOUT_TFTP=yes
WITHOUT_UNBOUND=yes
WITHOUT_WIRELESS=yes
WITH_MALLOC_PRODUCTION=yes
KERNCONF=GENERIC-NODEBUG
# hit <CTRL+D>
$ make -j4 buildworld buildkernel
$ swapoff -a
$ sed -i '' -e '/swap/d' /etc/fstab
$ gpart modify -i 2 -t freebsd-ufs da0
$ newfs /dev/da0p2
$ mount -t ufs /dev/da0p2 /mnt
$ make DESTDIR=/mnt distrib-dirs distribution installworld installkernel
$ echo 'vfs.root.mountfrom="ufs:/dev/da0p2"' >>/boot/loader.conf
$ cp /etc/rc.conf /mnt/etc/
$ cp /etc/fstab /mnt/etc/
$ cp /etc/ssh/sshd_config /mnt/etc/ssh/
$ cp /boot/loader.conf /mnt/boot/
$ cp -R /root/.ssh /mnt/root/
$ gpart modify -l rootfs-old -i 3 da0
$ gpart modify -l rootfs -i 2 da0
$ umount /mnt
$ shutdown -r now
After reboot, you should see /
is now mounted from
/dev/da0p2
.
In this next step, we will create the zpool and use its
/usr/src
and /usr/obj
datasets to build a full
-CURRENT. We will also enable meta-mode for this, so future
upgrades only need to build what changed.
Here are the commands to do that:
$ gpart modify -i 3 -t freebsd-zfs da0
$ zpool create zroot /dev/da0p3
$ zfs set mountpoint=/zroot zroot
$ zfs create -o mountpoint=none zroot/ROOT
$ zfs create -o mountpoint=/mnt -o canmount=noauto -o readonly=off zroot/ROOT/default
$ zfs mount zroot/ROOT/default
$ zpool set bootfs=zroot/ROOT/default zroot
$ zfs create -o mountpoint=/mnt/tmp -o exec=on -o setuid=off zroot/tmp
$ zfs create -o mountpoint=/mnt/usr -o canmount=off zroot/usr
$ zfs create zroot/usr/home
$ ln -s usr/home /mnt/home
$ zfs create zroot/usr/src
$ zfs create zroot/usr/obj
$ zfs create -o mountpoint=/mnt/var -o canmount=off zroot/var
$ zfs create -o exec=off -o setuid=off zroot/var/audit
$ zfs create -o exec=off -o setuid=off zroot/var/crash
$ zfs create -o exec=off -o setuid=off zroot/var/log
$ zfs create -o atime=on zroot/var/mail
$ zfs create -o setuid=off zroot/var/tmp
$ mount -t nullfs /mnt/usr/src /usr/src
$ mount -t nullfs /mnt/usr/obj /usr/obj
$ mkdir /mnt/usr/local
$ mount -t nullfs /mnt/usr/local /usr/local
$ pkg install git-tiny
$ cd /usr/src
$ git clone https://git.freebsd.org/src.git .
$ cat - >/etc/src.conf
WITHOUT_ASSERT_DEBUG=yes
WITHOUT_LLVM_ASSERTIONS=yes
WITHOUT_TESTS=yes
WITH_MALLOC_PRODUCTION=yes
KERNCONF=GENERIC-NODEBUG
# hit <CTRL+D>
$ cat - >/etc/src-env.conf
WITH_META_MODE=yes
# hit <CTRL+D>
$ kldload filemon
$ make -j4 buildworld buildkernel
$ make DESTDIR=/mnt BATCH_DELETE_OLD_FILES=yes distrib-dirs distribution installworld installkernel delete-old delete-old-libs
$ sed -i '' -e 's,ufs.*,zfs:zroot/ROOT/default",' /boot/loader.conf
$ cp /etc/src*.conf /mnt/etc/
$ cp /etc/rc.conf /mnt/etc/
$ cp /etc/ssh/sshd_config /mnt/etc/ssh/
$ cp /boot/loader.conf /mnt/boot/
$ cp /mnt/boot/loader.efi /boot/efi/EFI/BOOT/bootaa64.efi
$ cp -R /root/.ssh /mnt/root/
$ touch /mnt/etc/fstab
$ cd
$ umount /usr/src
$ umount /usr/obj
$ umount /usr/local
$ rm -fr /mnt/usr/local
$ zfs umount -a
$ umount /mnt
$ zfs set mountpoint=/ zroot/ROOT/default
$ zfs set mountpoint=/tmp zroot/tmp
$ zfs set mountpoint=/usr zroot/usr
$ zfs set mountpoint=/var zroot/var
$ zpool export zroot
$ umount /boot/efi
$ shutdown -r now
After that reboot succeeded, you should see the system running from a ZFS root now. We will do some minor adjustments and re-enable swap, and then reboot again just to check everything works correctly.
Here you might want to first add filemon
to
kld_list
in /etc/rc.conf
, so it’s always
available for building with meta-mode later. Then, also do the
following steps.
$ sed -i '' -e '/opensolaris/d' -e '/mountfrom/d' /boot/loader.conf
$ gpart modify -i 2 -t freebsd-swap -l swap da0
$ dd if=/dev/zero of=/dev/da0p2 bs=1M
$ cat - >/etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/gpt/swap none swap sw 0 0
# hit <CTRL+D>
$ etcupdate extract
$ shutdown -r now
The following commands are really just recommendations for setting up
poudriere. They will install poudriere jails of all currently supported
RELEASE versions (at the time of writing 12.4-RELEASE and 13.2-RELEASE)
and manually create a -CURRENT jail from our source tree. A ports tree
for poudriere will be fetched with git
.
Then, we’ll bulk build a small list of packages (the example here
shows what I find useful for work on ports), configure pkg
to use our local repository, and install them.
$ pkg install git-tiny poudriere-devel
$ vi /usr/local/etc/poudriere.conf
Here, you should configure the following:
ZPOOL
settingFREEBSD_HOST
as explainedDISTFILE_CACHE
, I recommend
${BASEFS}/data/distfiles
ALLOW_MAKE_JOBS=yes
PACKAGE_FETCH_BRANCH=latest
$ poudriere jail -c -j 124 -v 12.4-RELEASE -m ftp
$ poudriere jail -c -j 132 -v 13.2-RELEASE -m ftp
$ zfs create zroot/poudriere/jails/14
$ cd /usr/src
$ make DESTDIR=/usr/local/poudriere/jails/14 BATCH_DELETE_OLD_FILES=yes distrib-dirs distribution installworld delete-old delete-old-libs
$ etcupdate extract -D /usr/local/poudriere/jails/14
$ poudriere jail -c -j 14 -v 14.0-CURRENT -M /usr/local/poudriere/jails/14 -m null -S /usr/src
$ zfs create zroot/poudriere/data/distfiles
$ zfs create zroot/poudriere/ports/default
$ cd /usr/local/poudriere/ports/default
$ git clone https://git.freebsd.org/ports.git .
$ cd
$ poudriere ports -c -p default -M /usr/local/poudriere/ports/default -m null
$ cat - >ports.txt
devel/git
devel/rclint
editors/vim
ports-mgmt/portfmt
ports-mgmt/portlint
ports-mgmt/poudriere-devel
shells/zsh
sysutils/tmux
# hit <CTRL+D>
$ poudriere bulk -j 14 -p default -f ~/ports.txt
$ ln -s 14-default /usr/local/poudriere/data/packages/local
$ mkdir -p /usr/local/etc/pkg/repos
$ cat - >/usr/local/etc/pkg/repos/FreeBSD.conf
FreeBSD: { enabled: NO }
# hit <CTRL+D>
$ cat - >/usr/local/etc/pkg/repos/local.conf
local: { url: file:///usr/local/poudriere/data/packages/local }
# hit <CTRL+D>
$ pkg upgrade -f
$ pkg install git vim portlint portfmt rclint tmux zsh
$ pkg autoremove
$ pkg clean
Yes, please do so ;)
Of course, if you’re reading this howto, I’m sure you already know
how to upgrade your machine. Still, I’ll document the procedure I would
recommend here. We’ll start with upgrading the src
tree and
building again:
$ cd /usr/src
$ git pull
$ kldload filemon # only if you didn't add it to kld_list
$ make -j4 buildworld buildkernel
$ bectl create new
$ bectl mount new /mnt
$ make DESTDIR=/mnt BATCH_DELETE_OLD_FILES=yes installworld installkernel delete-old
$ etcupdate -D /mnt
$ etcupdate resolve -D /mnt # only in case of conflicts
$ bectl umount new
$ bectl activate -t new
$ shutdown -r now
Now, let’s upgrade our -CURRENT
poudriere jail as
well:
$ cd /usr/src
$ zfs rollback zroot/poudriere/jails/14@clean
$ zfs destroy zroot/poudriere/jails/14@clean
$ make DESTDIR=/usr/local/poudriere/jails/14 BATCH_DELETE_OLD_FILES=yes installworld delete-old delete-old-libs
$ etcupdate -D /usr/local/poudriere/jails/14
$ zfs snapshot zroot/poudriere/jails/14@clean
$ touch /usr/local/poudriere/jails/14/.poudriere-snap-clean
$ date +%s >/usr/local/etc/poudriere.d/jails/14/timestamp
We probably also want to upgrade ports here …
$ cd /usr/local/poudriere/ports/default
# This assumes we're on the main branch. Otherwise, you will hopefully know
# how to upgrade ...
$ git pull
And then, update our local package repository and upgrade packages from there.
$ poudriere bulk -j 14 -p default -c -f ~/ports.txt
$ pkg upgrade -f
$ pkg autoremove
$ pkg clean
If everything went fine so far, it’s time to make the new boot environment the default. And if something went wrong, well just reboot. In that case, you will have to re-install your poudriere jail as it’s outside the boot environment.
But let’s assume everything went fine and finish this:
$ bectl rename default old
$ bectl rename new default
$ bectl activate default
$ shutdown -r now
$ cd /usr/src
$ make BATCH_DELETE_OLD_FILES=yes delete-old-libs
Now, you could remove the old
boot environment with
bectl destroy old
whenever you feel comfortable to do
so.