-
-
Notifications
You must be signed in to change notification settings - Fork 16.6k
NixOS test framework: Add macOS VMs #429189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This is horrible code, and it doesn't have a backdoor service yet. Maybe it needs to be an SSH connection? Would be nice to send commands to an offline machine though.
ln -s ${hostPkgs.writeScript "run-nixos-vm" startVM} $out/bin/run-${config.system.name}-vm | ||
''; | ||
virtualisation.qemu.options = [ | ||
"-enable-kvm" # ?? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intended to run on Linux or on macOS? There is no such thing as kvm on macOS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're allowed to use Linux as a hypervisor of sorts on your Apple computer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these settings will not work on macOS hosts, though? That would significantly diminishes the usefulness given the fact that you’d need macOS to build a nix‐darwin configuration to run in the VMs to begin with. We have darwin.linux-builder
to solve that bootstrapping problem one way, but it’s less tractable the other way around. It’s also not really practical to get cloud Macs running Linux.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, and I should mention that running aarch64-darwin
guests on anything other than aarch64-darwin
is much less of a thing than even with x86_64-darwin
, so the aarch64-linux
to aarch64-darwin
mapping elsewhere in the PR is dubious. Apple do ship a kernel variant for VMs that doesn’t rely on their proprietary ISA extensions and I believe people have gotten something running, but in practical terms you need to be using the system Virtualization framework. Even QEMU’s Apple Silicon guest support requires an Apple Silicon host, albeit with the lower‐level Hypervisor framework and more bespoke implementation of the macOS VM device model.
nixThePlanet = builtins.getFlake "github:MatthewCroughan/NixThePlanet/c9d159dc2e0049e7b250a767a3a01def52c3412b"; | ||
|
||
# no specific commit in particular | ||
nix-darwin = builtins.getFlake "github:nix-darwin/nix-darwin/e04a388232d9a6ba56967ce5b53a8a6f713cdfcf"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if the correct place of this test framework would be nix-darwin itself? Afaik all the module system of the test framework should be accessible from there as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was thinking to move things when it works, and the refactoring is done.
Refactoring will be important, because when the code is split out, it will need a reasonably clean interface to attach to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect some parts should live in NixThePlanet and some parts will make more sense to be put into nix-darwin where they can be shared between both x86 and ARM VMs
# A macOS VM | ||
daisy = { | ||
system.stateVersion = 6; | ||
virtualisation.diskImage = "${nixThePlanet.packages.${hostPkgs.stdenv.hostPlatform.system}.macos-ventura-image}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be an FOD?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an installation process into a disk image, and it's not byte for byte reproducible, so we can't slap a hash on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this! I have wanted VM tests for nix‐darwin for a long while now. There is some prior art by @Enzime (nix-darwin/nix-darwin#1000) and @winterqt (I believe unpublished), but those didn’t use the full NixOS VM test framework. I would love to be able to use the existing mechanisms to test nix‐darwin, and remember looking into the possibility of using QEMU to make that possible; it’s very cool to see it proven out this far and I’m curious what led you to doing this work.
However, I have significant concerns about this approach. The code here only works with x86_64-darwin
; the latest macOS won’t even run on that platform in a year’s time, and although we’re still working out the exact deprecation timeline, the platform clearly has a limited remaining lifespan, and it’s only still built on Hydra with slow user‐space emulation on aarch64-darwin
hardware.
There has been work to make QEMU able to host Apple Silicon macOS guests, and I see that at least some of it has been merged upstream. However, there are severe limitations: it cannot handle installing a new VM and it doesn’t support macOS ≥ 13 guests. macOS 12 is already end‐of‐life, and the plan is for Nixpkgs 25.11 to support only macOS ≥ 14, as macOS 13 will be end‐of‐life by the time of its release. So using QEMU for aarch64-darwin
guests seems like a non‐starter at present.
I don’t think we would want to pursue x86_64-darwin
‐only functionality at this juncture, and I wouldn’t expect that QEMU’s aarch64-darwin
guest support will become production‐ready any time soon. Therefore, it doesn’t seem like a QEMU‐based solution is the way to go, at least for now.
The reason QEMU’s support for this is so patchy is that it builds on top of the raw Hypervisor framework rather than the higher‐level Virtualization framework, which has first‐class support for macOS guests. There are tools like Tart that use the Virtualization framework to manage automation of macOS guests on Apple Silicon, including things like automated macOS installation; that’s what was used in @Enzime’s earlier work.
Unfortunately, Tart is non‐free, although of course given that macOS is as well, that may not be a hard blocker; I think there are alternatives, but I haven’t done a deep dive on the options. It only supports Apple Silicon, but that doesn’t seem like as big of a problem these days. In any case, the test framework would require further adaptation to use with any non‐QEMU VMM, of course, but I don’t see any other practical option for macOS VM tests at this point.
FWIW, the macOS EULA only allows using macOS on two guest VMs simultaneously on a given host (and this is technologically enforced by the Virtualization framework). So we will be limited to two nodes for macOS tests, which would be rather unfortunate perf‐wise in terms of running a full nix‐darwin test suite, but oh well.
I’ve left some additional comments on the implementation inline, but they’re probably not too relevant given the above issues with the QEMU‐based approach.
ln -s ${hostPkgs.writeScript "run-nixos-vm" startVM} $out/bin/run-${config.system.name}-vm | ||
''; | ||
virtualisation.qemu.options = [ | ||
"-enable-kvm" # ?? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these settings will not work on macOS hosts, though? That would significantly diminishes the usefulness given the fact that you’d need macOS to build a nix‐darwin configuration to run in the VMs to begin with. We have darwin.linux-builder
to solve that bootstrapping problem one way, but it’s less tractable the other way around. It’s also not really practical to get cloud Macs running Linux.
|
||
let | ||
|
||
nixThePlanet = builtins.getFlake "github:MatthewCroughan/NixThePlanet/c9d159dc2e0049e7b250a767a3a01def52c3412b"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think we should use builtins.getFlake
in Nixpkgs, especially to a repository that contains a bunch of legally dubious stuff. (But I assume this is just a proof‐of‐concept and the intention was to pull the relevant functionality in‐tree.)
# A macOS VM | ||
daisy = { | ||
system.stateVersion = 6; | ||
virtualisation.diskImage = "${nixThePlanet.packages.${hostPkgs.stdenv.hostPlatform.system}.macos-ventura-image}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ventura is going to be EOL by the release of Nixpkgs 25.11.
"-device" "usb-ehci,id=ehci" | ||
"-device" "nec-usb-xhci,id=xhci" | ||
"-global" "nec-usb-xhci.msi=off" | ||
"-device" ''isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc"'' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This string has, of course, been the subject of substantial legal dispute. I don’t know if there’s any consensus position on whether there is a problematic copyright or DMCA aspect to including it here. Psystar did lose their case, though.
(It’s only relevant for x86_64-darwin
QEMU hacks, not aarch64-darwin
using the Virtualization framework, so I think it probably isn’t relevant these days, but I figured we would require end users to supply this string as an assertion that they accept that it’s their responsibility to comply with the EULA.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading about the Psystar Corporation, it sounds like they were grifters and this string is now publicly available in court filings:
Some relevant links:
https://dortania.github.io/OpenCore-Install-Guide/why-oc.html#legality-of-hackintoshing
https://www.contrib.andrew.cmu.edu/~somlo/OSXKVM/#sec_4
https://en.wikipedia.org/wiki/Hackintosh#Legal_issues_and_Apple's_objections
https://en.wikipedia.org/wiki/Psystar_Corporation
"-drive" "if=pflash,format=raw,readonly=on,file=${nixThePlanet.legacyPackages.${hostPkgs.stdenv.hostPlatform.system}.osx-kvm}/OVMF_CODE.fd" | ||
"-drive" "if=pflash,format=raw,readonly=on,file=${nixThePlanet.legacyPackages.${hostPkgs.stdenv.hostPlatform.system}.osx-kvm}/OVMF_VARS-1920x1080.fd" | ||
"-drive" "id=OpenCoreBoot,if=virtio,snapshot=on,readonly=on,format=qcow2,file=${nixThePlanet.legacyPackages.${hostPkgs.stdenv.hostPlatform.system}.osx-kvm}/OpenCore/OpenCore.qcow2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OpenCore is, of course, open, and we have from‐source builds of EDK II and OVMF. It would be unfortunate to consume it in the form of opaque binary blobs from the somewhat messy OSX-KVM repository that contains things like decompiled macOS code. (Again only relevant for x86_64-darwin
anyway, though.)
Hey @emilazy, thank you so much for your elaborate feedback. I'd adopted the qemu approach because I could reuse a working example, but I don't think it needs to be qemu.
I hope the Virtualization Framework has similar networking functionality or is compatible with qemu. I guess this is a good use case for mixing macOS and NixOS VMs: one or two client VMs, and however many application / backend / infra VMs. Both technologically and legally I suppose it would be simpler to start running BSDs using this, but those and macOS can both be done using code like this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i kind of like this change because it opens up the possibility to properly mimic the open submodules type. freeformType is nice, but has its problems, with infinite recursion when refering to config.
The same change could also be applied to listOf but thats a bit harder because of the list merging not ensuring the index stays constant after merging 🤔
Needing this feels like bad design, but you're right, and it is entirely possible to, for example, implement type checked "Hungarian notation" with this.
I guess that's inherently like
Probably best solved by avoiding lists (which are also not overridable, and whose ordering is susceptible to changes in |
Goal: enable automated testing of Nix on macOS
Done
nix run -f . nixosTests.nixos-test-driver.multi-os.driverInteractive
launches macOSTODO:
requiredFeatures = ["apple-branded-computer"];
to support license compliancegetFlake
somehow (not sure if those parts can be in-tree)qemu-vm.nix
Things done
passthru.tests
.nixpkgs-review
on this PR. See nixpkgs-review usage../result/bin/
.Add a 👍 reaction to pull requests you find important.