diff --git a/content/posts/nixos-disk-images-m1/1-os-dialog.png b/content/posts/nixos-disk-images-m1/1-os-dialog.png new file mode 100644 index 0000000..be4d096 Binary files /dev/null and b/content/posts/nixos-disk-images-m1/1-os-dialog.png differ diff --git a/content/posts/nixos-disk-images-m1/2-disable-iso-boot.png b/content/posts/nixos-disk-images-m1/2-disable-iso-boot.png new file mode 100644 index 0000000..f2b7412 Binary files /dev/null and b/content/posts/nixos-disk-images-m1/2-disable-iso-boot.png differ diff --git a/content/posts/nixos-disk-images-m1/3-open-vm-settings.png b/content/posts/nixos-disk-images-m1/3-open-vm-settings.png new file mode 100644 index 0000000..4b70ea6 Binary files /dev/null and b/content/posts/nixos-disk-images-m1/3-open-vm-settings.png differ diff --git a/content/posts/nixos-disk-images-m1/4-delete-volume.png b/content/posts/nixos-disk-images-m1/4-delete-volume.png new file mode 100644 index 0000000..39af017 Binary files /dev/null and b/content/posts/nixos-disk-images-m1/4-delete-volume.png differ diff --git a/content/posts/nixos-disk-images-m1/5-import-image.png b/content/posts/nixos-disk-images-m1/5-import-image.png new file mode 100644 index 0000000..c0fcf92 Binary files /dev/null and b/content/posts/nixos-disk-images-m1/5-import-image.png differ diff --git a/content/posts/nixos-disk-images-m1/configuration.nix b/content/posts/nixos-disk-images-m1/configuration.nix new file mode 100644 index 0000000..729719f --- /dev/null +++ b/content/posts/nixos-disk-images-m1/configuration.nix @@ -0,0 +1,43 @@ +{ config, modulesPath, pkgs, lib, ... }: +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + + networking.hostName = "thinnix"; + networking.useDHCP = false; + networking.interfaces.enp0s5.useDHCP = true; + + users.users.root.initialPassword = "changeme"; + + boot.kernelParams = ["console=ttyAMA0,115200n8" "console=tty0"]; + boot.consoleLogLevel = lib.mkDefault 7; + + boot.growPartition = true; + # not sure if needed + boot.initrd.kernelModules = [ "nvme" ]; + boot.loader.grub = { + efiSupport = true; + efiInstallAsRemovable = true; + device = "nodev"; + }; + + fileSystems."/" = { device = "/dev/vda2"; fsType = "ext4"; }; + fileSystems."/boot" = { device = "/dev/vda1"; fsType = "vfat"; }; + + nixpkgs.localSystem.system = "aarch64-linux"; + + system.build.image = import { + diskSize = 10000; + format = "qcow2-compressed"; + installBootLoader = true; + partitionTableType = "efi"; + inherit config lib pkgs; + }; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? +} diff --git a/content/posts/nixos-disk-images-m1/index.md b/content/posts/nixos-disk-images-m1/index.md new file mode 100644 index 0000000..94b4755 --- /dev/null +++ b/content/posts/nixos-disk-images-m1/index.md @@ -0,0 +1,107 @@ ++++ +date = "2022-06-21" +draft = false +path = "/blog/nixos-disk-images-m1" +tags = ["nix", "nixos"] +title = "Adventures in building disk images of NixOS virtual machines for M1" ++++ + +I work in a thoroughly Nix-based environment, and sometimes I need to test +NixOS things, but I have a Mac at work. So, time to get a NixOS VM going on the +M1, I guess! This was a partially-planned adventure. + +People I know have been saying good things about the (mostly) qemu wrapper +[UTM] ([also on GitHub here][utm-github]), so that was the tool of choice. + +[UTM]: https://mac.getutm.app/ +[utm-github]: https://github.com/utmapp/UTM + +I kind of didn't realize there were [normal installer images that would +absolutely just work][images-lol] (since UTM implements UEFI by default), so I +tried a more fun option: just build the root filesystem offline and import it. + +[images-lol]: https://nixos.wiki/wiki/NixOS_on_ARM/UEFI#Getting_the_installer_image_.28ISO.29 + +To do this, you will need a Linux machine with Nix and the capacity to execute +aarch64 binaries, either by emulation with binfmt-misc and qemu-user on Linux, +or natively because you have an aarch64-linux computer with Nix on it. I have +the latter because Oracle Cloud [apparently just gives away 24GB memory aarch64 +instances for free][oracle-lol]. + +[oracle-lol]: https://www.oracle.com/ca-en/cloud/free/#always-free + +NixOS has infrastructure for building disk images of systems, so it's more or +less a case of doing it, with the correct configuration. + +The config for the bootloader is also [documented on the NixOS +wiki here][uefi-bootloader]. The listed config worked for me, which is: + +[uefi-bootloader]: https://nixos.wiki/wiki/NixOS_on_ARM/UEFI#Bootloader_configuration + +```nix +{ ... }: { + boot.loader.grub = { + efiSupport = true; + efiInstallAsRemovable = true; + device = "nodev"; + }; +} +``` + +Notable things about the hardware UTM configures by default: + +* Ethernet: enp0s5, with the host at 192.168.64.1/24 and the guest receiving an + IP via DHCP (probably 192.168.64.2) +* Disk: root on vda2, boot on vda1 + +It's a QEMU VM so everything is virtio; NixOS provides a configuration to get +all the necessary modules, which you can import at +`(modulesPath + "/profiles/qemu-guest.nix")`. + +Here's the configuration I used: + +{{ codefile(path="./configuration.nix", code_lang="nix", colocated=true, hide=true) }} + +Build with: + +``` +$ nix-build -I "nixpkgs=channel:nixos-22.05,nixos-config=$(pwd)/configuration.nix" \ + '/nixos' -A config.system.build.image +``` + +## Creating a VM + +To do this, create a VM, selecting the "Other" type: + +{% image(name="./1-os-dialog.png", colocated=true) %} +Screenshot of the UTM operating system selection dialog, in which macOS, Linux, +Windows, and Other are listed. +{% end %} + +Then disable ISO boot, since we don't need an installer where we're going. + +{% image(name="./2-disable-iso-boot.png", colocated=true) %} +Dialog in UTM: "disable ISO boot" checkbox checked +{% end %} + +Finish setting up the VM, don't worry about the disk size since we will +immediately delete it. Select "Open VM Settings" on the summary page so you can +do that. + +{% image(name="./3-open-vm-settings.png", colocated=true) %} +UTM VM creation summary dialog with "Open VM Settings" box checked +{% end %} + +Then select the disk and delete it: + +{% image(name="./4-delete-volume.png", colocated=true) %} +Screenshot of the VM settings showing the delete button of the disk selected in +the sidebar. +{% end %} + +Finally, create a new disk, selecting import to get the newly built root +filesystem image from Nix: + +{% image(name="./5-import-image.png", colocated=true) %} +Screenshot of the "create disk" dialog, with the import button visible. +{% end %}