Setting up a 9front CPU server on a Raspberry Pi 4
2024-03-01 17:52:00
Recently got a Raspberry Pi 4 and I wanted to make it a 9front CPU server. I struggled a bit so here are some notes on what I did.
By default 9front image for Raspberry Pi is quite small around 2GB, I wanted it use my whole 64GB SD Card so I used qemu to boot a 9front terminal and cross-compile a custom Pi4 image with more storage.
Making a custom Pi image
Since my SD Card is 64GB, I first created a qemu image of 100GB just to be safe, most probably less space is needed.
λ qemu-img create -f qcow2 9front.qcow2.img 100G
Then started qemu to boot the 9front iso and the qemu image.
λ qemu-system-x86_64 -enable-kvm \
-smp $(nproc) \
-m $((4*1024)) \
-cpu host \
-M q35 \
-cdrom /path/to/9front.amd64.iso \
-net nic -net user,hostfwd=tcp::17007-:17007,hostfwd=tcp::17010-:17010,hostfwd=tcp::17019-:17019,hostfwd=tcp::17020-:17020,hostfwd=tcp::12564-:564,hostfwd=tcp::12567-:567 \
-drive file=/path/to/9front.qcow2.img,media=disk,index=0,cache=writeback
Ports 564 and 567 are used by drawterm but I can bind them as a non-root user so I bind them to 12564/12567.
When rio is started I made the VM accessible with drawterm.
auth/factotum -g 'key proto=p9sk1 dom=plan9 user=glenda !password=glenda'
aux/listen1 -t tcp!*!rcpu /rc/bin/service/tcp17019 -R &
ip/ipconfig
Then I can use drawterm to connect to the VM
PASS=glenda drawterm -a 'tcp!localhost!12567' -s localhost -h localhost -u glenda
In order to make image size bigger I changed mb=1885 to mb=60000 in the %.pi3.img: section of /sys/lib/dist/mkfile. Now I could build the new ~64GB Pi4 image.
First got to the 9front source dir
cd /sys/src
Built the arm64 userspace
objtype=arm64
mk install
Built the 64-bit kernel for Raspberry Pi ¾, the build script expects both kernels to be present
cd /sys/src/9/bcm64
mk 'CONF=pi3' install
mk 'CONF=pi4' install
Built the bootable hjfs SD Card image for Raspberry Pi ¾
cd /sys/lib/dist
bind / /n/src9
mk /tmp/sdcard.pi3.img
I order to copy the image outside the qemu VM I used /mnt/term
cp /tmp/sdcard.pi3.img /mnt/term/tmp/sdcard.pi3.img
And finally wrote the new image to my SD Card.
dd if=/tmp/sdcard.pi3.img of=/dev/sdb bs=4M oflag=direct status=progress
Turning the Pi into a CPU server
The Pi booted in terminal mode. In order to have it boot in cpu mode I edited cmdline.txt (the plan9.ini equivalent for the Pi). First I mounted the dos partition.
9fs dos
Optional: if it complains that no dos partition is found
bind -b '#S' /dev
Updated /n/dos/cmdline.txt adding nobootprompt (so that the Pi automatically boots into the fs), declaring where the nvram is, that the user is glenda and that this machine is a cpu server.
console=0 nobootprompt=local!/dev/sdN0/fs nvram=/dev/sdN0/nvram user=glenda service=cpu
Adding nvram after nobootprompt was important for some reason otherwise it wouldn’t be taken into account. It’s also mandatory to have all these settings on a single line.
Then I set networking up. To get the ethernet identifier:
ip/ipconfig
cat /net/ether0/addr
I edited /lib/ndb/local to declare my ipnet and sys, I use DHCP.
...
#
# because the public demands the name localhost
#
ip=127.0.0.1 sys=localhost dom=localhost
auth=nein authdom=9front
ipnet=9front ip=192.168.1.0 ipmask=255.255.255.0
ipgw=192.168.1.254
dns=192.168.1.254
auth=nein
dnsdom=9front
cpu=nein
smtp=nein
sys=nein dom=9front ether=<the ethernet identifier>
One last change is giving a password to glenda in nvram and for the local user.
auth/keyfs
nvram=/dev/sdN0/nvram auth/wrkey
authid: glenda
authdom: 9front
secstore key: <press enter to skip>
password: <type your password>
confirm pasword: <retype your password>
auth/changeuser glenda
Password: <same as what's in nvram>
...
Rebooted with fshalt -r, I’m now greeted by the cpu prompt. I need to get the cpu server IP:
cpu% cat /net/ndb
...
ip=192.168.1.76 ipmask=255.255.255.0 ipgw=192.168.1.254
sys=nein
dns=192.168.1.254
And I can finally connect via drawterm to my new CPU server \o/
PASS=<glenda's password> drawterm -h 192.168.1.76 -a 192.168.1.76 -u glenda