├── .gitignore ├── flake.lock ├── flake.nix └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /result* 2 | /nixos.qcow2 3 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1662039439, 6 | "narHash": "sha256-A5oHURLII5JoHl5ZckZobED8pZbY6q6BIRmuO3mBMvE=", 7 | "owner": "nixos", 8 | "repo": "nixpkgs", 9 | "rev": "1bd8d11cc5c83c94582f43c21c3bfd0497586a28", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "nixos", 14 | "ref": "master", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:nixos/nixpkgs/master"; 4 | }; 5 | 6 | outputs = { self, nixpkgs }: { 7 | nixosModules = { 8 | vm = 9 | { config, pkgs, lib, modulesPath, ... }: 10 | 11 | { 12 | imports = [ 13 | "${modulesPath}/virtualisation/qemu-vm.nix" 14 | ]; 15 | 16 | system.stateVersion = "22.05"; 17 | 18 | # Configure networking 19 | networking.useDHCP = false; 20 | networking.interfaces.eth0.useDHCP = true; 21 | 22 | # Create user "test" 23 | services.getty.autologinUser = "test"; 24 | users.users.test.isNormalUser = true; 25 | 26 | # Enable paswordless ‘sudo’ for the "test" user 27 | users.users.test.extraGroups = [ "wheel" ]; 28 | security.sudo.wheelNeedsPassword = false; 29 | 30 | # Make it output to the terminal instead of separate window 31 | virtualisation.graphics = false; 32 | }; 33 | withStoreImage = { 34 | virtualisation.useNixStoreImage = true; 35 | virtualisation.writableStore = true; 36 | }; 37 | }; 38 | nixosConfigurations = { 39 | vm-x86_64 = nixpkgs.lib.nixosSystem { 40 | system = "x86_64-linux"; 41 | modules = [ 42 | self.nixosModules.vm 43 | { 44 | virtualisation.host.pkgs = nixpkgs.legacyPackages.x86_64-darwin; 45 | } 46 | ]; 47 | }; 48 | vm-x86_64-storeImage = nixpkgs.lib.nixosSystem { 49 | system = "x86_64-linux"; 50 | modules = [ 51 | self.nixosModules.vm 52 | self.nixosModules.withStoreImage 53 | { 54 | virtualisation.host.pkgs = nixpkgs.legacyPackages.x86_64-darwin; 55 | } 56 | ]; 57 | }; 58 | vm-aarch64 = nixpkgs.lib.nixosSystem { 59 | system = "aarch64-linux"; 60 | modules = [ 61 | self.nixosModules.vm 62 | { 63 | virtualisation.host.pkgs = nixpkgs.legacyPackages.aarch64-darwin; 64 | } 65 | ]; 66 | }; 67 | vm-aarch64-storeImage = nixpkgs.lib.nixosSystem { 68 | system = "aarch64-linux"; 69 | modules = [ 70 | self.nixosModules.vm 71 | self.nixosModules.withStoreImage 72 | { 73 | virtualisation.host.pkgs = nixpkgs.legacyPackages.aarch64-darwin; 74 | } 75 | ]; 76 | }; 77 | }; 78 | packages.x86_64-darwin.default = self.nixosConfigurations.vm-x86_64.config.system.build.vm; 79 | packages.x86_64-darwin.withStoreImage = self.nixosConfigurations.vm-x86_64-storeImage.config.system.build.vm; 80 | packages.aarch64-darwin.default = self.nixosConfigurations.vm-aarch64.config.system.build.vm; 81 | packages.aarch64-darwin.withStoreImage = self.nixosConfigurations.vm-aarch64-storeImage.config.system.build.vm; 82 | }; 83 | 84 | nixConfig = { 85 | extra-substituters = [ "https://yoriksar-gh.cachix.org" ]; 86 | extra-trusted-public-keys = [ "yoriksar-gh.cachix.org-1:YrztCV1unI7qDV6IXmiXFig5PgptqTlUa4MiobULGT8=" ]; 87 | }; 88 | } 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Run NixOS VM on macOS machine 2 | 3 | This repo provides an example of running a NixOS VM on your macOS machine using 4 | new features in nixpkgs. It contains results of the work done for issue 5 | [NixOS/nixpkgs#108984](https://github.com/NixOS/nixpkgs/issues/108984). 6 | 7 | ## TL;DR 8 | 9 | Run this and you will get a working VM on your macOS machine, built with NixOS 10 | configuration from this flake: 11 | 12 | ```bash 13 | nix run github:YorikSar/nixos-vm-on-macos 14 | ``` 15 | 16 | To exit, run `sudo poweroff` or press Ctrl-a-x 17 | 18 | ## Setting up 19 | 20 | Here I will list errors that you might encounter and how to address them. 21 | 22 | ### Experimental features 23 | 24 | ``` 25 | error: experimental Nix feature 'nix-command' is disabled; use '--extra-experimental-features nix-command' to override 26 | ``` 27 | 28 | Flakes are still experimental in Nix, so if you didn't enable them in your 29 | config yet, you can do one of: 30 | 31 | * run `export NIX_CONFIG="extra-experimental-features = nix-command flakes"` to 32 | temporary enable them in your current shell 33 | * add line `extra-experimental-features = nix-command flakes` to your 34 | `~/.config/nix/nix.conf` file to enable them for your current user 35 | * add line `extra-experimental-features = nix-command flakes` to your 36 | `/etc/nix/nix.conf` file to enable them globally on your machine 37 | 38 | ### Flake configuration settings 39 | 40 | ``` 41 | do you want to allow configuration setting 'extra-substituters' to be set to 'https://yoriksar-gh.cachix.org' (y/N)? y 42 | do you want to permanently mark this value as trusted (y/N)? y 43 | do you want to allow configuration setting 'extra-trusted-public-keys' to be set to 'yoriksar-gh.cachix.org-1:YrztCV1unI7qDV6IXmiXFig5PgptqTlUa4MiobULGT8=' (y/N)? y 44 | do you want to permanently mark this value as trusted (y/N)? y 45 | ``` 46 | 47 | This flake provides configuration settings for using my cache hosted on 48 | [Cachix](https://cachix.org). On the first run, Nix will ask you if you want to 49 | enable each of these settings (I recommend answer "yes") and whether you want 50 | to trust these settings in the future so that you don't have to reply to these 51 | questions every time. 52 | 53 | ### Trust my substituter 54 | 55 | ``` 56 | warning: ignoring untrusted substituter 'https://yoriksar-gh.cachix.org' 57 | ``` 58 | 59 | If you see this line, it means that while your Nix trusts the configuration 60 | values, it doesn't trust substituter. Add these lines to your 61 | `/etc/nix/nix.conf`: 62 | 63 | ``` 64 | trusted-substituters = https://yoriksar-gh.cachix.org 65 | trusted-public-keys = yoriksar-gh.cachix.org-1:YrztCV1unI7qDV6IXmiXFig5PgptqTlUa4MiobULGT8= 66 | ``` 67 | 68 | and then restart your Nix daemon with: 69 | 70 | ``` 71 | sudo launchctl kickstart -k system/org.nixos.nix-daemon 72 | ``` 73 | 74 | ### Linux builder is required 75 | 76 | ``` 77 | error: a 'aarch64-linux' with features {} is required to build '...', but I am a 'x86_64-darwin' with features {benchmark, big-parallel, nixos-test} 78 | ``` 79 | 80 | If you don't configure my substituter (see previous 2 sections) or change 81 | the configuration in any way, you will have to rebuild NixOS system 82 | configuration. Unfortunately, it requires you to have a remote builder 83 | configured for your machine with the appropriate Linux support. I will refer 84 | you to [docs](https://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html) 85 | that describe how to set it up. You would still have to provide your own Linux 86 | machine though. 87 | 88 | ### Host and guest architecture must match 89 | 90 | ``` 91 | qemu-system-x86_64: Unknown Error 92 | ``` 93 | 94 | If you're seeing this on your Apple Silicon machine, you're probably running 95 | Intel version of Nix that uses `x86_64-darwin` system by default. You can't run 96 | `x86_64-linux` machine on Apple Silicon at this point (will be fixed in nixpkgs 97 | eventually), and it would be very slow (Rosetta is of no help here), so you 98 | should stick to running `aarch64-linux` VM on your machine. To do so, add 99 | `--system aarch64-darwin` to your `nix run` and it will pick up the right 100 | package. 101 | 102 | ### Broken sudo 103 | 104 | ``` 105 | [test@nixos:~]$ sudo poweroff 106 | sudo: error in /etc/sudo.conf, line 0 while loading plugin "sudoers_policy" 107 | sudo: /nix/store/kkn64rx0ns1kv8yadwclnwrny29n6inj-sudo-1.9.11p3/libexec/sudo/sudoers.so must be owned by uid 0 108 | sudo: fatal error, unable to load plugins 109 | ``` 110 | 111 | This probably means that you're using single-user (daemon-less) Nix 112 | installation and all `/nix/store` paths are owned by you instead of root. By 113 | default, VM shares `/nix/store` with the host, so things like `sudoers.so` ends 114 | up with wrong permissions. This can be fixed by using a qcow image with all 115 | necessary store path for the VM. There's a special output that has already been 116 | build and cached for this. To use it, run 117 | 118 | ``` 119 | nix run github:YorikSar/nixos-vm-on-macos#withStoreImage 120 | ``` 121 | 122 | Note that it will download the image from the cache for you that weight about 123 | 1Gb. 124 | 125 | ### There's a different issue 126 | 127 | Feel free to ask about it in 128 | [the original issue](https://github.com/NixOS/nixpkgs/issues/108984) or in this 129 | repo's [issues](https://github.com/YorikSar/nixos-vm-on-macos/issues). 130 | --------------------------------------------------------------------------------