From 161d9307bc61add2ee79fd7df7f619fc1fa60acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Nordstr=C3=B8m?= Date: Sat, 17 Jan 2026 02:28:44 +0100 Subject: [PATCH] Initial commit. --- .gitignore | 4 + README.md | 171 +++++++++++++++++++++++++++ cloudinit-data/simple/meta-data.yaml | 2 + cloudinit-data/simple/user-data.yaml | 27 +++++ 4 files changed, 204 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 cloudinit-data/simple/meta-data.yaml create mode 100644 cloudinit-data/simple/user-data.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0fcdee --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/efi/ +/qcow2/ +/user-data-iso/ +/vm/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..1238cee --- /dev/null +++ b/README.md @@ -0,0 +1,171 @@ +# FreeBSD 15 cloudinit VMs + +Configs and details for how to set up and run FreeBSD 15 cloudinit VMs +in QEMU on Apple Silicon machines such as MacBook Pro M1. + +## Install tools on host + +On your Apple Silicon machine, install Homebrew if you haven't already. + + + +Then use Homebrew to install QEMU, cdrtools, wget and xz: + +```zsh +brew install qemu cdrtools wget xz +``` + +## Create directories on host + +Create the following directories inside your local clone of this repo. + +```zsh +mkdir -p efi/ qcow2/ user-data-iso/ vm/ +``` + +At this point, you should have the following directory structure: + +```text +. +├── README.md +├── cloudinit-data +│   └── simple +│   ├── meta-data.yaml +│   └── user-data.yaml +├── efi +├── qcow2 +├── user-data-iso +└── vm +``` + +## Download FreeBSD and EFI files + +Download FreeBSD 15 VM image and uncompress it: + +```zsh +cd qcow2/ +wget https://download.freebsd.org/releases/VM-IMAGES/15.0-RELEASE/aarch64/Latest/FreeBSD-15.0-RELEASE-arm64-aarch64-BASIC-CLOUDINIT-zfs.qcow2.xz +unxz FreeBSD-15.0-RELEASE-arm64-aarch64-BASIC-CLOUDINIT-zfs.qcow2.xz +cd .. +``` + +Download and extract EFI files: + +```zsh +cd efi/ +wget https://gist.github.com/niw/4f1f9bb572f40d406866f23b3127919b/raw/f546faea68f4149c06cca88fa67ace07a3758268/QEMU_EFI-cb438b9-edk2-stable202011-with-extra-resolutions.tar.gz +tar xf QEMU_EFI-cb438b9-edk2-stable202011-with-extra-resolutions.tar.gz +cd .. +``` + +We will be reusing these files for each of our VMs. + +## Prepare files for VM + +Create cloudinit config ISO for first VM from config files +using mkisofs from cdrtools: + +```zsh +mkisofs \ + -o user-data-iso/simple.iso \ + -volid cidata \ + -joliet -rock \ + -input-charset utf-8 \ + -quiet \ + -graft-points \ + user-data=cloudinit-data/simple/user-data.yaml \ + meta-data=cloudinit-data/simple/meta-data.yaml +``` + +Create directory for VM files: + +```zsh +mkdir -p vm/simple/ +``` + +Create EFI files for the VM: + +```zsh +dd if=/dev/zero of=vm/simple/pflash0.img bs=1m count=64 +dd if=/dev/zero of=vm/simple/pflash1.img bs=1m count=64 +dd if=efi/QEMU_EFI.fd of=vm/simple/pflash0.img conv=notrunc +dd if=efi/QEMU_VARS.fd of=vm/simple/pflash1.img conv=notrunc +``` + +Copy FreeBSD 15 cloudinit image for the VM: + +```zsh +cp \ + qcow2/FreeBSD-15.0-RELEASE-arm64-aarch64-BASIC-CLOUDINIT-zfs.qcow2 \ + vm/simple/hdd0.qcow2 +``` + +At this point, you should have the following directory structure: + +```text +. +├── README.md +├── cloudinit-data +│   └── simple +│   ├── meta-data.yaml +│   └── user-data.yaml +├── efi +│   ├── QEMU_EFI-cb438b9-edk2-stable202011-with-extra-resolutions.tar.gz +│   ├── QEMU_EFI.fd +│   └── QEMU_VARS.fd +├── qcow2 +│   └── FreeBSD-15.0-RELEASE-arm64-aarch64-BASIC-CLOUDINIT-zfs.qcow2 +├── user-data-iso +│   └── simple.iso +└── vm + └── simple + ├── hdd0.qcow2 + ├── pflash0.img + └── pflash1.img +``` + +Boot the VM in QEMU: + +```zsh +qemu-system-aarch64 \ + -M virt \ + -accel hvf \ + -cpu host \ + -smp 4 \ + -m 4096 \ + -drive file=vm/simple/pflash0.img,format=raw,if=pflash,readonly=on \ + -drive file=vm/simple/pflash1.img,format=raw,if=pflash \ + -device virtio-gpu-pci \ + -display default,show-cursor=on \ + -device qemu-xhci \ + -device usb-kbd \ + -device usb-tablet \ + -device intel-hda \ + -device hda-duplex \ + -drive file=vm/simple/hdd0.qcow2,format=qcow2,cache=writethrough \ + -nographic \ + -serial mon:stdio \ + -netdev user,id=net0,hostfwd=tcp::2222-:22 \ + -device virtio-net-pci,netdev=net0 \ + -device virtio-scsi-pci,id=scsi0 \ + -drive file=user-data-iso/simple.iso,format=raw,readonly=on,if=none,id=cdrom0 \ + -device scsi-cd,drive=cdrom0 +``` + +A bunch of text will scroll by, and you will see FreeBSD updating itself to latest version if necessary, and FreeBSD installing the packages that we have in the cloud-init configs, and doing other cloud-init steps. + +After a pretty short amount of time, you should see the login prompt: + +```text +FreeBSD/arm64 (simple-vm) (ttyu0) + +login: +``` + +We see here that hostname has been set according to our cloud-init configs. + +Log in as user `simple-user` + +Enter password `hest123` + +Now you are logged in on the VM :D diff --git a/cloudinit-data/simple/meta-data.yaml b/cloudinit-data/simple/meta-data.yaml new file mode 100644 index 0000000..130e5bf --- /dev/null +++ b/cloudinit-data/simple/meta-data.yaml @@ -0,0 +1,2 @@ +instance-id: simple-vm-1 +local-hostname: simple-vm diff --git a/cloudinit-data/simple/user-data.yaml b/cloudinit-data/simple/user-data.yaml new file mode 100644 index 0000000..10c3c91 --- /dev/null +++ b/cloudinit-data/simple/user-data.yaml @@ -0,0 +1,27 @@ +#cloud-config +groups: +- cloud-users +users: +- name: simple-user + gecos: Simple User + primary_group: simple-user + doas: [permit nopass simple-user, deny simple-user as root] + shell: /bin/tcsh + groups: wheel, cloud-users + plain_text_passwd: hest123 +- name: user3 + gecos: User the Third + primary_group: user3 + shell: /bin/tcsh + groups: cloud-users + plain_text_passwd: changeme +chpasswd: + expire: false + users: + - {name: root, password: hest123, type: text} + - {name: user3, type: RANDOM} +ssh_pwauth: true +packages: +- doas +- git +- curl