diff --git a/config/host-config/plato.nix b/config/host-config/plato.nix index 11bca26..9ac5c7e 100644 --- a/config/host-config/plato.nix +++ b/config/host-config/plato.nix @@ -4,6 +4,12 @@ with lib; let primary-ip = "10.0.0.21"; in { config = { + + # TODO: remove? + nixpkgs.config.permittedInsecurePackages = [ + "openssh-with-gssapi-8.4p1" # CVE-2021-28041 + ]; + environment.etc = { nixos.source = "/state/nixos"; adjtime.source = "/state/etc/adjtime"; diff --git a/config/hosts/plato.nix b/config/hosts/plato.nix index b85e492..8fa9a6c 100644 --- a/config/hosts/plato.nix +++ b/config/hosts/plato.nix @@ -13,4 +13,7 @@ profile = "server"; ssh-pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGuClWAtkOMBOVFAFFdWosCT8NvuJBps46P4RV+Qqz4b"; + build-pubkeys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDMPjwpcktL0Rhjc/D3ZmzwkSRqSJX5TGjMXVstpg8nNqQQrj9DxPq7gV4a+1LxMtQGPUv4gYx7De1a5LMVk8u6qJJnaLlt3TB1e1SUCBxxeh5sWIY5BMx8Q0/aRTkyTchyczX6FX0LXM7FP6yvxZVZSn2WHRp7REr8G1PUAwuIGy2a4bKOUSh5Uj4riXFXnROW2mp1vUfe5oH4X5HP3ACCXWRVUFdqDt1ldcrqqi+7/8x2G1eOHJcQ7B5FdL3uuq0nBrUzFQTt6KCHy0C2Jc3DFwOS1+ZdGKZpao+/arh/fH+LQfMUePx/AQOkYrJwvuRwbxg8XmlZ89u2gyDuqapzjBmsu+wyd5pF2QglyTRZW9Ijy1NTuzduPm6wgqN0Q09evFJvM9ZjShcIY3xTcCGDxpwTeYgMVXMF79sV9u+JwCSBpaIyteIJ7M/J/NWmaKoUF6Ia9mNts889Ba9TKzQFek19KYetOB2hfXV+7bvXrH+OBppzpdrztJFavBceQTs=" + ]; } diff --git a/config/profile-config/common.nix b/config/profile-config/common.nix index 54c1a65..f27b7c4 100644 --- a/config/profile-config/common.nix +++ b/config/profile-config/common.nix @@ -11,10 +11,10 @@ in { systemPackages = global-packages; - shellInit = '' - ${pkgs.gnupg}/bin/gpg-connect-agent /bye - export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket) - ''; + # shellInit = '' + # ${pkgs.gnupg}/bin/gpg-connect-agent /bye + # export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket) + # ''; }; nixpkgs.config.allowUnfree = true; @@ -91,13 +91,12 @@ in { gnupg.agent = { enable = true; - enableSSHSupport = true; + # enableSSHSupport = true; # pinentryFlavor = if cfg.enable-gui then "gnome3" else "curses"; }; ssh = { - # Use GPG agent instead - startAgent = false; + startAgent = true; package = pkgs.openssh_gssapi; diff --git a/config/sites.nix b/config/sites.nix index 1ee6c56..86c3605 100644 --- a/config/sites.nix +++ b/config/sites.nix @@ -11,6 +11,16 @@ gateway-host = "nostromo"; deploy-pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPwh522lvafTJYA0X2uFdP7Ws+Um1f8gZsARK1Y5nMzf6ZcWBF1jplTOKUVSOl4isMWni0Tu0TnX4zqCcgocWUVbwIwXSIRYqdiCPvVOH+/Ibc97n1/dYxk5JPMtbrsEw6/gWZxVg0qwe0J3dQWldEMiDY7iWhlrmIr7YL+Y3PUd7DOwp3PbfWfNyzTfE1kXcz5YvTeN+txFhbbXT0oS2R2wtc1vYXFZ/KbNstjqd+i8jszAq3ZkbbwL3aNR0RO4n8+GoIILGw8Ya4eP7D6+mYk608IhAoxpGyMrUch2TC2uvOK3rd/rw1hsTxf4AKjAZbrfd/FJaYru9ZeoLjD4bRGMdVp56F1m7pLvRiWRK62pV2Q/fjx+4KjHUrgyPd601eUIP0ayS/Rfuq8ijLpBJgO5/Y/6mFus/kjZIfRR9dXfLM67IMpyEzEITYrc/R2sedWf+YHxSh6eguAZ/kLzioar1nHLR7Wzgeu0tgWkD78WQGjpXGoefAz3xHeBg3Et0="; + build-servers = { + nostromo = { + max-jobs = 2; + speed-factor = 2; + }; + lambda = { + max-jobs = 2; + speed-factor = 2; + }; + }; # FIXME: good idea? # network-mounts = { # "/mnt/documents" = { diff --git a/lib/fudo/hosts.nix b/lib/fudo/hosts.nix index 9094eaa..b0993c8 100644 --- a/lib/fudo/hosts.nix +++ b/lib/fudo/hosts.nix @@ -106,6 +106,12 @@ let "SSH key of the host. Find with `ssh-keyscan`. Skip the hostname, just type and key."; default = null; }; + + build-pubkeys = mkOption { + type = listOf str; + description = "SSH public keys used to access the build server."; + default = [ ]; + }; }; }; @@ -124,6 +130,8 @@ in { site = config.fudo.sites.${site-name}; domain-name = host-cfg.domain; domain = config.fudo.domains.${domain-name}; + has-build-servers = (length (attrNames site.build-servers)) > 0; + has-build-keys = (length host-cfg.build-pubkeys) > 0; in { networking = { @@ -138,6 +146,17 @@ in { hosts = { "127.0.0.1" = [ "${hostname}.${domain-name}" "${hostname}" ]; }; }; + nix = mkIf + (has-build-servers && has-build-keys && site.enable-distributed-builds) { + buildMachines = mapAttrsToList (hostname: buildOpts: { + hostName = "${hostname}.${domain}"; + maxJobs = buildOpts.max-jobs; + speedFactor = buildOpts.speed-factor; + supportedFeatures = buildOpts.supported-features; + }) site.build-servers; + distributedBuilds = true; + }; + time.timeZone = site.timezone; krb5.libdefaults.default_realm = domain.gssapi-realm; diff --git a/lib/fudo/sites.nix b/lib/fudo/sites.nix index 7a052af..9389b42 100644 --- a/lib/fudo/sites.nix +++ b/lib/fudo/sites.nix @@ -6,6 +6,9 @@ let site-name = config.fudo.hosts.${hostname}.site; site-cfg = config.fudo.sites.${site-name}; + site-hosts = filterAttrs (hostname: hostOpts: hostOpts.site == site-name) + config.fudo.hosts; + siteOpts = { site, ... }: { options = with types; { site = mkOption { @@ -84,7 +87,12 @@ let default = null; }; - enable-ssh-backdoor = mkEnableOption "Enable a backup SSH server in case of failures of the primary."; + enable-ssh-backdoor = mkOption { + type = bool; + description = + "Enable a backup SSH server in case of failures of the primary."; + default = true; + }; dropbear-rsa-key-path = mkOption { type = str; @@ -98,11 +106,68 @@ let default = "/etc/dropbear/host_ecdsa_key"; }; - dropbear-port = mkOption { + dropbear-ssh-port = mkOption { type = port; description = "Port to be used for the deploy SSH server."; default = 2112; }; + + enable-distributed-builds = + mkEnableOption "Enable distributed builds for the site."; + + build-servers = mkOption { + type = attrsOf (submodule buildServerOpts); + description = + "List of hosts to be used as build servers for the local site."; + default = { }; + example = { + my-build-host = { + port = 22; + systems = [ "i686-linux" "x86_64-linux" ]; + }; + }; + }; + + build-user = mkOption { + type = str; + description = "User as which to run builds."; + default = "nix-site-builder"; + }; + }; + }; + + buildServerOpts = { ... }: { + options = with types; { + port = mkOption { + type = port; + description = "SSH port at which to contact the server."; + default = 22; + }; + + systems = mkOption { + type = listOf str; + description = + "A list of systems for which this build server can build."; + default = [ "i686-linux" "x86_64-linux" ]; + }; + + max-jobs = mkOption { + type = int; + description = "Max build allowed per-system."; + default = 1; + }; + + speed-factor = mkOption { + type = int; + description = "Weight to give this server, i.e. it's relative speed."; + default = 1; + }; + + supported-features = mkOption { + type = listOf str; + description = "List of features supported by this server."; + default = [ ]; + }; }; }; @@ -114,19 +179,29 @@ in { }; config = { - users.users.root.openssh.authorizedKeys.keys = mkIf (site-cfg.deploy-pubkey != null) [ - site-cfg.deploy-pubkey - ]; + users.users = { + root.openssh.authorizedKeys.keys = + mkIf (site-cfg.deploy-pubkey != null) [ site-cfg.deploy-pubkey ]; - networking.firewall.allowedTCPPorts = mkIf site-cfg.enable-ssh-backdoor - [ site-cfg.dropbear-deploy-port ]; + ${site-cfg.build-user} = mkIf + (any (build-host: build-host == config.instance.hostname) + (attrNames site-cfg.build-servers)) { + isSystemUser = true; + openssh.authorizedKeys.keys = + concatMap (hostOpts: hostOpts.build-pubkeys) + (attrValues site-hosts); + }; + }; + + networking.firewall.allowedTCPPorts = + mkIf site-cfg.enable-ssh-backdoor [ site-cfg.dropbear-ssh-port ]; systemd = mkIf site-cfg.enable-ssh-backdoor { sockets = { dropbear-deploy = { wantedBy = [ "sockets.target" ]; socketConfig = { - ListenStream = "0.0.0.0:${toString site-cfg.dropbear-deploy-port}"; + ListenStream = "0.0.0.0:${toString site-cfg.dropbear-ssh-port}"; Accept = true; }; unitConfig = { restartIfChanged = true; }; @@ -162,7 +237,7 @@ in { serviceConfig = { Type = "simple"; ExecStart = - "${pkgs.dropbear}/bin/dropbear -F -i -m -s -j -k -r ${site-cfg.dropbear-rsa-key-path} -r ${site-cfg.dropbear-ecdsa-key-path}"; + "${pkgs.dropbear}/bin/dropbear -F -i -w -m -j -k -r ${site-cfg.dropbear-rsa-key-path} -r ${site-cfg.dropbear-ecdsa-key-path}"; ExecReload = "${pkgs.utillinux}/bin/kill -HUP $MAINPID"; StandardInput = "socket"; };