Loading doc/packages/darwin-builder.section.md +3 −3 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ $ sudo launchctl kickstart -k system/org.nixos.nix-daemon darwin-builder = nixpkgs.lib.nixosSystem { system = linuxSystem; modules = [ "${nixpkgs}/nixos/modules/profiles/macos-builder.nix" "${nixpkgs}/nixos/modules/profiles/nix-builder-vm.nix" { virtualisation = { host.pkgs = pkgs; darwin-builder.workingDirectory = "/var/lib/darwin-builder"; Loading Loading @@ -158,7 +158,7 @@ in the example below and rebuild. darwin-builder = nixpkgs.lib.nixosSystem { system = linuxSystem; modules = [ "${nixpkgs}/nixos/modules/profiles/macos-builder.nix" "${nixpkgs}/nixos/modules/profiles/nix-builder-vm.nix" { virtualisation.host.pkgs = pkgs; virtualisation.darwin-builder.diskSize = 5120; Loading @@ -185,6 +185,6 @@ nix-repl> darwin.linux-builder.nixosConfig.nix.package «derivation /nix/store/...-nix-2.17.0.drv» nix-repl> :p darwin.linux-builder.nixosOptions.virtualisation.memorySize.definitionsWithLocations [ { file = "/home/user/src/nixpkgs/nixos/modules/profiles/macos-builder.nix"; value = 3072; } ] [ { file = "/home/user/src/nixpkgs/nixos/modules/profiles/nix-builder-vm.nix"; value = 3072; } ] ``` nixos/modules/profiles/macos-builder.nix +4 −255 Original line number Diff line number Diff line { config, lib, options, ... }: let keysDirectory = "/var/keys"; user = "builder"; keyType = "ed25519"; cfg = config.virtualisation.darwin-builder; let lib = import ../../../lib; in { imports = [ ../virtualisation/qemu-vm.nix # Avoid a dependency on stateVersion { disabledModules = [ ../virtualisation/nixos-containers.nix ../services/x11/desktop-managers/xterm.nix ]; # swraid's default depends on stateVersion config.boot.swraid.enable = false; options.boot.isContainer = lib.mkOption { default = false; internal = true; }; } ]; options.virtualisation.darwin-builder = with lib; { diskSize = mkOption { default = 20 * 1024; type = types.int; example = 30720; description = "The maximum disk space allocated to the runner in MB"; }; memorySize = mkOption { default = 3 * 1024; type = types.int; example = 8192; description = "The runner's memory in MB"; }; min-free = mkOption { default = 1024 * 1024 * 1024; type = types.int; example = 1073741824; description = '' The threshold (in bytes) of free disk space left at which to start garbage collection on the runner ''; }; max-free = mkOption { default = 3 * 1024 * 1024 * 1024; type = types.int; example = 3221225472; description = '' The threshold (in bytes) of free disk space left at which to stop garbage collection on the runner ''; }; workingDirectory = mkOption { default = "."; type = types.str; example = "/var/lib/darwin-builder"; description = '' The working directory to use to run the script. When running as part of a flake will need to be set to a non read-only filesystem. ''; }; hostPort = mkOption { default = 31022; type = types.int; example = 22; description = '' The localhost host port to forward TCP to the guest port. ''; }; }; config = { # The builder is not intended to be used interactively documentation.enable = false; environment.etc = { "ssh/ssh_host_ed25519_key" = { mode = "0600"; source = ./keys/ssh_host_ed25519_key; }; "ssh/ssh_host_ed25519_key.pub" = { mode = "0644"; source = ./keys/ssh_host_ed25519_key.pub; }; }; # DNS fails for QEMU user networking (SLiRP) on macOS. See: # # https://github.com/utmapp/UTM/issues/2353 # # This works around that by using a public DNS server other than the DNS # server that QEMU provides (normally 10.0.2.3) networking.nameservers = [ "8.8.8.8" ]; # The linux builder is a lightweight VM for remote building; not evaluation. nix.channel.enable = false; # Deployment is by image. # TODO system.switch.enable = false;? system.disableInstallerTools = true; nix.settings = { auto-optimise-store = true; min-free = cfg.min-free; max-free = cfg.max-free; trusted-users = [ user ]; }; services = { getty.autologinUser = user; openssh = { enable = true; authorizedKeysFiles = [ "${keysDirectory}/%u_${keyType}.pub" ]; }; }; system.build.macos-builder-installer = let privateKey = "/etc/nix/${user}_${keyType}"; publicKey = "${privateKey}.pub"; # This installCredentials script is written so that it's as easy as # possible for a user to audit before confirming the `sudo` installCredentials = hostPkgs.writeShellScript "install-credentials" '' set -euo pipefail KEYS="''${1}" INSTALL=${hostPkgs.coreutils}/bin/install "''${INSTALL}" -g nixbld -m 600 "''${KEYS}/${user}_${keyType}" ${privateKey} "''${INSTALL}" -g nixbld -m 644 "''${KEYS}/${user}_${keyType}.pub" ${publicKey} ''; hostPkgs = config.virtualisation.host.pkgs; script = hostPkgs.writeShellScriptBin "create-builder" ( '' set -euo pipefail '' + # When running as non-interactively as part of a DarwinConfiguration the working directory # must be set to a writeable directory. (if cfg.workingDirectory != "." then '' ${hostPkgs.coreutils}/bin/mkdir --parent "${cfg.workingDirectory}" cd "${cfg.workingDirectory}" '' else "") + '' KEYS="''${KEYS:-./keys}" ${hostPkgs.coreutils}/bin/mkdir --parent "''${KEYS}" PRIVATE_KEY="''${KEYS}/${user}_${keyType}" PUBLIC_KEY="''${PRIVATE_KEY}.pub" if [ ! -e "''${PRIVATE_KEY}" ] || [ ! -e "''${PUBLIC_KEY}" ]; then ${hostPkgs.coreutils}/bin/rm --force -- "''${PRIVATE_KEY}" "''${PUBLIC_KEY}" ${hostPkgs.openssh}/bin/ssh-keygen -q -f "''${PRIVATE_KEY}" -t ${keyType} -N "" -C 'builder@localhost' fi if ! ${hostPkgs.diffutils}/bin/cmp "''${PUBLIC_KEY}" ${publicKey}; then (set -x; sudo --reset-timestamp ${installCredentials} "''${KEYS}") fi KEYS="$(${hostPkgs.nix}/bin/nix-store --add "$KEYS")" ${lib.getExe config.system.build.vm} ''); in script.overrideAttrs (old: { pos = __curPos; # sets meta.position to point here; see script binding above for package definition meta = (old.meta or { }) // { platforms = lib.platforms.darwin; }; passthru = (old.passthru or { }) // { # Let users in the repl inspect the config nixosConfig = config; nixosOptions = options; }; }); system = { # To prevent gratuitous rebuilds on each change to Nixpkgs nixos.revision = null; # to be updated by module maintainers, see nixpkgs#325610 stateVersion = "24.05"; }; users.users."${user}" = { isNormalUser = true; }; security.polkit.enable = true; security.polkit.extraConfig = '' polkit.addRule(function(action, subject) { if (action.id === "org.freedesktop.login1.power-off" && subject.user === "${user}") { return "yes"; } else { return "no"; } }) ''; virtualisation = { diskSize = cfg.diskSize; memorySize = cfg.memorySize; forwardPorts = [ { from = "host"; guest.port = 22; host.port = cfg.hostPort; } ]; # Disable graphics for the builder since users will likely want to run it # non-interactively in the background. graphics = false; sharedDirectories.keys = { source = "\"$KEYS\""; target = keysDirectory; }; # If we don't enable this option then the host will fail to delegate builds # to the guest, because: # # - The host will lock the path to build # - The host will delegate the build to the guest # - The guest will attempt to lock the same path and fail because # the lockfile on the host is visible on the guest # # Snapshotting the host's /nix/store as an image isolates the guest VM's # /nix/store from the host's /nix/store, preventing this problem. useNixStoreImage = true; # Obviously the /nix/store needs to be writable on the guest in order for it # to perform builds. writableStore = true; # This ensures that anything built on the guest isn't lost when the guest is # restarted. writableStoreUseTmpfs = false; # Pass certificates from host to the guest otherwise when custom CA certificates # are required we can't use the cached builder. useHostCerts = true; }; }; } lib.warnIf (lib.isInOldestRelease 2411) "nixos/modules/profiles/macos-builder.nix has moved to nixos/modules/profiles/nix-builder-vm.nix; please update your NixOS imports." ./nix-builder-vm.nix nixos/modules/profiles/nix-builder-vm.nix 0 → 100644 +284 −0 Original line number Diff line number Diff line /* This profile uses NixOS to create a remote builder VM to build Linux packages, which can be used to build packages for Linux on other operating systems; primarily macOS. It contains both the relevant guest settings as well as an installer script that manages it as a QEMU virtual machine on the host. */ { config, lib, options, ... }: let keysDirectory = "/var/keys"; user = "builder"; keyType = "ed25519"; cfg = config.virtualisation.darwin-builder; in { imports = [ ../virtualisation/qemu-vm.nix # Avoid a dependency on stateVersion { disabledModules = [ ../virtualisation/nixos-containers.nix ../services/x11/desktop-managers/xterm.nix ]; # swraid's default depends on stateVersion config.boot.swraid.enable = false; options.boot.isContainer = lib.mkOption { default = false; internal = true; }; } ]; options.virtualisation.darwin-builder = with lib; { diskSize = mkOption { default = 20 * 1024; type = types.int; example = 30720; description = "The maximum disk space allocated to the runner in MB"; }; memorySize = mkOption { default = 3 * 1024; type = types.int; example = 8192; description = "The runner's memory in MB"; }; min-free = mkOption { default = 1024 * 1024 * 1024; type = types.int; example = 1073741824; description = '' The threshold (in bytes) of free disk space left at which to start garbage collection on the runner ''; }; max-free = mkOption { default = 3 * 1024 * 1024 * 1024; type = types.int; example = 3221225472; description = '' The threshold (in bytes) of free disk space left at which to stop garbage collection on the runner ''; }; workingDirectory = mkOption { default = "."; type = types.str; example = "/var/lib/darwin-builder"; description = '' The working directory to use to run the script. When running as part of a flake will need to be set to a non read-only filesystem. ''; }; hostPort = mkOption { default = 31022; type = types.int; example = 22; description = '' The localhost host port to forward TCP to the guest port. ''; }; }; config = { # The builder is not intended to be used interactively documentation.enable = false; environment.etc = { "ssh/ssh_host_ed25519_key" = { mode = "0600"; source = ./keys/ssh_host_ed25519_key; }; "ssh/ssh_host_ed25519_key.pub" = { mode = "0644"; source = ./keys/ssh_host_ed25519_key.pub; }; }; # DNS fails for QEMU user networking (SLiRP) on macOS. See: # # https://github.com/utmapp/UTM/issues/2353 # # This works around that by using a public DNS server other than the DNS # server that QEMU provides (normally 10.0.2.3) networking.nameservers = [ "8.8.8.8" ]; # The linux builder is a lightweight VM for remote building; not evaluation. nix.channel.enable = false; # Deployment is by image. # TODO system.switch.enable = false;? system.disableInstallerTools = true; nix.settings = { auto-optimise-store = true; min-free = cfg.min-free; max-free = cfg.max-free; trusted-users = [ user ]; }; services = { getty.autologinUser = user; openssh = { enable = true; authorizedKeysFiles = [ "${keysDirectory}/%u_${keyType}.pub" ]; }; }; system.build.macos-builder-installer = let privateKey = "/etc/nix/${user}_${keyType}"; publicKey = "${privateKey}.pub"; # This installCredentials script is written so that it's as easy as # possible for a user to audit before confirming the `sudo` installCredentials = hostPkgs.writeShellScript "install-credentials" '' set -euo pipefail KEYS="''${1}" INSTALL=${hostPkgs.coreutils}/bin/install "''${INSTALL}" -g nixbld -m 600 "''${KEYS}/${user}_${keyType}" ${privateKey} "''${INSTALL}" -g nixbld -m 644 "''${KEYS}/${user}_${keyType}.pub" ${publicKey} ''; hostPkgs = config.virtualisation.host.pkgs; script = hostPkgs.writeShellScriptBin "create-builder" ( '' set -euo pipefail '' + # When running as non-interactively as part of a DarwinConfiguration the working directory # must be set to a writeable directory. ( if cfg.workingDirectory != "." then '' ${hostPkgs.coreutils}/bin/mkdir --parent "${cfg.workingDirectory}" cd "${cfg.workingDirectory}" '' else "" ) + '' KEYS="''${KEYS:-./keys}" ${hostPkgs.coreutils}/bin/mkdir --parent "''${KEYS}" PRIVATE_KEY="''${KEYS}/${user}_${keyType}" PUBLIC_KEY="''${PRIVATE_KEY}.pub" if [ ! -e "''${PRIVATE_KEY}" ] || [ ! -e "''${PUBLIC_KEY}" ]; then ${hostPkgs.coreutils}/bin/rm --force -- "''${PRIVATE_KEY}" "''${PUBLIC_KEY}" ${hostPkgs.openssh}/bin/ssh-keygen -q -f "''${PRIVATE_KEY}" -t ${keyType} -N "" -C 'builder@localhost' fi if ! ${hostPkgs.diffutils}/bin/cmp "''${PUBLIC_KEY}" ${publicKey}; then (set -x; sudo --reset-timestamp ${installCredentials} "''${KEYS}") fi KEYS="$(${hostPkgs.nix}/bin/nix-store --add "$KEYS")" ${lib.getExe config.system.build.vm} '' ); in script.overrideAttrs (old: { pos = __curPos; # sets meta.position to point here; see script binding above for package definition meta = (old.meta or { }) // { platforms = lib.platforms.darwin; }; passthru = (old.passthru or { }) // { # Let users in the repl inspect the config nixosConfig = config; nixosOptions = options; }; }); system = { # To prevent gratuitous rebuilds on each change to Nixpkgs nixos.revision = null; # to be updated by module maintainers, see nixpkgs#325610 stateVersion = "24.05"; }; users.users."${user}" = { isNormalUser = true; }; security.polkit.enable = true; security.polkit.extraConfig = '' polkit.addRule(function(action, subject) { if (action.id === "org.freedesktop.login1.power-off" && subject.user === "${user}") { return "yes"; } else { return "no"; } }) ''; virtualisation = { diskSize = cfg.diskSize; memorySize = cfg.memorySize; forwardPorts = [ { from = "host"; guest.port = 22; host.port = cfg.hostPort; } ]; # Disable graphics for the builder since users will likely want to run it # non-interactively in the background. graphics = false; sharedDirectories.keys = { source = "\"$KEYS\""; target = keysDirectory; }; # If we don't enable this option then the host will fail to delegate builds # to the guest, because: # # - The host will lock the path to build # - The host will delegate the build to the guest # - The guest will attempt to lock the same path and fail because # the lockfile on the host is visible on the guest # # Snapshotting the host's /nix/store as an image isolates the guest VM's # /nix/store from the host's /nix/store, preventing this problem. useNixStoreImage = true; # Obviously the /nix/store needs to be writable on the guest in order for it # to perform builds. writableStore = true; # This ensures that anything built on the guest isn't lost when the guest is # restarted. writableStoreUseTmpfs = false; # Pass certificates from host to the guest otherwise when custom CA certificates # are required we can't use the cached builder. useHostCerts = true; }; }; } pkgs/top-level/darwin-packages.nix +1 −1 Original line number Diff line number Diff line Loading @@ -245,7 +245,7 @@ impure-cmds // appleSourcePackages // chooseLibs // { nixos = import ../../nixos { configuration = { imports = [ ../../nixos/modules/profiles/macos-builder.nix ../../nixos/modules/profiles/nix-builder-vm.nix ] ++ modules; # If you need to override this, consider starting with the right Nixpkgs Loading Loading
doc/packages/darwin-builder.section.md +3 −3 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ $ sudo launchctl kickstart -k system/org.nixos.nix-daemon darwin-builder = nixpkgs.lib.nixosSystem { system = linuxSystem; modules = [ "${nixpkgs}/nixos/modules/profiles/macos-builder.nix" "${nixpkgs}/nixos/modules/profiles/nix-builder-vm.nix" { virtualisation = { host.pkgs = pkgs; darwin-builder.workingDirectory = "/var/lib/darwin-builder"; Loading Loading @@ -158,7 +158,7 @@ in the example below and rebuild. darwin-builder = nixpkgs.lib.nixosSystem { system = linuxSystem; modules = [ "${nixpkgs}/nixos/modules/profiles/macos-builder.nix" "${nixpkgs}/nixos/modules/profiles/nix-builder-vm.nix" { virtualisation.host.pkgs = pkgs; virtualisation.darwin-builder.diskSize = 5120; Loading @@ -185,6 +185,6 @@ nix-repl> darwin.linux-builder.nixosConfig.nix.package «derivation /nix/store/...-nix-2.17.0.drv» nix-repl> :p darwin.linux-builder.nixosOptions.virtualisation.memorySize.definitionsWithLocations [ { file = "/home/user/src/nixpkgs/nixos/modules/profiles/macos-builder.nix"; value = 3072; } ] [ { file = "/home/user/src/nixpkgs/nixos/modules/profiles/nix-builder-vm.nix"; value = 3072; } ] ```
nixos/modules/profiles/macos-builder.nix +4 −255 Original line number Diff line number Diff line { config, lib, options, ... }: let keysDirectory = "/var/keys"; user = "builder"; keyType = "ed25519"; cfg = config.virtualisation.darwin-builder; let lib = import ../../../lib; in { imports = [ ../virtualisation/qemu-vm.nix # Avoid a dependency on stateVersion { disabledModules = [ ../virtualisation/nixos-containers.nix ../services/x11/desktop-managers/xterm.nix ]; # swraid's default depends on stateVersion config.boot.swraid.enable = false; options.boot.isContainer = lib.mkOption { default = false; internal = true; }; } ]; options.virtualisation.darwin-builder = with lib; { diskSize = mkOption { default = 20 * 1024; type = types.int; example = 30720; description = "The maximum disk space allocated to the runner in MB"; }; memorySize = mkOption { default = 3 * 1024; type = types.int; example = 8192; description = "The runner's memory in MB"; }; min-free = mkOption { default = 1024 * 1024 * 1024; type = types.int; example = 1073741824; description = '' The threshold (in bytes) of free disk space left at which to start garbage collection on the runner ''; }; max-free = mkOption { default = 3 * 1024 * 1024 * 1024; type = types.int; example = 3221225472; description = '' The threshold (in bytes) of free disk space left at which to stop garbage collection on the runner ''; }; workingDirectory = mkOption { default = "."; type = types.str; example = "/var/lib/darwin-builder"; description = '' The working directory to use to run the script. When running as part of a flake will need to be set to a non read-only filesystem. ''; }; hostPort = mkOption { default = 31022; type = types.int; example = 22; description = '' The localhost host port to forward TCP to the guest port. ''; }; }; config = { # The builder is not intended to be used interactively documentation.enable = false; environment.etc = { "ssh/ssh_host_ed25519_key" = { mode = "0600"; source = ./keys/ssh_host_ed25519_key; }; "ssh/ssh_host_ed25519_key.pub" = { mode = "0644"; source = ./keys/ssh_host_ed25519_key.pub; }; }; # DNS fails for QEMU user networking (SLiRP) on macOS. See: # # https://github.com/utmapp/UTM/issues/2353 # # This works around that by using a public DNS server other than the DNS # server that QEMU provides (normally 10.0.2.3) networking.nameservers = [ "8.8.8.8" ]; # The linux builder is a lightweight VM for remote building; not evaluation. nix.channel.enable = false; # Deployment is by image. # TODO system.switch.enable = false;? system.disableInstallerTools = true; nix.settings = { auto-optimise-store = true; min-free = cfg.min-free; max-free = cfg.max-free; trusted-users = [ user ]; }; services = { getty.autologinUser = user; openssh = { enable = true; authorizedKeysFiles = [ "${keysDirectory}/%u_${keyType}.pub" ]; }; }; system.build.macos-builder-installer = let privateKey = "/etc/nix/${user}_${keyType}"; publicKey = "${privateKey}.pub"; # This installCredentials script is written so that it's as easy as # possible for a user to audit before confirming the `sudo` installCredentials = hostPkgs.writeShellScript "install-credentials" '' set -euo pipefail KEYS="''${1}" INSTALL=${hostPkgs.coreutils}/bin/install "''${INSTALL}" -g nixbld -m 600 "''${KEYS}/${user}_${keyType}" ${privateKey} "''${INSTALL}" -g nixbld -m 644 "''${KEYS}/${user}_${keyType}.pub" ${publicKey} ''; hostPkgs = config.virtualisation.host.pkgs; script = hostPkgs.writeShellScriptBin "create-builder" ( '' set -euo pipefail '' + # When running as non-interactively as part of a DarwinConfiguration the working directory # must be set to a writeable directory. (if cfg.workingDirectory != "." then '' ${hostPkgs.coreutils}/bin/mkdir --parent "${cfg.workingDirectory}" cd "${cfg.workingDirectory}" '' else "") + '' KEYS="''${KEYS:-./keys}" ${hostPkgs.coreutils}/bin/mkdir --parent "''${KEYS}" PRIVATE_KEY="''${KEYS}/${user}_${keyType}" PUBLIC_KEY="''${PRIVATE_KEY}.pub" if [ ! -e "''${PRIVATE_KEY}" ] || [ ! -e "''${PUBLIC_KEY}" ]; then ${hostPkgs.coreutils}/bin/rm --force -- "''${PRIVATE_KEY}" "''${PUBLIC_KEY}" ${hostPkgs.openssh}/bin/ssh-keygen -q -f "''${PRIVATE_KEY}" -t ${keyType} -N "" -C 'builder@localhost' fi if ! ${hostPkgs.diffutils}/bin/cmp "''${PUBLIC_KEY}" ${publicKey}; then (set -x; sudo --reset-timestamp ${installCredentials} "''${KEYS}") fi KEYS="$(${hostPkgs.nix}/bin/nix-store --add "$KEYS")" ${lib.getExe config.system.build.vm} ''); in script.overrideAttrs (old: { pos = __curPos; # sets meta.position to point here; see script binding above for package definition meta = (old.meta or { }) // { platforms = lib.platforms.darwin; }; passthru = (old.passthru or { }) // { # Let users in the repl inspect the config nixosConfig = config; nixosOptions = options; }; }); system = { # To prevent gratuitous rebuilds on each change to Nixpkgs nixos.revision = null; # to be updated by module maintainers, see nixpkgs#325610 stateVersion = "24.05"; }; users.users."${user}" = { isNormalUser = true; }; security.polkit.enable = true; security.polkit.extraConfig = '' polkit.addRule(function(action, subject) { if (action.id === "org.freedesktop.login1.power-off" && subject.user === "${user}") { return "yes"; } else { return "no"; } }) ''; virtualisation = { diskSize = cfg.diskSize; memorySize = cfg.memorySize; forwardPorts = [ { from = "host"; guest.port = 22; host.port = cfg.hostPort; } ]; # Disable graphics for the builder since users will likely want to run it # non-interactively in the background. graphics = false; sharedDirectories.keys = { source = "\"$KEYS\""; target = keysDirectory; }; # If we don't enable this option then the host will fail to delegate builds # to the guest, because: # # - The host will lock the path to build # - The host will delegate the build to the guest # - The guest will attempt to lock the same path and fail because # the lockfile on the host is visible on the guest # # Snapshotting the host's /nix/store as an image isolates the guest VM's # /nix/store from the host's /nix/store, preventing this problem. useNixStoreImage = true; # Obviously the /nix/store needs to be writable on the guest in order for it # to perform builds. writableStore = true; # This ensures that anything built on the guest isn't lost when the guest is # restarted. writableStoreUseTmpfs = false; # Pass certificates from host to the guest otherwise when custom CA certificates # are required we can't use the cached builder. useHostCerts = true; }; }; } lib.warnIf (lib.isInOldestRelease 2411) "nixos/modules/profiles/macos-builder.nix has moved to nixos/modules/profiles/nix-builder-vm.nix; please update your NixOS imports." ./nix-builder-vm.nix
nixos/modules/profiles/nix-builder-vm.nix 0 → 100644 +284 −0 Original line number Diff line number Diff line /* This profile uses NixOS to create a remote builder VM to build Linux packages, which can be used to build packages for Linux on other operating systems; primarily macOS. It contains both the relevant guest settings as well as an installer script that manages it as a QEMU virtual machine on the host. */ { config, lib, options, ... }: let keysDirectory = "/var/keys"; user = "builder"; keyType = "ed25519"; cfg = config.virtualisation.darwin-builder; in { imports = [ ../virtualisation/qemu-vm.nix # Avoid a dependency on stateVersion { disabledModules = [ ../virtualisation/nixos-containers.nix ../services/x11/desktop-managers/xterm.nix ]; # swraid's default depends on stateVersion config.boot.swraid.enable = false; options.boot.isContainer = lib.mkOption { default = false; internal = true; }; } ]; options.virtualisation.darwin-builder = with lib; { diskSize = mkOption { default = 20 * 1024; type = types.int; example = 30720; description = "The maximum disk space allocated to the runner in MB"; }; memorySize = mkOption { default = 3 * 1024; type = types.int; example = 8192; description = "The runner's memory in MB"; }; min-free = mkOption { default = 1024 * 1024 * 1024; type = types.int; example = 1073741824; description = '' The threshold (in bytes) of free disk space left at which to start garbage collection on the runner ''; }; max-free = mkOption { default = 3 * 1024 * 1024 * 1024; type = types.int; example = 3221225472; description = '' The threshold (in bytes) of free disk space left at which to stop garbage collection on the runner ''; }; workingDirectory = mkOption { default = "."; type = types.str; example = "/var/lib/darwin-builder"; description = '' The working directory to use to run the script. When running as part of a flake will need to be set to a non read-only filesystem. ''; }; hostPort = mkOption { default = 31022; type = types.int; example = 22; description = '' The localhost host port to forward TCP to the guest port. ''; }; }; config = { # The builder is not intended to be used interactively documentation.enable = false; environment.etc = { "ssh/ssh_host_ed25519_key" = { mode = "0600"; source = ./keys/ssh_host_ed25519_key; }; "ssh/ssh_host_ed25519_key.pub" = { mode = "0644"; source = ./keys/ssh_host_ed25519_key.pub; }; }; # DNS fails for QEMU user networking (SLiRP) on macOS. See: # # https://github.com/utmapp/UTM/issues/2353 # # This works around that by using a public DNS server other than the DNS # server that QEMU provides (normally 10.0.2.3) networking.nameservers = [ "8.8.8.8" ]; # The linux builder is a lightweight VM for remote building; not evaluation. nix.channel.enable = false; # Deployment is by image. # TODO system.switch.enable = false;? system.disableInstallerTools = true; nix.settings = { auto-optimise-store = true; min-free = cfg.min-free; max-free = cfg.max-free; trusted-users = [ user ]; }; services = { getty.autologinUser = user; openssh = { enable = true; authorizedKeysFiles = [ "${keysDirectory}/%u_${keyType}.pub" ]; }; }; system.build.macos-builder-installer = let privateKey = "/etc/nix/${user}_${keyType}"; publicKey = "${privateKey}.pub"; # This installCredentials script is written so that it's as easy as # possible for a user to audit before confirming the `sudo` installCredentials = hostPkgs.writeShellScript "install-credentials" '' set -euo pipefail KEYS="''${1}" INSTALL=${hostPkgs.coreutils}/bin/install "''${INSTALL}" -g nixbld -m 600 "''${KEYS}/${user}_${keyType}" ${privateKey} "''${INSTALL}" -g nixbld -m 644 "''${KEYS}/${user}_${keyType}.pub" ${publicKey} ''; hostPkgs = config.virtualisation.host.pkgs; script = hostPkgs.writeShellScriptBin "create-builder" ( '' set -euo pipefail '' + # When running as non-interactively as part of a DarwinConfiguration the working directory # must be set to a writeable directory. ( if cfg.workingDirectory != "." then '' ${hostPkgs.coreutils}/bin/mkdir --parent "${cfg.workingDirectory}" cd "${cfg.workingDirectory}" '' else "" ) + '' KEYS="''${KEYS:-./keys}" ${hostPkgs.coreutils}/bin/mkdir --parent "''${KEYS}" PRIVATE_KEY="''${KEYS}/${user}_${keyType}" PUBLIC_KEY="''${PRIVATE_KEY}.pub" if [ ! -e "''${PRIVATE_KEY}" ] || [ ! -e "''${PUBLIC_KEY}" ]; then ${hostPkgs.coreutils}/bin/rm --force -- "''${PRIVATE_KEY}" "''${PUBLIC_KEY}" ${hostPkgs.openssh}/bin/ssh-keygen -q -f "''${PRIVATE_KEY}" -t ${keyType} -N "" -C 'builder@localhost' fi if ! ${hostPkgs.diffutils}/bin/cmp "''${PUBLIC_KEY}" ${publicKey}; then (set -x; sudo --reset-timestamp ${installCredentials} "''${KEYS}") fi KEYS="$(${hostPkgs.nix}/bin/nix-store --add "$KEYS")" ${lib.getExe config.system.build.vm} '' ); in script.overrideAttrs (old: { pos = __curPos; # sets meta.position to point here; see script binding above for package definition meta = (old.meta or { }) // { platforms = lib.platforms.darwin; }; passthru = (old.passthru or { }) // { # Let users in the repl inspect the config nixosConfig = config; nixosOptions = options; }; }); system = { # To prevent gratuitous rebuilds on each change to Nixpkgs nixos.revision = null; # to be updated by module maintainers, see nixpkgs#325610 stateVersion = "24.05"; }; users.users."${user}" = { isNormalUser = true; }; security.polkit.enable = true; security.polkit.extraConfig = '' polkit.addRule(function(action, subject) { if (action.id === "org.freedesktop.login1.power-off" && subject.user === "${user}") { return "yes"; } else { return "no"; } }) ''; virtualisation = { diskSize = cfg.diskSize; memorySize = cfg.memorySize; forwardPorts = [ { from = "host"; guest.port = 22; host.port = cfg.hostPort; } ]; # Disable graphics for the builder since users will likely want to run it # non-interactively in the background. graphics = false; sharedDirectories.keys = { source = "\"$KEYS\""; target = keysDirectory; }; # If we don't enable this option then the host will fail to delegate builds # to the guest, because: # # - The host will lock the path to build # - The host will delegate the build to the guest # - The guest will attempt to lock the same path and fail because # the lockfile on the host is visible on the guest # # Snapshotting the host's /nix/store as an image isolates the guest VM's # /nix/store from the host's /nix/store, preventing this problem. useNixStoreImage = true; # Obviously the /nix/store needs to be writable on the guest in order for it # to perform builds. writableStore = true; # This ensures that anything built on the guest isn't lost when the guest is # restarted. writableStoreUseTmpfs = false; # Pass certificates from host to the guest otherwise when custom CA certificates # are required we can't use the cached builder. useHostCerts = true; }; }; }
pkgs/top-level/darwin-packages.nix +1 −1 Original line number Diff line number Diff line Loading @@ -245,7 +245,7 @@ impure-cmds // appleSourcePackages // chooseLibs // { nixos = import ../../nixos { configuration = { imports = [ ../../nixos/modules/profiles/macos-builder.nix ../../nixos/modules/profiles/nix-builder-vm.nix ] ++ modules; # If you need to override this, consider starting with the right Nixpkgs Loading