darwin.builder: init

Fixes https://github.com/NixOS/nixpkgs/issues/108984

This originates from:

https://github.com/Gabriella439/macos-builder

… which in turn originates from:

https://github.com/YorikSar/nixos-vm-on-macos

Changed files
+160
nixos
pkgs
+7
nixos/modules/profiles/keys/ssh_host_ed25519_key
···
···
+
-----BEGIN OPENSSH PRIVATE KEY-----
+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+
QyNTUxOQAAACCQVnMW/wZWqrdWrjrRPhfEFFq1KLYguagSflLhFnVQmwAAAJASuMMnErjD
+
JwAAAAtzc2gtZWQyNTUxOQAAACCQVnMW/wZWqrdWrjrRPhfEFFq1KLYguagSflLhFnVQmw
+
AAAEDIN2VWFyggtoSPXcAFy8dtG1uAig8sCuyE21eMDt2GgJBWcxb/Blaqt1auOtE+F8QU
+
WrUotiC5qBJ+UuEWdVCbAAAACnJvb3RAbml4b3MBAgM=
+
-----END OPENSSH PRIVATE KEY-----
+1
nixos/modules/profiles/keys/ssh_host_ed25519_key.pub
···
···
+
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJBWcxb/Blaqt1auOtE+F8QUWrUotiC5qBJ+UuEWdVCb root@nixos
+134
nixos/modules/profiles/macos-builder.nix
···
···
+
{ config, pkgs, ... }:
+
+
let
+
keysDirectory = "/var/keys";
+
+
user = "builder";
+
+
keyType = "ed25519";
+
+
in
+
+
{ imports = [
+
../virtualisation/qemu-vm.nix
+
];
+
+
# 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" ];
+
+
nix.settings = {
+
auto-optimise-store = true;
+
+
min-free = 1024 * 1024 * 1024;
+
+
max-free = 3 * 1024 * 1024 * 1024;
+
+
trusted-users = [ "root" user ];
+
};
+
+
services.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 = pkgs.writeShellScript "install-credentials" ''
+
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;
+
+
in
+
hostPkgs.writeShellScriptBin "create-builder" ''
+
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="$(nix-store --add "$KEYS")" ${config.system.build.vm}/bin/run-nixos-vm
+
'';
+
+
system.stateVersion = "22.05";
+
+
users.users."${user}"= {
+
isNormalUser = true;
+
};
+
+
virtualisation = {
+
diskSize = 20 * 1024;
+
+
memorySize = 3 * 1024;
+
+
forwardPorts = [
+
{ from = "host"; guest.port = 22; host.port = 22; }
+
];
+
+
# 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;
+
};
+
}
+18
pkgs/top-level/darwin-packages.nix
···
discrete-scroll = callPackage ../os-specific/darwin/discrete-scroll { };
})
···
discrete-scroll = callPackage ../os-specific/darwin/discrete-scroll { };
+
builder =
+
let
+
toGuest = builtins.replaceStrings [ "darwin" ] [ "linux" ];
+
+
nixos = import ../../nixos {
+
configuration = {
+
imports = [
+
../../nixos/modules/profiles/macos-builder.nix
+
];
+
+
virtualisation.host = { inherit pkgs; };
+
};
+
+
system = toGuest stdenv.hostPlatform.system;
+
};
+
+
in
+
nixos.config.system.build.macos-builder-installer;
})