diff --git a/example-deployment/hydra/processes.nix b/example-deployment/hydra/processes.nix new file mode 100644 index 0000000..c6cefde --- /dev/null +++ b/example-deployment/hydra/processes.nix @@ -0,0 +1,85 @@ +{ pkgs ? import { inherit system; } +, system ? builtins.currentSystem +, stateDir ? "/var" +, runtimeDir ? "${stateDir}/run" +, logDir ? "${stateDir}/log" +, cacheDir ? "${stateDir}/cache" +, tmpDir ? (if stateDir == "/var" then "/tmp" else "${stateDir}/tmp") +, forceDisableUserChange ? false +, processManager +}: + +let + constructors = import ../../services-agnostic/constructors.nix { + inherit pkgs stateDir runtimeDir logDir tmpDir cacheDir forceDisableUserChange processManager; + }; + + instanceSuffix = ""; + hydraUser = hydraInstanceName; + hydraInstanceName = "hydra${instanceSuffix}"; + hydraQueueRunnerUser = "hydra-queue-runner${instanceSuffix}"; + hydraServerUser = "hydra-www${instanceSuffix}"; +in +rec { + nix-daemon = { + pkg = constructors.nix-daemon; + }; + + postgresql = rec { + port = 5432; + postgresqlUsername = "postgresql"; + postgresqlPassword = "postgresql"; + socketFile = "${runtimeDir}/postgresql/.s.PGSQL.${toString port}"; + + pkg = constructors.simplePostgresql { + inherit port; + authentication = '' + # TYPE DATABASE USER ADDRESS METHOD + local hydra all ident map=hydra-users + ''; + identMap = '' + # MAPNAME SYSTEM-USERNAME PG-USERNAME + hydra-users ${hydraUser} ${hydraUser} + hydra-users ${hydraQueueRunnerUser} ${hydraUser} + hydra-users ${hydraServerUser} ${hydraUser} + hydra-users root ${hydraUser} + # The postgres user is used to create the pg_trgm extension for the hydra database + hydra-users postgresql postgresql + ''; + }; + }; + + hydra-server = rec { + port = 3000; + hydraDatabase = hydraInstanceName; + hydraGroup = hydraInstanceName; + baseDir = "${stateDir}/lib/${hydraInstanceName}"; + inherit hydraUser instanceSuffix; + + pkg = constructors.hydra-server { + postgresqlDBMS = postgresql; + user = hydraServerUser; + inherit nix-daemon port instanceSuffix hydraInstanceName hydraDatabase hydraUser hydraGroup baseDir; + }; + }; + + hydra-evaluator = { + pkg = constructors.hydra-evaluator { + inherit nix-daemon hydra-server; + }; + }; + + hydra-queue-runner = { + pkg = constructors.hydra-queue-runner { + inherit nix-daemon hydra-server; + user = hydraQueueRunnerUser; + }; + }; + + apache = { + pkg = constructors.reverseProxyApache { + dependency = hydra-server; + serverAdmin = "admin@localhost"; + }; + }; +} diff --git a/example-deployment/idresources.nix b/example-deployment/services/idresources.nix similarity index 100% rename from example-deployment/idresources.nix rename to example-deployment/services/idresources.nix diff --git a/example-deployment/ids.nix b/example-deployment/services/ids.nix similarity index 100% rename from example-deployment/ids.nix rename to example-deployment/services/ids.nix diff --git a/example-deployment/processes.nix b/example-deployment/services/processes.nix similarity index 97% rename from example-deployment/processes.nix rename to example-deployment/services/processes.nix index 5282a4b..53c5c43 100644 --- a/example-deployment/processes.nix +++ b/example-deployment/services/processes.nix @@ -12,7 +12,7 @@ let ids = if builtins.pathExists ./ids.nix then (import ./ids.nix).ids else {}; - constructors = import ../services-agnostic/constructors.nix { + constructors = import ../../services-agnostic/constructors.nix { inherit pkgs stateDir runtimeDir logDir tmpDir cacheDir forceDisableUserChange processManager ids; }; in diff --git a/services-agnostic/constructors.nix b/services-agnostic/constructors.nix index 1dd049e..0206eff 100644 --- a/services-agnostic/constructors.nix +++ b/services-agnostic/constructors.nix @@ -50,6 +50,23 @@ in inherit (pkgs) docker kmod; }; + hydra-evaluator = import ./hydra/hydra-evaluator.nix { + inherit createManagedProcess; + hydra = pkgs.hydra-unstable; + }; + + hydra-queue-runner = import ./hydra/hydra-queue-runner.nix { + inherit (pkgs) stdenv nix; + inherit createManagedProcess forceDisableUserChange; + hydra = pkgs.hydra-unstable; + }; + + hydra-server = import ./hydra/hydra-server.nix { + inherit createManagedProcess stateDir forceDisableUserChange; + inherit (pkgs) stdenv writeTextFile postgresql su; + hydra = pkgs.hydra-unstable; + }; + influxdb = import ./influxdb { inherit createManagedProcess stateDir; inherit (pkgs) influxdb; @@ -90,6 +107,11 @@ in inherit (pkgs) stdenv writeTextFile nginx; }; + nix-daemon = import ./nix-daemon { + inherit createManagedProcess; + inherit (pkgs) nix; + }; + openssh = import ./openssh { inherit createManagedProcess stateDir runtimeDir tmpDir forceDisableUserChange; inherit (pkgs) writeTextFile openssh; diff --git a/services-agnostic/hydra/generate-env-vars.nix b/services-agnostic/hydra/generate-env-vars.nix new file mode 100644 index 0000000..a8a63b0 --- /dev/null +++ b/services-agnostic/hydra/generate-env-vars.nix @@ -0,0 +1,12 @@ +{baseDir, hydraDatabase ? null, hydraUser ? null, dbi ? null}: + +let + _dbi = if dbi == null then "dbi:Pg:dbname=${hydraDatabase};user=${hydraUser};" else dbi; +in +{ + HYDRA_DBI = _dbi; + HYDRA_CONFIG = "${baseDir}/hydra.conf"; + HYDRA_DATA = baseDir; + NIX_REMOTE = "daemon"; + PGPASSFILE = "${baseDir}/pgpass"; +} diff --git a/services-agnostic/hydra/hydra-evaluator.nix b/services-agnostic/hydra/hydra-evaluator.nix new file mode 100644 index 0000000..a91d28f --- /dev/null +++ b/services-agnostic/hydra/hydra-evaluator.nix @@ -0,0 +1,29 @@ +{createManagedProcess, hydra}: +{nix-daemon, hydra-server}: + +let + instanceName = "hydra-evaluator${hydra-server.instanceSuffix}"; + + # TODO: ExecStopPost /bin/hydra-evaluator --unlock +in +createManagedProcess { + name = instanceName; + inherit instanceName; + dependencies = [ nix-daemon.pkg hydra-server.pkg ]; + path = [ hydra ]; + environment = import ./generate-env-vars.nix { + inherit (hydra-server) baseDir hydraDatabase hydraUser; + }; + directory = hydra-server.baseDir; + foregroundProcess = "${hydra}/bin/hydra-evaluator"; + user = hydra-server.hydraUser; + + overrides = { + sysvinit = { + runlevels = [ 3 4 5 ]; + }; + systemd = { + Service.Restart = "always"; + }; + }; +} diff --git a/services-agnostic/hydra/hydra-queue-runner.nix b/services-agnostic/hydra/hydra-queue-runner.nix new file mode 100644 index 0000000..226270f --- /dev/null +++ b/services-agnostic/hydra/hydra-queue-runner.nix @@ -0,0 +1,58 @@ +{createManagedProcess, stdenv, hydra, nix, forceDisableUserChange}: +{nix-daemon, hydra-server, user ? null}: + +# TODO: execStopPost: /bin/hydra-queue-runner --unlock + +let + instanceName = "hydra-queue-runner${hydra-server.instanceSuffix}"; + _user = if user == null then instanceName else user; + queueRunnerBaseDir = "${hydra-server.baseDir}/queue-runner"; +in +createManagedProcess { + name = instanceName; + inherit instanceName; + environment = import ./generate-env-vars.nix { + inherit (hydra-server) baseDir hydraDatabase hydraUser; + } // { + LOGNAME = "hydra-queue-runner"; + }; + user = _user; + path = [ nix ]; + directory = queueRunnerBaseDir; + initialize = '' + mkdir -m 0700 -p ${queueRunnerBaseDir} + mkdir -m 0750 -p ${hydra-server.baseDir}/build-logs + ${stdenv.lib.optionalString (!forceDisableUserChange) '' + chown ${user}:${hydra-server.hydraGroup} ${queueRunnerBaseDir} ${hydra-server.baseDir}/build-logs + ''} + ''; + foregroundProcess = "${hydra}/bin/hydra-queue-runner"; + args = [ "-v" ]; + dependencies = [ nix-daemon.pkg hydra-server.pkg ]; + + credentials = { + users = { + "${user}" = { + group = hydra-server.hydraGroup; + description = "Hydra queue runner"; + homeDir = queueRunnerBaseDir; + shell = "/bin/sh"; + }; + }; + }; + + overrides = { + sysvinit = { + runlevels = [ 3 4 5 ]; + }; + systemd = { + Service = { + Restart = "always"; + LimitCORE = "infinity"; + Environment = { + IN_SYSTEMD = "1"; + }; + }; + }; + }; +} diff --git a/services-agnostic/hydra/hydra-server.nix b/services-agnostic/hydra/hydra-server.nix new file mode 100644 index 0000000..716753b --- /dev/null +++ b/services-agnostic/hydra/hydra-server.nix @@ -0,0 +1,118 @@ +{createManagedProcess, stdenv, writeTextFile, hydra, postgresql, su, stateDir, forceDisableUserChange}: + +{ instanceSuffix ? "" +, instanceName ? "hydra-server${instanceSuffix}" + +, hydraInstanceName ? "hydra${instanceSuffix}" +, hydraDatabase ? hydraInstanceName +, hydraUser ? hydraInstanceName +, hydraGroup ? hydraInstanceName + +, user ? "hydra-www${instanceSuffix}" +, listenHost ? "*" +, port ? 3000 +, baseDir ? "${stateDir}/lib/${hydraInstanceName}" +, dbi ? null +, gcRootsDir ? "/nix/var/nix/gcroots/${hydraInstanceName}" +, hydraURL ? "http://localhost" +, notificationSender ? "root@localhost" +, logo ? null +, useSubstitutes ? true + +, postgresqlDBMS ? null +, nix-daemon +}: + +let + hydraConf = writeTextFile { + name = "hydra.conf"; + text = '' + using_frontend_proxy = 1 + base_uri = ${hydraURL} + notification_sender = ${notificationSender} + max_servers = 25 + compress_num_threads = 0 + ${stdenv.lib.optionalString (logo != null) '' + hydra_logo = ${logo} + ''} + gc_roots_dir = ${gcRootsDir} + use-substitutes = ${if useSubstitutes then "1" else "0"} + ''; + }; +in +createManagedProcess { + name = instanceName; + inherit instanceName user; + + path = [ postgresql su ]; + + initialize = '' + ln -sfn ${hydraConf} ${baseDir}/hydra.conf + + mkdir -m 0700 -p ${baseDir}/www + mkdir -p ${gcRootsDir} + + ${stdenv.lib.optionalString (!forceDisableUserChange) '' + chown ${user}:${hydraGroup} ${baseDir}/www + chown ${hydraUser}:${hydraGroup} ${gcRootsDir} + ''} + + chmod 2775 ${gcRootsDir} + + ${stdenv.lib.optionalString (postgresqlDBMS != null) '' + if [ ! -e ${baseDir}/.db-created ] + then + count=1 + + while [ ! -e ${postgresqlDBMS.socketFile} ] && [ $count -lt 10 ] + do + sleep 1 + ((count++)) + done + + ${stdenv.lib.optionalString (!forceDisableUserChange) "su ${postgresqlDBMS.postgresqlUsername} -c '"}createuser ${hydraUser}${stdenv.lib.optionalString (!forceDisableUserChange) "'"} + ${stdenv.lib.optionalString (!forceDisableUserChange) "su ${postgresqlDBMS.postgresqlUsername} -c '"}createdb -O ${hydraUser} ${hydraDatabase}${stdenv.lib.optionalString (!forceDisableUserChange) "'"} + echo "create extension if not exists pg_trgm" | ${stdenv.lib.optionalString (!forceDisableUserChange) "su ${postgresqlDBMS.postgresqlUsername} -c '"}psql ${hydraDatabase}${stdenv.lib.optionalString (!forceDisableUserChange) "'"} + touch ${baseDir}/.db-created + fi + ''} + + ${hydra}/bin/hydra-init + ''; + foregroundProcess = "${hydra}/bin/hydra-server"; + args = [ "hydra-server" "-f" "-h" listenHost "-p" port "--max_spare_servers" 5 "--max_servers" 25 ]; + + environment = import ./generate-env-vars.nix { + inherit baseDir dbi hydraDatabase hydraUser; + }; + + dependencies = [ nix-daemon.pkg ] ++ stdenv.lib.optional (postgresqlDBMS != null) postgresqlDBMS.pkg; + + credentials = { + groups = { + "${hydraGroup}" = {}; + }; + users = { + "${hydraUser}" = { + group = hydraGroup; + description = "Hydra user"; + createHomeDir = true; + homeDir = baseDir; + shell = "/bin/sh"; + }; + "${user}" = { + group = hydraGroup; + description = "Hydra server user"; + }; + }; + }; + + overrides = { + sysvinit = { + runlevels = [ 3 4 5 ]; + }; + systemd = { + Service.Restart = "always"; + }; + }; +} diff --git a/services-agnostic/nix-daemon/default.nix b/services-agnostic/nix-daemon/default.nix new file mode 100644 index 0000000..d5530ad --- /dev/null +++ b/services-agnostic/nix-daemon/default.nix @@ -0,0 +1,13 @@ +{createManagedProcess, nix}: + +createManagedProcess { + name = "nix-daemon"; + foregroundProcess = "${nix}/bin/nix-daemon"; + path = [ nix ]; + + overrides = { + sysvinit = { + runlevels = [ 2 3 4 5 ]; + }; + }; +}