Skip to content

feat: add macOS support via vfkit hypervisor#4

Open
razvanz wants to merge 6 commits intomainfrom
feat/macos-vfkit-support
Open

feat: add macOS support via vfkit hypervisor#4
razvanz wants to merge 6 commits intomainfrom
feat/macos-vfkit-support

Conversation

@razvanz
Copy link
Copy Markdown
Owner

@razvanz razvanz commented Mar 24, 2026

Summary

  • Multi-system flake outputs (x86_64-linux, aarch64-linux, aarch64-darwin) using lib.genAttrs with per-system nixosConfigurations, packages, and apps
  • Conditional hypervisor: cloud-hypervisor + TAP + nftables on Linux, vfkit + vmnet NAT on macOS (via microvm.nix's built-in vfkit runner)
  • Darwin-specific CLI paths: platform detection, portable shell helpers (_portable_realpath, _sha256, _nix_system), ARP-based guest IP discovery, no virtiofsd/dnsmasq/nft dependencies
  • CI matrix: unit tests (ShellCheck, BATS, Nix eval) on both Linux and macOS; E2E on Linux only

Key design decisions

  • vfkit via microvm.nix: leverages existing lib/runners/vfkit.nix rather than hand-building CLI invocations
  • vmnet NAT + DHCP: no TAP devices needed on macOS; guest networking is DHCP with Google DNS
  • Native virtiofs: Apple's Virtualization.framework handles virtiofs without virtiofsd
  • Runner sed-patching: follows existing ADR-008 precedent for injecting CPU/RAM/device args
  • Hot-plug mount/unmount disabled on macOS MVP: acceptable limitation with clear error message
  • E2E Linux-only: macOS GitHub Actions runners cannot build aarch64-linux NixOS guest derivations (no Linux builder available). See ADR 015.

Bug fixes discovered during CI

  • _nix_system(): Apple tools report arm64 but Nix expects aarch64 — added mapping
  • flake.nix: missing required id field on darwin microvm network interface

Known limitations (MVP)

  • Network mode forced to open on macOS (no egress/DNS filtering)
  • No hot-plug mount/unmount (add mounts to config.nix and restart)
  • ARP-based IP discovery has 60s timeout (fragile if DHCP is slow)
  • Runner sed-patching is fragile if microvm.nix changes runner format
  • macOS E2E requires local testing — CI only runs unit tests on macOS

Test plan

  • nix flake show shows all three systems' outputs
  • nix build .#packages.x86_64-linux.nixbox succeeds (Linux regression)
  • nix build .#packages.aarch64-darwin.vm-runner produces vfkit runner (on macOS)
  • nixbox doctor on macOS passes without KVM/nft/dnsmasq/virtiofsd
  • nixbox upnixbox shellnixbox down cycle works on macOS
  • All existing Linux functionality unchanged (CI E2E passes)
  • ShellCheck + BATS + Nix eval pass on both Linux and macOS

🤖 Generated with Claude Code

Comment thread bin/nixbox
Comment thread flake.nix
Comment on lines +206 to +209
nameservers = [
"8.8.8.8"
"8.8.4.4"
];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can read, you'd need to install a local DNS forwarder (dnsmasq) if you didn't want to use Google DNS resolvers. Would it make sense to do that?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the README says in prerequisites

"dnsmasq, nftables, e2fsprogs (for mke2fs), virtiofsd"

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@razvanz razvanz force-pushed the feat/macos-vfkit-support branch 2 times, most recently from 89e99f6 to cfa91b1 Compare April 8, 2026 08:08
razvanz and others added 6 commits April 15, 2026 08:51
Multi-system flake (x86_64-linux, aarch64-linux, aarch64-darwin) with
conditional hypervisor selection: cloud-hypervisor+TAP on Linux,
vfkit+vmnet NAT on macOS. Darwin path uses ARP-based IP discovery,
native virtiofs (no virtiofsd), and DHCP networking. Hot-plug
mount/unmount disabled on macOS MVP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
uname -m returns "arm64" on Apple Silicon but Nix expects "aarch64".
Also add fail-fast: false to E2E matrix so Linux E2E isn't canceled
by macOS failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
microvm.nix requires an id for all interface types, not just tap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
macOS GitHub runners cannot build aarch64-linux derivations required
for the NixOS guest image. E2E stays linux-only; test job (ShellCheck,
BATS, Nix eval) remains cross-platform.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@razvanz razvanz force-pushed the feat/macos-vfkit-support branch from cfa91b1 to e7e6fe8 Compare April 15, 2026 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants