xynos space Blog

Using Rosetta 2 in a NixOS VM

Released On: 2022-09-07 00:00Z

Last Updated On: 2022-10-29 23:02+02:00

A 2 minute read.

Update (2022-10-29): Removed parts about how everything is in beta, as macOS Ventura and UTM 4 are out of beta.

This only works with macOS 13 (or later) and UTM 4 (or later)

With the release of macOS Ventura, Apple generously allows people to also use Rosetta 2 in their Linux VMs.

It of course only works in Linux VMs on Apple Silicon macs, althrough seemingly you could just take the binary and put it onto other (ARM) computers

To use it, you have to use a VM Software utilizing Virtualization.Framework (not to be confused with Hypervisor.Framework), which also exposes the option to mount the Rosetta volume, and you have to be on macOS 13 (Beta).

We’ll use UTM here. The Rosetta option is only exposed on UTM Version 4.0 and above (you can also get it from the Mac App Store).

While creating the VM, check both “Use Apple Virtualization” and “Enable Rosetta”

Then install NixOS like normal (using an aarch64 ISO).

To mount the Rosetta virtiofs, register the binary format and tell nix that you can build x86 now, put the following inside your NixOS configuration:

{ config, lib, ...}: {
  boot.initrd.availableKernelModules = [ "virtiofs" ];
  fileSystems."/run/rosetta" = {
    device = "rosetta";
    fsType = "virtiofs";
  nix.settings.extra-platforms = [ "x86_64-linux" ];
  nix.settings.extra-sandbox-paths = [ "/run/rosetta" "/run/binfmt" ];
  boot.binfmt.registrations."rosetta" = { # based on https://developer.apple.com/documentation/virtualization/running_intel_binaries_in_linux_vms_with_rosetta#3978495
    interpreter = "/run/rosetta/rosetta";
    fixBinary = true;
    wrapInterpreterInShell = false;
    matchCredentials = true;
    magicOrExtension = ''\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00'';
    mask = ''\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'';


And now you can run X86 Applications

$ nix-shell -E 'with import <nixpkgs> { system="x86_64-linux"; }; runCommand "dummy" { buildInputs = [ hello ]; } ""' --command hello
Hello, world!
$ # or `nix run nixpkgs#legacyPackages.x86_64-linux.hello` if you're already using the new nix cli

Using nix-command is such a breeze compared to how it was before

Rosetta seems to work pretty good. In my testing (mostly building NixOS configuratinos to deploy to servers) everything just worked and UTM only crashed once.

Setting the VM up as a remote builder is also really convenient.