Skip to content

Commit 21185d0

Browse files
committed
feat: Add Rosetta support for vfkit on Apple Silicon
Enables running x86_64 (Intel) binaries in ARM64 Linux VMs on Apple Silicon Macs using Apple's Rosetta translation layer. Changes: - Add microvm.vfkit.rosetta.enable option to enable Rosetta - Add microvm.vfkit.rosetta.install option to auto-install Rosetta - Add microvm.vfkit.rosetta.ignoreIfMissing for compatibility - Add rosetta device to vfkit runner when enabled - Add NixOS module to automatically configure guest (mount + binfmt) - Validate that Rosetta is only used on aarch64-darwin systems - Create comprehensive documentation with setup instructions
1 parent e21c05a commit 21185d0

File tree

7 files changed

+143
-3
lines changed

7 files changed

+143
-3
lines changed

doc/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- [Device pass-through](./devices.md)
99
- [CPU emulation](./cpu-emulation.md)
1010
- [Output options](./output-options.md)
11+
- [Using Rosetta with vfkit (macOS)](./vfkit-rosetta.md)
1112
- [MicroVM options reference ⚙️](./microvm-options.md)
1213
- [Running a MicroVM as a package](./packages.md)
1314
- [Preparing a host for declarative MicroVMs](./host.md)

doc/src/options.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ available for customization. These are the most important ones:
1717
| `microvm.forwardPorts` | (qemu user-networking only) TCP/UDP port forwarding |
1818
| `microvm.vfkit.extraArgs` | (vfkit only) Extra arguments to pass to vfkit |
1919
| `microvm.vfkit.logLevel` | (vfkit only) Log level: "debug", "info", or "error" (default: "info") |
20+
| `microvm.vfkit.rosetta.enable` | (vfkit only) Enable Rosetta for running x86_64 binaries on ARM64 (Apple Silicon only) |
2021
| `microvm.kernelParams` | Like `boot.kernelParams` but will not end up in `system.build.toplevel`, saving you rebuilds |
2122
| `microvm.storeOnDisk` | Enables the store on the boot squashfs even in the presence of a share with the host's `/nix/store` |
2223
| `microvm.writableStoreOverlay` | Optional string of the path where all writes to `/nix/store` should go to. |

doc/src/vfkit-rosetta.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Using Rosetta with vfkit on Apple Silicon
2+
3+
Rosetta support enables running x86_64 (Intel) binaries in your ARM64 Linux VM on Apple Silicon Macs. This is useful for running legacy applications or development tools that haven't been ported to ARM yet.
4+
5+
## Requirements
6+
7+
- Apple Silicon (M1/M2/M3/etc.) Mac
8+
- macOS with Rosetta installed
9+
- vfkit hypervisor
10+
11+
## Configuration
12+
13+
Enable Rosetta in your MicroVM configuration:
14+
15+
```nix
16+
{
17+
microvm = {
18+
hypervisor = "vfkit";
19+
20+
vfkit.rosetta = {
21+
enable = true;
22+
# Optional: install Rosetta automatically if missing
23+
install = true;
24+
};
25+
};
26+
}
27+
```
28+
29+
The NixOS module automatically handles mounting the Rosetta virtiofs share and configuring binfmt to use Rosetta for x86_64 binaries. No additional guest configuration is required.
30+
31+
## Usage
32+
33+
Once configured, you can run any x86_64 binary in your ARM64 VM. To verify Rosetta is working:
34+
35+
```nix
36+
# Add an x86_64 package to your configuration
37+
environment.systemPackages = with pkgs; [
38+
file # to verify binary architecture
39+
(pkgsCross.gnu64.hello) # x86_64 version of hello
40+
];
41+
```
42+
43+
Then in the VM:
44+
45+
```bash
46+
# Verify you're running on ARM64
47+
uname -m
48+
# Output: aarch64
49+
50+
# Check the binary architecture
51+
file $(which hello)
52+
# Output: ELF 64-bit LSB executable, x86-64, ...
53+
54+
# Run the x86_64 binary via Rosetta
55+
hello
56+
# Output: Hello, world!
57+
```
58+
59+
You can use `pkgsCross.gnu64.<package>` to cross-compile any package from nixpkgs to x86_64 and run it via Rosetta.
60+
61+
## Options Reference
62+
63+
| Option | Type | Default | Description |
64+
|--------|------|---------|-------------|
65+
| `microvm.vfkit.rosetta.enable` | bool | `false` | Enable Rosetta support |
66+
| `microvm.vfkit.rosetta.install` | bool | `false` | Auto-install Rosetta if missing |
67+
| `microvm.vfkit.rosetta.ignoreIfMissing` | bool | `false` | Continue if Rosetta unavailable |
68+
69+
## Limitations
70+
71+
- Only works on Apple Silicon Macs (M-series chips)
72+
- vfkit will fail to start on Intel Macs if Rosetta is enabled
73+
- Performance is slower than native ARM64 execution
74+
- Not all x86_64 binaries may work perfectly

lib/runners/vfkit.nix

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ let
1717
storeOnDisk kernel initrdPath storeDisk kernelParams
1818
balloon devices credentialFiles vsock graphics;
1919

20-
inherit (microvmConfig.vfkit) extraArgs logLevel;
20+
inherit (microvmConfig.vfkit) extraArgs logLevel rosetta;
2121

2222
volumesWithLetters = withDriveLetters microvmConfig;
2323

@@ -61,8 +61,18 @@ let
6161
else if type == "bridge" then
6262
throw "vfkit bridge networking requires vmnet-helper which is not yet implemented. Use type = \"user\" for NAT networking."
6363
else
64-
throw "Unknown network interface type: ${type}"
65-
) interfaces);
64+
throw "vfkit does not support ${type} networking on macOS. Use type = \"user\" for NAT networking."
65+
) interfaces)
66+
++ lib.optionals rosetta.enable (
67+
let
68+
rosettaArgs = builtins.concatStringsSep "," (
69+
[ "rosetta" "mountTag=rosetta" ]
70+
++ lib.optional rosetta.install "install"
71+
++ lib.optional rosetta.ignoreIfMissing "ignoreIfMissing"
72+
);
73+
in
74+
[ "--device" rosettaArgs ]
75+
);
6676

6777
allArgsWithoutSocket = [
6878
"${lib.getExe vfkit}"
@@ -96,6 +106,8 @@ in
96106
then throw "vfkit does not support changing user"
97107
else if balloon
98108
then throw "vfkit does not support memory ballooning"
109+
else if rosetta.enable && !vmHostPackages.stdenv.hostPlatform.isAarch64
110+
then throw "Rosetta requires Apple Silicon (aarch64-darwin). Current host: ${system}"
99111
else if devices != []
100112
then throw "vfkit does not support device passthrough"
101113
else if credentialFiles != {}

nixos-modules/microvm/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ in
1919
./pci-devices.nix
2020
./virtiofsd
2121
./graphics.nix
22+
./rosetta.nix
2223
./optimization.nix
2324
./ssh-deploy.nix
2425
];

nixos-modules/microvm/options.nix

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,38 @@ in
608608
description = "vfkit log level.";
609609
};
610610

611+
vfkit.rosetta = {
612+
enable = mkOption {
613+
type = types.bool;
614+
default = false;
615+
description = ''
616+
Enable Rosetta support for running x86_64 binaries in ARM64 Linux VMs.
617+
Only works on Apple Silicon (ARM) Macs.
618+
619+
When enabled, the Rosetta virtiofs share will be automatically mounted
620+
and binfmt will be configured to use Rosetta for x86_64 binaries.
621+
'';
622+
};
623+
624+
install = mkOption {
625+
type = types.bool;
626+
default = false;
627+
description = ''
628+
Automatically install Rosetta if missing.
629+
If false and Rosetta is not installed, vfkit will fail to start.
630+
'';
631+
};
632+
633+
ignoreIfMissing = mkOption {
634+
type = types.bool;
635+
default = false;
636+
description = ''
637+
Continue execution even if Rosetta installation fails or is unavailable.
638+
Useful for configurations that should work on both ARM and Intel Macs.
639+
'';
640+
};
641+
};
642+
611643
prettyProcnames = mkOption {
612644
type = types.bool;
613645
default = true;

nixos-modules/microvm/rosetta.nix

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{ config, lib, pkgs, ... }:
2+
3+
let
4+
cfg = config.microvm.vfkit.rosetta;
5+
mountPoint = "/run/rosetta";
6+
mountTag = "rosetta";
7+
in
8+
lib.mkIf (config.microvm.hypervisor == "vfkit" && cfg.enable) {
9+
fileSystems.${mountPoint} = {
10+
device = mountTag;
11+
fsType = "virtiofs";
12+
};
13+
14+
boot.binfmt.registrations.rosetta = {
15+
interpreter = "${mountPoint}/rosetta";
16+
magicOrExtension = ''\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00'';
17+
mask = ''\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'';
18+
};
19+
}

0 commit comments

Comments
 (0)