diff --git a/config/common.nix b/config/common.nix index 4053c8d..cae8ca3 100644 --- a/config/common.nix +++ b/config/common.nix @@ -1,11 +1,14 @@ { config, lib, pkgs, ... }: +with lib; # Config common to all hosts, which don't belong anywhere else { config = let home-generator = pkgs.callPackage ../nix-home {}; host-domain = config.fudo.hosts.${config.instance.hostname}.domain; in { + nix.nixPath = lib.mkBefore [ "/nix/var/nix/profiles/per-user/$USER/channels" ]; + home-manager.users.root = home-generator.generate-config { username = "root"; home-dir = "/root"; diff --git a/config/host-config/lambda.nix b/config/host-config/lambda.nix index 48107b2..cebe035 100644 --- a/config/host-config/lambda.nix +++ b/config/host-config/lambda.nix @@ -6,7 +6,10 @@ let state-dir = "/state"; # This must be a string! in { - boot.loader.grub.copyKernels = true; + boot = { + loader.grub.copyKernels = true; + kernelModules = [ "rpcsec_gss_krb5" ]; + }; networking = { interfaces = { diff --git a/config/sites.nix b/config/sites.nix index 68d1cd5..263269c 100644 --- a/config/sites.nix +++ b/config/sites.nix @@ -11,19 +11,21 @@ gateway-host = "nostromo"; deploy-pubkeys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPwh522lvafTJYA0X2uFdP7Ws+Um1f8gZsARK1Y5nMzf6ZcWBF1jplTOKUVSOl4isMWni0Tu0TnX4zqCcgocWUVbwIwXSIRYqdiCPvVOH+/Ibc97n1/dYxk5JPMtbrsEw6/gWZxVg0qwe0J3dQWldEMiDY7iWhlrmIr7YL+Y3PUd7DOwp3PbfWfNyzTfE1kXcz5YvTeN+txFhbbXT0oS2R2wtc1vYXFZ/KbNstjqd+i8jszAq3ZkbbwL3aNR0RO4n8+GoIILGw8Ya4eP7D6+mYk608IhAoxpGyMrUch2TC2uvOK3rd/rw1hsTxf4AKjAZbrfd/FJaYru9ZeoLjD4bRGMdVp56F1m7pLvRiWRK62pV2Q/fjx+4KjHUrgyPd601eUIP0ayS/Rfuq8ijLpBJgO5/Y/6mFus/kjZIfRR9dXfLM67IMpyEzEITYrc/R2sedWf+YHxSh6eguAZ/kLzioar1nHLR7Wzgeu0tgWkD78WQGjpXGoefAz3xHeBg3Et0=" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDGVez4of30f+j0cWKj5kYCKeFjyNsYvG9UbOMxF5hImD2lP5MSbFBv31gFgHjx3yCG4zQRZlpuyU5uWo0qIwe9N84/LcZcB9WrWKZXDmuof7zPFy0J+Hj+LVLDQI/mVXHNwkMhBMHpPrdwA05EYDAYCYklWT4cSByu10pHtST+olF8i+A+UQgUzgNZzdJVeiYZv6MBDTYsJWptGeDUkl2B0Es3gtbGYcCCfnyS3RC7DIXlDo3NBbAr7WaHY2MBbT+R/+jicn9E3IY3NCM5jENxqmvHy9MDsxEEYgFNm7IDwq4V1VRUWy277YsvRbmEaHb+osOA5u1VNN4z3UftOZcSZgR5C/vR71cENXoPt1YQpCzu7i38ojtvL+tDVEKT7sIovrQw8q1sszNlW2nXh8RSPiIq5TMnrV73MP0egKcr9n3tfxwi1BIkLjvfom/02BkTK9R9v+VMNhYU1YwROhORCiMIgoxUGiUvtH8u38JGr7E0hhMoAjCE5k80WPUivl0=" ]; build-servers = { nostromo = { - max-jobs = 2; + max-jobs = 4; speed-factor = 2; }; lambda = { - max-jobs = 2; + max-jobs = 4; speed-factor = 2; }; }; enable-distributed-builds = false; - keytab-directory = "/state/secrets/kerberos"; + keytab-path = "/state/secrets/kerberos"; + build-key-path = "/state/secrets/build-keys"; # FIXME: good idea? # network-mounts = { # "/mnt/documents" = { @@ -75,6 +77,7 @@ timezone = "America/Winnipeg"; deploy-pubkeys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPwh522lvafTJYA0X2uFdP7Ws+Um1f8gZsARK1Y5nMzf6ZcWBF1jplTOKUVSOl4isMWni0Tu0TnX4zqCcgocWUVbwIwXSIRYqdiCPvVOH+/Ibc97n1/dYxk5JPMtbrsEw6/gWZxVg0qwe0J3dQWldEMiDY7iWhlrmIr7YL+Y3PUd7DOwp3PbfWfNyzTfE1kXcz5YvTeN+txFhbbXT0oS2R2wtc1vYXFZ/KbNstjqd+i8jszAq3ZkbbwL3aNR0RO4n8+GoIILGw8Ya4eP7D6+mYk608IhAoxpGyMrUch2TC2uvOK3rd/rw1hsTxf4AKjAZbrfd/FJaYru9ZeoLjD4bRGMdVp56F1m7pLvRiWRK62pV2Q/fjx+4KjHUrgyPd601eUIP0ayS/Rfuq8ijLpBJgO5/Y/6mFus/kjZIfRR9dXfLM67IMpyEzEITYrc/R2sedWf+YHxSh6eguAZ/kLzioar1nHLR7Wzgeu0tgWkD78WQGjpXGoefAz3xHeBg3Et0=" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDGVez4of30f+j0cWKj5kYCKeFjyNsYvG9UbOMxF5hImD2lP5MSbFBv31gFgHjx3yCG4zQRZlpuyU5uWo0qIwe9N84/LcZcB9WrWKZXDmuof7zPFy0J+Hj+LVLDQI/mVXHNwkMhBMHpPrdwA05EYDAYCYklWT4cSByu10pHtST+olF8i+A+UQgUzgNZzdJVeiYZv6MBDTYsJWptGeDUkl2B0Es3gtbGYcCCfnyS3RC7DIXlDo3NBbAr7WaHY2MBbT+R/+jicn9E3IY3NCM5jENxqmvHy9MDsxEEYgFNm7IDwq4V1VRUWy277YsvRbmEaHb+osOA5u1VNN4z3UftOZcSZgR5C/vR71cENXoPt1YQpCzu7i38ojtvL+tDVEKT7sIovrQw8q1sszNlW2nXh8RSPiIq5TMnrV73MP0egKcr9n3tfxwi1BIkLjvfom/02BkTK9R9v+VMNhYU1YwROhORCiMIgoxUGiUvtH8u38JGr7E0hhMoAjCE5k80WPUivl0=" ]; keytab-directory = "/state/secrets/kerberos"; }; diff --git a/lib/fudo/hosts.nix b/lib/fudo/hosts.nix index 99df101..97f21a3 100644 --- a/lib/fudo/hosts.nix +++ b/lib/fudo/hosts.nix @@ -2,6 +2,8 @@ with lib; let + mapOptional = f: val: if (val != null) then (f val) else null; + hostOpts = { hostname, ... }: { options = with types; { domain = mkOption { @@ -183,14 +185,6 @@ in { #defaultGateway = site.gateway-v4; #defaultGateway6 = site.gateway-v6; - # Necessary to ensure that Kerberos and Avahi both work. Kerberos needs - # the fqdn of the host, whereas Avahi wants just the simple hostname.` - # hosts = { - # "127.0.0.2" = mkForce [ "${hostname}.${domain-name}" "${hostname}" ]; - # "127.0.0.1" = mkForce [ "${hostname}.${domain-name}" "${hostname}" ]; - # "::1" = mkForce [ "${hostname}.${domain-name}" "${hostname}" ]; - # }; - firewall = { enable = (length host-cfg.external-interfaces) > 0; allowedTCPPorts = [ 22 ]; @@ -214,6 +208,11 @@ in { mode = "0444"; }; + fudo.hosts.${hostname}.build-pubkeys = + map builtins.readFile + (map (build-key-path: "${build-key-path}/${hostname}.key.pub") + (optional (site.build-key-path != null) site.build-key-path)); + nix = mkIf (has-build-servers && has-build-keys && site.enable-distributed-builds) { buildMachines = mapAttrsToList (hostname: buildOpts: { @@ -221,6 +220,7 @@ in { maxJobs = buildOpts.max-jobs; speedFactor = buildOpts.speed-factor; supportedFeatures = buildOpts.supported-features; + sshKey = config.fudo.secrets.host-secrets.${hostname}.build-private-key.target-file; }) site.build-servers; distributedBuilds = true; }; @@ -242,18 +242,30 @@ in { boot.tmpOnTmpfs = host-cfg.tmp-on-tmpfs; - fudo.secrets.host-secrets.${hostname}.host-keytab = let - mapOptional = f: val: if (val != null) then (f val) else null; - keytab-file = mapOptional (keytab-path: - if (pathExists keytab-path) then - /. + builtins.toPath keytab-path - else - null) (mapOptional (keytab-dir: "${keytab-dir}/${hostname}.keytab") - site.keytab-directory); - in mkIf (keytab-file != null) { - source-file = /. + builtins.toPath keytab-file; - target-file = "/etc/krb5.keytab"; - user = "root"; + fudo.secrets.host-secrets.${hostname} = { + host-keytab = let + keytab-file = mapOptional (keytab-path: + if (pathExists keytab-path) then + /. + builtins.toPath keytab-path + else + null) (mapOptional (keytab-dir: "${keytab-dir}/${hostname}.keytab") + site.keytab-path); + in mkIf (keytab-file != null) { + source-file = /. + builtins.toPath keytab-file; + target-file = "/etc/krb5.keytab"; + user = "root"; + }; + + build-private-key = let + build-key-file = mapOptional + (build-key-file: if (pathExists build-key-file) then (/. + builtins.toPath build-key-file) else null) + (mapOptional (build-key-path: "${build-key-path}/${hostname}.key") + site.build-key-path); + in mkIf (build-key-file != null) { + source-file = build-key-file; + target-file = "/var/run/nix-build/host.key"; + user = "root"; + }; }; programs.adb.enable = host-cfg.android-dev; diff --git a/lib/fudo/sites.nix b/lib/fudo/sites.nix index 9cd2cd6..2f895c8 100644 --- a/lib/fudo/sites.nix +++ b/lib/fudo/sites.nix @@ -140,7 +140,7 @@ let default = [ ]; }; - keytab-directory = mkOption { + keytab-path = mkOption { type = nullOr str; description = '' Directory containing site keytabs (files named $hostname.keytab). @@ -149,6 +149,16 @@ let ''; default = null; }; + + build-key-path = mkOption { + type = nullOr str; + description = '' + Directory containing host build keys (files named $hostname.key). + + Should exist only on build host. + ''; + default = null; + }; }; }; diff --git a/lib/fudo/users.nix b/lib/fudo/users.nix index bba964c..f644a9e 100644 --- a/lib/fudo/users.nix +++ b/lib/fudo/users.nix @@ -94,6 +94,26 @@ let description = "List of Kerberos principals that map to this user."; default = [ ]; }; + + ssh-keys = mkOption { + type = nullOr (submodule sshKeyOpts); + description = "Path to the user's public and private key files."; + default = null; + }; + }; + }; + + sshKeyOpts = { ... }: { + options = with types; { + private-key = mkOption { + type = str; + description = "Path to the user's private key."; + }; + + public-key = mkOption { + type = str; + description = "Path to the user's public key."; + }; }; }; @@ -211,6 +231,16 @@ in { }) config.fudo.system-users; }; + programs.ssh.extraConfig = mkAfter '' + IdentityFile %h/.ssh/id_rsa + IdentityFile /etc/ssh/private_keys.d/%u.key + ''; + + environment.etc = let + privkey-users = filterAttrs (username: userOpts: userOpts.ssh-keys != null) sys.local-users; + in mapAttrs' (username: userOpts: + nameValuePair "ssh/private_keys.bd/${username}.key" userOpts.ssh-keys.private-key) privkey-users; + users = { users = mapAttrs (username: userOpts: { isNormalUser = true;