2024-07-09 22:43:03 +00:00
|
|
|
{ nodes, config, lib, pkgs, ... }:
|
2024-06-24 14:45:59 +00:00
|
|
|
|
|
|
|
let
|
|
|
|
cfg = config.bagel.services.hydra;
|
2024-07-09 22:43:03 +00:00
|
|
|
ssh-keys = import ../../common/ssh-keys.nix;
|
2024-06-24 14:45:59 +00:00
|
|
|
|
|
|
|
narCacheDir = "/var/cache/hydra/nar-cache";
|
|
|
|
port = 3000;
|
|
|
|
|
|
|
|
mkCacheSettings = settings: builtins.concatStringsSep "&" (
|
|
|
|
lib.mapAttrsToList (k: v: "${k}=${v}") settings
|
2024-08-16 06:19:18 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
mkPgConnString = options: builtins.concatStringsSep ";" (
|
|
|
|
lib.mapAttrsToList (k: v: "${k}=${v}") options
|
|
|
|
);
|
2024-07-09 22:43:03 +00:00
|
|
|
|
2024-07-10 00:16:45 +00:00
|
|
|
# XXX: to support Nix's dumb public host key syntax (base64'd), this outputs
|
|
|
|
# a string with shell-style command interpolations: $(...).
|
2024-07-30 14:33:47 +00:00
|
|
|
mkBaremetalBuilder = {
|
|
|
|
parallelBuilds,
|
|
|
|
publicHostKey,
|
|
|
|
host,
|
|
|
|
speedFactor ? 1,
|
|
|
|
user ? "builder",
|
|
|
|
supportedSystems ? [ "i686-linux" "x86_64-linux" ],
|
|
|
|
supportedFeatures ? [ "big-parallel" "kvm" "nixos-test" ],
|
|
|
|
requiredFeatures ? [ ]
|
|
|
|
}:
|
|
|
|
let
|
|
|
|
supportedFeatures_ = if (supportedFeatures != []) then lib.concatStringsSep "," supportedFeatures else "-";
|
|
|
|
requiredFeatures_ = if (requiredFeatures != []) then lib.concatStringsSep "," requiredFeatures else "-";
|
|
|
|
in
|
|
|
|
"ssh://${user}@${host}?remote-store=/mnt ${lib.concatStringsSep "," supportedSystems} ${config.age.secrets.hydra-ssh-key-priv.path} ${toString parallelBuilds} ${toString speedFactor} ${supportedFeatures_} ${requiredFeatures_} $(echo -n '${publicHostKey}' | base64 -w0)";
|
2024-07-09 22:43:03 +00:00
|
|
|
|
|
|
|
# TODO:
|
|
|
|
# - generalize to new architectures
|
|
|
|
# - generalize to new features
|
2024-07-10 00:16:45 +00:00
|
|
|
baremetalBuilders = lib.concatStringsSep "\n"
|
2024-07-30 14:33:47 +00:00
|
|
|
(map (n: let
|
|
|
|
assignments = (import ../baremetal-builder/assignments.nix).${n} or {
|
|
|
|
inherit (nodes.${n}.config.nix.settings) max-jobs;
|
|
|
|
supported-features = [ "big-parallel" "kvm" "nixos-test" ];
|
|
|
|
required-features = [];
|
|
|
|
};
|
|
|
|
in mkBaremetalBuilder {
|
|
|
|
parallelBuilds = assignments.max-jobs;
|
|
|
|
supportedFeatures = assignments.supported-features;
|
|
|
|
requiredFeatures = assignments.required-features;
|
2024-07-09 22:43:03 +00:00
|
|
|
publicHostKey = ssh-keys.machines.${n};
|
|
|
|
host = nodes.${n}.config.networking.fqdn;
|
|
|
|
}) cfg.builders);
|
2024-06-24 14:45:59 +00:00
|
|
|
in {
|
|
|
|
options.bagel.services.hydra = with lib; {
|
|
|
|
enable = mkEnableOption "Hydra coordinator";
|
|
|
|
|
2024-07-09 22:43:03 +00:00
|
|
|
builders = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
description = "List of builders to configure for Hydra";
|
|
|
|
example = [ "builder-0" "builder-1" ];
|
|
|
|
};
|
2024-06-24 14:45:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
config = lib.mkIf cfg.enable {
|
2024-07-09 22:43:03 +00:00
|
|
|
# TODO: we should assert or warn that the builders
|
|
|
|
# does indeed have our public SSH key and are *builders*
|
|
|
|
# as a simple evaluation preflight check.
|
|
|
|
|
2024-10-05 16:03:41 +00:00
|
|
|
bagel.secrets.files = [
|
|
|
|
"hydra-s3-credentials"
|
|
|
|
"hydra-postgres-key"
|
|
|
|
"hydra-signing-priv"
|
|
|
|
"hydra-ssh-key-priv"
|
|
|
|
];
|
2024-06-24 18:59:19 +00:00
|
|
|
|
2024-08-16 06:19:18 +00:00
|
|
|
age.secrets.hydra-postgres-key.group = "hydra";
|
|
|
|
age.secrets.hydra-postgres-key.mode = "0440";
|
|
|
|
|
2024-07-10 15:34:57 +00:00
|
|
|
age.secrets.hydra-signing-priv.owner = "hydra-queue-runner";
|
|
|
|
|
2024-06-24 18:59:19 +00:00
|
|
|
age.secrets.hydra-ssh-key-priv.owner = "hydra-queue-runner";
|
|
|
|
|
2024-06-24 14:45:59 +00:00
|
|
|
systemd.tmpfiles.rules = [
|
|
|
|
"d /var/cache/hydra 0755 hydra hydra - -"
|
|
|
|
"d ${narCacheDir} 0755 hydra hydra 1d -"
|
|
|
|
];
|
|
|
|
|
|
|
|
# XXX: Otherwise services.hydra-dev overwrites it to only hydra-queue-runner...
|
|
|
|
#
|
|
|
|
# Can be removed once this is added to some common config template.
|
2024-07-10 15:36:39 +00:00
|
|
|
nix.settings.trusted-users = [ "root" "hydra" "hydra-www" "@wheel" ];
|
2024-06-24 14:45:59 +00:00
|
|
|
|
2024-07-10 16:52:22 +00:00
|
|
|
# Because Hydra can't fetch flake inputs otherwise... also yes, this
|
|
|
|
# prefix-based matching is absurdly bad.
|
|
|
|
nix.settings.allowed-uris = [
|
|
|
|
"github:"
|
|
|
|
"https://github.com/"
|
|
|
|
"https://git.lix.systems/"
|
|
|
|
"https://git@git.lix.systems/"
|
|
|
|
];
|
|
|
|
|
2024-06-24 14:45:59 +00:00
|
|
|
services.hydra-dev = {
|
|
|
|
enable = true;
|
|
|
|
|
2024-08-16 07:20:49 +00:00
|
|
|
listenHost = "127.0.0.1";
|
2024-06-24 14:45:59 +00:00
|
|
|
port = port;
|
2024-08-16 06:19:18 +00:00
|
|
|
|
|
|
|
dbi = "dbi:Pg:${mkPgConnString {
|
|
|
|
host = "postgres.forkos.org";
|
|
|
|
dbname = "hydra";
|
|
|
|
user = "hydra";
|
|
|
|
sslmode = "verify-full";
|
|
|
|
sslcert = "${./postgres.crt}";
|
|
|
|
sslkey = config.age.secrets.hydra-postgres-key.path;
|
|
|
|
sslrootcert = "${../postgres/ca.crt}";
|
|
|
|
}}";
|
2024-06-24 14:45:59 +00:00
|
|
|
|
2024-07-07 21:53:21 +00:00
|
|
|
hydraURL = "https://hydra.forkos.org";
|
2024-06-24 14:45:59 +00:00
|
|
|
useSubstitutes = false;
|
|
|
|
|
2024-07-07 21:53:21 +00:00
|
|
|
notificationSender = "hydra@forkos.org";
|
2024-06-24 14:45:59 +00:00
|
|
|
|
2024-06-24 18:59:37 +00:00
|
|
|
# XXX: hydra overlay sets pkgs.hydra, but hydra's nixos module uses
|
|
|
|
# pkgs.hydra_unstable...
|
|
|
|
package = pkgs.hydra;
|
|
|
|
|
2024-06-24 18:59:19 +00:00
|
|
|
buildMachinesFiles = [
|
2024-07-10 00:16:45 +00:00
|
|
|
(pkgs.runCommandNoCC "hydra-builders.conf" {} ''
|
|
|
|
cat >$out <<EOF
|
|
|
|
${baremetalBuilders}
|
|
|
|
EOF
|
|
|
|
'')
|
2024-06-24 18:59:19 +00:00
|
|
|
];
|
|
|
|
|
2024-06-24 14:45:59 +00:00
|
|
|
extraConfig = ''
|
|
|
|
store_uri = s3://bagel-cache?${mkCacheSettings {
|
|
|
|
endpoint = "s3.delroth.net";
|
|
|
|
region = "garage";
|
|
|
|
|
2024-07-10 15:34:57 +00:00
|
|
|
secret-key = config.age.secrets.hydra-signing-priv.path;
|
2024-06-24 14:45:59 +00:00
|
|
|
|
|
|
|
compression = "zstd";
|
|
|
|
log-compression = "br";
|
|
|
|
ls-compression = "br";
|
|
|
|
|
|
|
|
write-nar-listing = "1";
|
|
|
|
}}
|
|
|
|
|
|
|
|
server_store_uri = https://bagel-cache.s3-web.delroth.net?local-nar-cache=${narCacheDir}
|
|
|
|
binary_cache_public_url = https://bagel-cache.s3-web.delroth.net
|
2024-08-16 07:25:46 +00:00
|
|
|
log_prefix = https://bagel-cache.s3-web.delroth.net/
|
2024-06-24 14:45:59 +00:00
|
|
|
|
|
|
|
upload_logs_to_binary_cache = true
|
|
|
|
|
2024-07-22 21:13:33 +00:00
|
|
|
evaluator_workers = 16
|
2024-06-24 14:45:59 +00:00
|
|
|
evaluator_max_memory_size = 4096
|
|
|
|
max_concurrent_evals = 1
|
|
|
|
|
|
|
|
allow_import_from_derivation = false
|
|
|
|
|
|
|
|
max_output_size = ${builtins.toString (3 * 1024 * 1024 * 1024)}
|
|
|
|
max_db_connections = 100
|
2024-08-16 15:44:45 +00:00
|
|
|
|
|
|
|
<git-input>
|
|
|
|
timeout = 1800
|
|
|
|
</git-input>
|
2024-06-24 14:45:59 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2024-07-19 09:06:03 +00:00
|
|
|
systemd.services.hydra-queue-runner = {
|
|
|
|
# FIXME: should probably be set in the upstream Hydra module?
|
|
|
|
wants = [ "network-online.target" ];
|
|
|
|
serviceConfig.EnvironmentFile = config.age.secrets.hydra-s3-credentials.path;
|
|
|
|
};
|
2024-06-24 16:03:07 +00:00
|
|
|
|
2024-06-24 14:45:59 +00:00
|
|
|
services.nginx = {
|
|
|
|
enable = true;
|
|
|
|
enableReload = true;
|
|
|
|
|
|
|
|
recommendedBrotliSettings = true;
|
|
|
|
recommendedGzipSettings = true;
|
|
|
|
recommendedOptimisation = true;
|
|
|
|
recommendedProxySettings = true;
|
|
|
|
recommendedTlsSettings = true;
|
|
|
|
recommendedZstdSettings = true;
|
|
|
|
|
|
|
|
proxyTimeout = "900s";
|
|
|
|
|
|
|
|
appendConfig = ''
|
|
|
|
worker_processes auto;
|
|
|
|
'';
|
|
|
|
|
2024-07-07 21:53:21 +00:00
|
|
|
virtualHosts."hydra.forkos.org" = {
|
2024-06-24 14:45:59 +00:00
|
|
|
forceSSL = true;
|
|
|
|
enableACME = true;
|
|
|
|
|
|
|
|
locations."/" = {
|
|
|
|
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
|
|
|
};
|
|
|
|
|
|
|
|
locations."/static/" = {
|
|
|
|
alias = "${config.services.hydra-dev.package}/libexec/hydra/root/static/";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
|
|
|
};
|
|
|
|
}
|