{ nixpkgs , system , name ? "sandbox" , user ? "dummy" , config ? { } , restrictNetwork ? true # to be replaced with virtualisation.restrictNetwork }: with nixpkgs.lib; let pkgs = import nixpkgs { inherit system; }; in rec { nixosConfigurations.${name} = nixosSystem { inherit system; modules = [ (nixpkgs + "/nixos/modules/profiles/minimal.nix") { environment.noXlibs = false; } # avoid mass rebuild (nixpkgs + "/nixos/modules/profiles/qemu-guest.nix") (nixpkgs + "/nixos/modules/virtualisation/qemu-vm.nix") ({ config, lib, pkgs, ... }: { system.stateVersion = mkDefault pkgs.lib.trivial.release; networking = { hostName = name; firewall.enable = mkDefault false; }; users.users.${user} = { isNormalUser = mkDefault true; password = mkDefault ""; extraGroups = mkDefault [ "wheel" ]; }; security.sudo.wheelNeedsPassword = mkDefault false; services.getty = { autologinUser = mkDefault user; helpLine = mkDefault '' Press to terminate the virtual machine. The working directory on the host is mounted to /mnt. ''; }; virtualisation = { graphics = mkDefault false; diskImage = mkDefault "$(mktemp).qcow2"; sharedDirectories.host = { source = "$SHARED_CWD"; target = "/mnt"; }; # Uncomment when this is merged: # https://github.com/NixOS/nixpkgs/pull/200225 #restrictNetwork = mkDefault true; }; }) config ]; }; packages.${name} = nixosConfigurations.${name}.config.system.build.vm; apps.${name} = { type = "app"; program = toString (pkgs.writeShellScript "sandbox-vm" ( (pkgs.lib.optionalString restrictNetwork '' # Isolate from network # Stopgap solution until this is merged: # https://github.com/NixOS/nixpkgs/pull/200225 QEMU_NET_OPTS="restrict=yes,''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS}" export QEMU_NET_OPTS '') + '' # Save current directory for mounting in VM SHARED_CWD=$PWD export SHARED_CWD ${packages.${name}}/bin/run-${name}-vm reset echo "Exited virtual machine." '')); }; }