Skip to content
/ vmcli Public
forked from gyf304/vmcli

Arch Linux on macOS's Virtualization.framework

License

Notifications You must be signed in to change notification settings

cynecx/vmcli

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VMCLI

A set of utilities to help you manage VMs with Virtualization.framework

Installation

Prerequisites

  • macOS Ventura (13+)
  • XCode.app installed
# make sure xcode command-line tools are installed
xcode-select --install

# run build (produces ./build/vmcli)
make

Arch Linux from scratch

Preparations:

# PWD=./

mkdir arch && cd arch # this will contain all vm related data

# prepare disk image (eg. 20GiB)
dd if=/dev/null of="$(pwd)/disk.img" bs=1m count=0 seek=20000

Fetch archboot images:

# PWD=./arch

mkdir archboot && cd archboot

# Fetch archboot's linux kernel image
wget -O linux.gz "https://archboot.com/iso/aarch64/latest/boot/Image-aarch64.gz"
gzip -d linux.gz

# Fetch archboot's initrd
wget -O initrd https://archboot.com/iso/aarch64/latest/boot/initrd-aarch64.img

Boot archboot:

# PWD=./arch

# Boot archboot and use the `disk.img` image
# Note: archboot requires somewhat >1GB ram to boot
vmcli -b linux -k ./archboot/linux --initrd ./archboot/initrd -d ./disk.img -m 1536 --cmdline "console=hvc0 irqaffinity=0 mitigations=off root=/dev/vda"

# Follow the archboot instructions
# Tip: Just exit/cancel the initial setup and use the default configuration, so you get faster to a working shell.

    [root@archboot /]#

Inside archboot, continue with a basic Arch Linux installation.

Requirements:

  • Partition table should preferrably be GPT
  • Virtualization.framework supports booting EFI compatible systems, so make sure your installation is "EFI supported", that includes having a EFI system partition and an EFI enabled bootloader

One possible way to install Arch Linux:

# Inside archboot

# First partition disk
fdisk /dev/vda

# Create GPT table
fdisk> g

# Create boot partition
fdisk> n

Command (m for help): n
Partition number (1-128, default 1):
First sector (2048-4095966, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-4095966, default 4093951): +500M

Created a new partition 1 of type 'Linux filesystem' and of size 500 MiB.

# Change boot partition type to EFI system
fdisk> t

Command (m for help): t
Selected partition 1
Partition type or alias (type L to list all): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.

# Create root partition
fdisk> n

Command (m for help): n
Partition number (2-128, default 2):
First sector (1026048-4095966, default 1026048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1026048-4095966, default 4093951):

Created a new partition 2 of type 'Linux filesystem' and of size 1.5 GiB.

# Save changes
fdisk> w

# Partition table should look like:
[root@archboot /]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
zram0  251:0    0    4G  0 disk /
vda    253:0    0    2G  0 disk
|-vda1 253:1    0  500M  0 part
`-vda2 253:2    0  1.5G  0 part

# Format partitions
mkfs.fat -F 32 /dev/vda1
mkfs.ext4 /dev/vda2

# Mount partitions
mount /dev/vda2 /mnt
mkdir /mnt/boot
mount /dev/vda1 /mnt/boot

# Install base packages
# Note: I'd usually go for systemd-boot but somehow Virtualization.framework doesn't boot with that. GRUB however, booted fine, so we'll go with that.
pacstrap -K /mnt base linux-aarch64 archlinuxarm-keyring grub vim

# Basic configuration
genfstab -U /mnt >> /mnt/etc/fstab

arch-chroot /mnt
echo "vm" > /etc/hostname
passwd

# Install GRUB bootloader
# Note: The --removable flag is important. That causes grub to put the booloader as `/boot/EFI/BOOT/BOOTAA64.EFI` which is kinda the default lookup place when the nvram doesn't have any bootloader entries.
grub-install --target=arm64-efi --efi-directory=/boot --bootloader-id=GRUB --removable

# Change `GRUB_CMDLINE_LINUX_DEFAULT` inside `/etc/default/grub`
vim /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="console=hvc0 irqaffinity=0 mitigations=off"
# Change timeouts because they are useless when running headless
GRUB_DEFAULT=0
GRUB_TIMEOUT=0

# Default grub doesn't appear to find the initramfs image.
# Fix that by applying this patch
--- a/etc/grub.d/10_linux	2023-07-25 01:29:17.628000113 +0200
+++ b/etc/grub.d/10_linux	2023-07-25 01:28:58.621000104 +0200
@@ -236,7 +236,8 @@
 	   "initramfs-genkernel-${version}" \
 	   "initramfs-genkernel-${alt_version}" \
 	   "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
-	   "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
+	   "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}" \
+	   "initramfs-linux.img"; do
     if test -e "${dirname}/${i}" ; then
       initrd_real="${i}"
       break

# Generate grub config
grub-mkconfig -o /boot/grub/grub.cfg

# Exit
exit

# Unmount
umount -R /mnt

# Shutdown
poweroff

The initial setup is done. Now you should be able to boot into the system with the EFI bootloader:

# PWD=./arch

# Note: Make use to use a fixed mac address for the network interface, so the dhcp service will try to always assign a stable ip address.
vmcli -b efi --efivars ./efivars -d ./disk.img -m 512 -n 74:a5:1a:d1:78:ed@nat

You should have a working Arch Linux. As mentioned above this is a very minimal installation. You probably need to setup things like networking and other stuff afterwards too.

About

Arch Linux on macOS's Virtualization.framework

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 97.4%
  • Makefile 2.6%