NixOS for Apple container
I have written at length about containers and VMs on this blog: I use them daily to segregate work, contain rogue AI agents, and defend against supply-chain attacks. To build a good developer experience, I package everything with NixOS.
A couple of days ago Apple released v1.0.0 of container, a tool to run
Linux containers on macOS. I decided to give it a try and compare it against
QEMU (battle-tested, but with a large attack surface).
Under the hood, container consumes standard OCI images and runs them either:
- as an ephemeral container (with
container run), where each container gets its own VM; - as a persistent VM (with
container machine create, then... run).
The VM automatically forwards your SSH socket and mounts your home directory
read/write. Unset SSH_AUTH_SOCK and add --home-mount none to prevent both.
NixOS doesn’t use FHS and containers don’t run systemd. So I wrote a
small NixOS module that ensures a smooth boot. It loads the Nix database and
bundles the TLS roots, provides the filesystem shims and the UID that Apple’s
init expects, sets up the session environment, and waits for the rest of the
system (e.g., home-manager) to come up. Figuring out all this took Claude a
few round trips, with me supervising to keep things minimal, DRY, and elegant.
The result is this Nix flake. It includes:
- a NixOS module (use it to build your own NixOS image),
- a minimal NixOS image,
- and a full image of my configuration.
The same NixOS image can run both as a container and as a persistent VM. To
give it a try, install container and then run:
$ container run -it --rm ghcr.io/aldur/nixos:latest
[nixos@nixos:~]$ nix shell nixpkgs#cowsay
[nixos@nixos:~]$ cowsay "Hello, world!"
_______________
< Hello, world! >
---------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
[nixos@nixos:~]$
Or, for the VM:
$ container machine create ghcr.io/aldur/nixos:latest --home-mount none
nixos-latest
$ container machine run -n nixos-latest
[nixos@nixos:/home/aldur]$ id
uid=501(nixos) gid=20(lp) groups=20(lp)
# If you are confused about `/home/aldur`,
# container VMs derive `cwd`, `id` and `guid` from your macOS user.