2014-05-14 19:06:57 +00:00
|
|
|
{ config, pkgs, lib ? pkgs.lib, ... }:
|
2011-05-05 06:27:38 +00:00
|
|
|
|
2014-05-14 19:06:57 +00:00
|
|
|
with lib;
|
2011-05-05 06:27:38 +00:00
|
|
|
|
|
|
|
let
|
2015-07-01 23:01:44 +00:00
|
|
|
|
2016-10-10 09:29:15 +00:00
|
|
|
cfg = config.services.hydra-dev;
|
2011-05-05 06:27:38 +00:00
|
|
|
|
2013-03-22 16:16:05 +00:00
|
|
|
baseDir = "/var/lib/hydra";
|
|
|
|
|
2013-09-22 23:20:09 +00:00
|
|
|
hydraConf = pkgs.writeScript "hydra.conf" cfg.extraConfig;
|
2013-01-22 13:41:02 +00:00
|
|
|
|
2013-11-06 16:32:50 +00:00
|
|
|
hydraEnv =
|
|
|
|
{ HYDRA_DBI = cfg.dbi;
|
2015-07-01 23:01:44 +00:00
|
|
|
HYDRA_CONFIG = "${baseDir}/hydra.conf";
|
|
|
|
HYDRA_DATA = "${baseDir}";
|
2013-11-06 16:32:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
env =
|
|
|
|
{ NIX_REMOTE = "daemon";
|
2015-07-01 23:01:44 +00:00
|
|
|
PGPASSFILE = "${baseDir}/pgpass";
|
2016-03-25 14:41:38 +00:00
|
|
|
NIX_REMOTE_SYSTEMS = concatStringsSep ":" cfg.buildMachinesFiles;
|
2016-04-13 14:46:24 +00:00
|
|
|
} // optionalAttrs (cfg.smtpHost != null) {
|
|
|
|
EMAIL_SENDER_TRANSPORT = "SMTP";
|
|
|
|
EMAIL_SENDER_TRANSPORT_host = cfg.smtpHost;
|
2014-04-30 16:54:45 +00:00
|
|
|
} // hydraEnv // cfg.extraEnv;
|
2013-11-06 15:17:11 +00:00
|
|
|
|
2013-03-22 12:58:08 +00:00
|
|
|
serverEnv = env //
|
2022-01-05 19:49:18 +00:00
|
|
|
{
|
2015-07-01 23:01:44 +00:00
|
|
|
COLUMNS = "80";
|
2015-07-02 00:55:15 +00:00
|
|
|
PGPASSFILE = "${baseDir}/pgpass-www"; # grrr
|
2017-10-18 13:33:46 +00:00
|
|
|
XDG_CACHE_HOME = "${baseDir}/www/.cache";
|
2016-04-29 01:37:25 +00:00
|
|
|
} // (optionalAttrs cfg.debugServer { DBIC_TRACE = "1"; });
|
2015-07-01 23:01:44 +00:00
|
|
|
|
|
|
|
localDB = "dbi:Pg:dbname=hydra;user=hydra;";
|
|
|
|
|
|
|
|
haveLocalDB = cfg.dbi == localDB;
|
|
|
|
|
2011-05-05 06:27:38 +00:00
|
|
|
in
|
|
|
|
|
|
|
|
{
|
|
|
|
###### interface
|
|
|
|
options = {
|
2013-11-06 16:27:36 +00:00
|
|
|
|
2016-10-10 09:29:15 +00:00
|
|
|
services.hydra-dev = rec {
|
2013-01-22 13:41:02 +00:00
|
|
|
|
2011-05-05 06:27:38 +00:00
|
|
|
enable = mkOption {
|
2013-11-06 15:34:16 +00:00
|
|
|
type = types.bool;
|
2011-05-05 06:27:38 +00:00
|
|
|
default = false;
|
|
|
|
description = ''
|
|
|
|
Whether to run Hydra services.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
dbi = mkOption {
|
2015-06-29 09:28:34 +00:00
|
|
|
type = types.str;
|
2015-07-01 23:01:44 +00:00
|
|
|
default = localDB;
|
2013-11-06 16:07:25 +00:00
|
|
|
example = "dbi:Pg:dbname=hydra;host=postgres.example.org;user=foo;";
|
2011-05-05 06:27:38 +00:00
|
|
|
description = ''
|
2011-05-05 10:07:59 +00:00
|
|
|
The DBI string for Hydra database connection.
|
2021-03-03 23:23:30 +00:00
|
|
|
|
|
|
|
NOTE: Attempts to set `application_name` will be overridden by
|
|
|
|
`hydra-TYPE` (where TYPE is e.g. `evaluator`, `queue-runner`,
|
|
|
|
etc.) in all hydra services to more easily distinguish where
|
|
|
|
queries are coming from.
|
2011-05-05 06:27:38 +00:00
|
|
|
'';
|
|
|
|
};
|
2013-01-22 13:41:02 +00:00
|
|
|
|
2013-11-06 15:34:16 +00:00
|
|
|
package = mkOption {
|
|
|
|
type = types.path;
|
2019-09-17 15:25:59 +00:00
|
|
|
default = pkgs.hydra;
|
2013-11-06 15:34:16 +00:00
|
|
|
description = "The Hydra package.";
|
2011-05-05 06:27:38 +00:00
|
|
|
};
|
2013-01-22 13:41:02 +00:00
|
|
|
|
2011-05-05 06:27:38 +00:00
|
|
|
hydraURL = mkOption {
|
2013-11-06 15:34:16 +00:00
|
|
|
type = types.str;
|
2011-05-05 06:27:38 +00:00
|
|
|
description = ''
|
2013-01-22 13:41:02 +00:00
|
|
|
The base URL for the Hydra webserver instance. Used for links in emails.
|
2011-05-05 06:27:38 +00:00
|
|
|
'';
|
|
|
|
};
|
2011-05-05 10:07:56 +00:00
|
|
|
|
2013-08-28 22:20:51 +00:00
|
|
|
listenHost = mkOption {
|
2013-11-06 15:34:16 +00:00
|
|
|
type = types.str;
|
2013-08-28 22:20:51 +00:00
|
|
|
default = "*";
|
|
|
|
example = "localhost";
|
|
|
|
description = ''
|
|
|
|
The hostname or address to listen on or <literal>*</literal> to listen
|
|
|
|
on all interfaces.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2011-05-05 10:07:56 +00:00
|
|
|
port = mkOption {
|
2013-11-06 15:34:16 +00:00
|
|
|
type = types.int;
|
2011-05-05 10:07:56 +00:00
|
|
|
default = 3000;
|
|
|
|
description = ''
|
|
|
|
TCP port the web server should listen to.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2011-05-05 06:27:38 +00:00
|
|
|
minimumDiskFree = mkOption {
|
2013-11-06 15:34:16 +00:00
|
|
|
type = types.int;
|
2015-07-01 23:01:44 +00:00
|
|
|
default = 0;
|
2011-05-05 06:27:38 +00:00
|
|
|
description = ''
|
2015-10-07 11:12:24 +00:00
|
|
|
Threshold of minimum disk space (GiB) to determine if the queue runner should run or not.
|
2011-05-05 06:27:38 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
minimumDiskFreeEvaluator = mkOption {
|
2013-11-06 15:34:16 +00:00
|
|
|
type = types.int;
|
2015-07-01 23:01:44 +00:00
|
|
|
default = 0;
|
2011-05-05 06:27:38 +00:00
|
|
|
description = ''
|
2015-10-07 11:12:24 +00:00
|
|
|
Threshold of minimum disk space (GiB) to determine if the evaluator should run or not.
|
2011-05-05 06:27:38 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
notificationSender = mkOption {
|
2013-11-06 15:34:16 +00:00
|
|
|
type = types.str;
|
2011-05-05 06:27:38 +00:00
|
|
|
description = ''
|
2013-01-22 13:41:02 +00:00
|
|
|
Sender email address used for email notifications.
|
2011-05-05 06:27:38 +00:00
|
|
|
'';
|
2013-01-22 13:41:02 +00:00
|
|
|
};
|
2011-05-05 06:27:38 +00:00
|
|
|
|
2016-04-13 14:46:24 +00:00
|
|
|
smtpHost = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
example = ["localhost"];
|
|
|
|
description = ''
|
|
|
|
Hostname of the SMTP server to use to send email.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2011-05-05 06:27:38 +00:00
|
|
|
tracker = mkOption {
|
2013-11-06 15:34:16 +00:00
|
|
|
type = types.str;
|
2011-05-05 06:27:38 +00:00
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
Piece of HTML that is included on all pages.
|
|
|
|
'';
|
2011-05-05 10:07:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
logo = mkOption {
|
2013-11-06 16:27:36 +00:00
|
|
|
type = types.nullOr types.path;
|
2011-05-05 10:07:59 +00:00
|
|
|
default = null;
|
|
|
|
description = ''
|
2015-07-01 23:01:44 +00:00
|
|
|
Path to a file containing the logo of your Hydra instance.
|
2011-05-05 10:07:59 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2013-07-28 15:11:09 +00:00
|
|
|
debugServer = mkOption {
|
|
|
|
type = types.bool;
|
2013-11-06 15:34:16 +00:00
|
|
|
default = false;
|
2015-07-01 23:01:44 +00:00
|
|
|
description = "Whether to run the server in debug mode.";
|
2013-07-28 15:11:09 +00:00
|
|
|
};
|
|
|
|
|
2013-09-22 23:20:09 +00:00
|
|
|
extraConfig = mkOption {
|
|
|
|
type = types.lines;
|
2015-07-01 23:01:44 +00:00
|
|
|
description = "Extra lines for the Hydra configuration.";
|
2013-09-22 23:20:09 +00:00
|
|
|
};
|
|
|
|
|
2014-04-30 16:54:45 +00:00
|
|
|
extraEnv = mkOption {
|
|
|
|
type = types.attrsOf types.str;
|
|
|
|
default = {};
|
2015-07-01 23:01:44 +00:00
|
|
|
description = "Extra environment variables for Hydra.";
|
2014-04-30 16:54:45 +00:00
|
|
|
};
|
2015-12-14 12:31:24 +00:00
|
|
|
|
|
|
|
gcRootsDir = mkOption {
|
|
|
|
type = types.path;
|
|
|
|
default = "/nix/var/nix/gcroots/hydra";
|
|
|
|
description = "Directory that holds Hydra garbage collector roots.";
|
|
|
|
};
|
2016-03-25 14:41:38 +00:00
|
|
|
|
|
|
|
buildMachinesFiles = mkOption {
|
2016-05-09 17:09:33 +00:00
|
|
|
type = types.listOf types.path;
|
2016-12-11 14:35:38 +00:00
|
|
|
default = optional (config.nix.buildMachines != []) "/etc/nix/machines";
|
2016-03-25 14:41:38 +00:00
|
|
|
example = [ "/etc/nix/machines" "/var/lib/hydra/provisioner/machines" ];
|
|
|
|
description = "List of files containing build machines.";
|
|
|
|
};
|
2016-04-19 14:12:48 +00:00
|
|
|
|
|
|
|
useSubstitutes = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = ''
|
|
|
|
Whether to use binary caches for downloading store paths. Note that
|
|
|
|
binary substitutions trigger (a potentially large number of) additional
|
|
|
|
HTTP requests that slow down the queue monitor thread significantly.
|
|
|
|
Also, this Hydra instance will serve those downloaded store paths to
|
|
|
|
its users with its own signature attached as if it had built them
|
|
|
|
itself, so don't enable this feature unless your active binary caches
|
|
|
|
are absolute trustworthy.
|
|
|
|
'';
|
|
|
|
};
|
2011-05-05 06:27:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
};
|
2013-01-22 13:41:02 +00:00
|
|
|
|
2011-05-05 06:27:38 +00:00
|
|
|
|
|
|
|
###### implementation
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
2013-11-06 16:27:36 +00:00
|
|
|
|
hydra-module: don't use `createHome = true;` to create Hydra's base-dir
In NixOS, the user generation script was changed to set the permissions `0700`
to a home-directory that's specified in the `users.users`-submodule with
`createHome` being set to `true`[1].
However, the home-directory of `hydra` is also the base directory of other services using
other users (e.g. `hydra-queue-runner`). With permissions being `0700`, processes with
such a user cannot traverse into `/var/lib/hydra` and thus not into subdirectories.
I guess that this issue was kind of hidden because `hydra-init.service` ensures
proper permissions[2]. However, if `hydra-init.service` is not restarted on a
system-activation, the permissions of `/var/lib/hydra` will be set back to `0700`
by the activation script that runs on each activation.
This has lead to errors like this in `hydra-queue-runner` on my Hydra:
```
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/7h/dssz03gazrkqzfmlr5cprd0dvkg4db-squashfs.img.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/b9/350vd8jpv1f86i312c9pkdcd2z56aw-squashfs.img.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/kz/vlq4v9a1rylcp4fsqqav3lcjgskky4-squashfs.img.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/xd/hkjnbbr9jp7364pkn8zpk9v8xapj2c-nix-2.4pre20210917_37cc50f.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/zn/9df7225fl8p7iavqqfvlyay4rf0msw-nix-2.4pre20210917_37cc50f.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: possibly transient failure building ‘/nix/store/7hdssz03gazrkqzfmlr5cprd0dvkg4db-squashfs.img.drv’ on ‘roflmayr’: error: creating directory '/var/lib/hydra/build-logs': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: will retry ‘/nix/store/7hdssz03gazrkqzfmlr5cprd0dvkg4db-squashfs.img.drv’ after 543s
```
Because of that, I decided to remove the `createHome = true;` setting and instead used
`systemd-tmpfiles`[3] which can not only ensure that certain directories
exist, but also proper permissions.
With this change, we can also get rid of the manual setup in
`hydra-init.service` since `systemd-tmpfiles` will be executed by
`switch-to-configuration` before *any* systemd service gets started. On
startup, `systemd-tmpfiles-setup.service` is invoked within
`sysinit.target` being reached, so when `hydra-init.service` gets called
in `multi-user.target`, the structure already exists.
[1] https://github.com/NixOS/nixpkgs/commit/fa0d499dbfa56be0b57b5d822702c624bb434dc1
[2] https://github.com/NixOS/hydra/blob/3cec9087384620c22b5b2a94251408d93664dca0/hydra-module.nix#L260-L262
[3] https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles.html
2021-09-21 21:58:37 +00:00
|
|
|
systemd.tmpfiles.rules = [
|
|
|
|
"d ${baseDir} 0750 hydra hydra"
|
|
|
|
];
|
|
|
|
|
2015-07-01 23:01:44 +00:00
|
|
|
users.extraGroups.hydra = { };
|
|
|
|
|
|
|
|
users.extraUsers.hydra =
|
|
|
|
{ description = "Hydra";
|
|
|
|
group = "hydra";
|
|
|
|
home = baseDir;
|
2021-05-24 12:47:30 +00:00
|
|
|
isSystemUser = true;
|
2015-07-01 23:01:44 +00:00
|
|
|
useDefaultShell = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
users.extraUsers.hydra-queue-runner =
|
|
|
|
{ description = "Hydra queue runner";
|
|
|
|
group = "hydra";
|
|
|
|
useDefaultShell = true;
|
2021-05-24 12:47:30 +00:00
|
|
|
isSystemUser = true;
|
2015-07-02 00:55:15 +00:00
|
|
|
home = "${baseDir}/queue-runner"; # really only to keep SSH happy
|
2015-07-01 23:01:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
users.extraUsers.hydra-www =
|
|
|
|
{ description = "Hydra web server";
|
|
|
|
group = "hydra";
|
2021-05-24 12:47:30 +00:00
|
|
|
isSystemUser = true;
|
2015-07-01 23:01:44 +00:00
|
|
|
useDefaultShell = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
nix.trustedUsers = [ "hydra-queue-runner" ];
|
|
|
|
|
2016-10-10 09:29:15 +00:00
|
|
|
services.hydra-dev.extraConfig =
|
2013-09-22 23:20:09 +00:00
|
|
|
''
|
2017-10-18 12:23:10 +00:00
|
|
|
using_frontend_proxy = 1
|
|
|
|
base_uri = ${cfg.hydraURL}
|
|
|
|
notification_sender = ${cfg.notificationSender}
|
|
|
|
max_servers = 25
|
|
|
|
compress_num_threads = 0
|
2013-11-06 16:27:36 +00:00
|
|
|
${optionalString (cfg.logo != null) ''
|
2017-10-18 12:23:10 +00:00
|
|
|
hydra_logo = ${cfg.logo}
|
2013-11-06 16:27:36 +00:00
|
|
|
''}
|
2017-10-18 12:23:10 +00:00
|
|
|
gc_roots_dir = ${cfg.gcRootsDir}
|
2017-04-10 12:59:58 +00:00
|
|
|
use-substitutes = ${if cfg.useSubstitutes then "1" else "0"}
|
2022-01-05 19:49:18 +00:00
|
|
|
|
|
|
|
${optionalString (cfg.tracker != null) (let
|
|
|
|
indentedTrackerData = lib.concatMapStringsSep "\n" (line: " ${line}") (lib.splitString "\n" cfg.tracker);
|
|
|
|
in ''
|
|
|
|
tracker = <<TRACKER
|
|
|
|
${indentedTrackerData}
|
|
|
|
TRACKER
|
|
|
|
'')}
|
2013-09-22 23:20:09 +00:00
|
|
|
'';
|
|
|
|
|
2013-11-06 15:34:16 +00:00
|
|
|
environment.systemPackages = [ cfg.package ];
|
2011-05-05 06:27:38 +00:00
|
|
|
|
2013-11-06 16:32:50 +00:00
|
|
|
environment.variables = hydraEnv;
|
|
|
|
|
2011-05-05 06:27:38 +00:00
|
|
|
nix.extraOptions = ''
|
|
|
|
gc-keep-outputs = true
|
|
|
|
gc-keep-derivations = true
|
|
|
|
'';
|
|
|
|
|
2015-06-26 13:24:12 +00:00
|
|
|
systemd.services.hydra-init =
|
2013-03-22 12:58:08 +00:00
|
|
|
{ wantedBy = [ "multi-user.target" ];
|
2015-07-02 00:54:16 +00:00
|
|
|
requires = optional haveLocalDB "postgresql.service";
|
|
|
|
after = optional haveLocalDB "postgresql.service";
|
2021-03-03 23:23:30 +00:00
|
|
|
environment = env // {
|
|
|
|
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-init";
|
|
|
|
};
|
2018-07-31 19:41:17 +00:00
|
|
|
path = [ pkgs.utillinux ];
|
2014-04-10 18:09:29 +00:00
|
|
|
preStart = ''
|
2015-07-01 23:01:44 +00:00
|
|
|
ln -sf ${hydraConf} ${baseDir}/hydra.conf
|
|
|
|
|
2015-07-02 00:54:59 +00:00
|
|
|
mkdir -m 0700 -p ${baseDir}/www
|
|
|
|
chown hydra-www.hydra ${baseDir}/www
|
2015-07-01 23:01:44 +00:00
|
|
|
|
2015-07-02 00:54:59 +00:00
|
|
|
mkdir -m 0700 -p ${baseDir}/queue-runner
|
|
|
|
mkdir -m 0750 -p ${baseDir}/build-logs
|
2021-12-26 15:14:10 +00:00
|
|
|
mkdir -m 0750 -p ${baseDir}/runcommand-logs
|
|
|
|
chown hydra-queue-runner.hydra \
|
|
|
|
${baseDir}/queue-runner \
|
|
|
|
${baseDir}/build-logs \
|
|
|
|
${baseDir}/runcommand-logs
|
2015-07-01 23:01:44 +00:00
|
|
|
|
|
|
|
${optionalString haveLocalDB ''
|
2013-11-06 16:07:25 +00:00
|
|
|
if ! [ -e ${baseDir}/.db-created ]; then
|
2018-07-31 19:41:17 +00:00
|
|
|
runuser -u ${config.services.postgresql.superUser} -- ${config.services.postgresql.package}/bin/createuser hydra
|
|
|
|
runuser -u ${config.services.postgresql.superUser} -- ${config.services.postgresql.package}/bin/createdb -O hydra hydra
|
2013-11-06 16:07:25 +00:00
|
|
|
touch ${baseDir}/.db-created
|
|
|
|
fi
|
2019-06-20 12:53:43 +00:00
|
|
|
echo "create extension if not exists pg_trgm" | runuser -u ${config.services.postgresql.superUser} -- ${config.services.postgresql.package}/bin/psql hydra
|
2013-11-06 16:07:25 +00:00
|
|
|
''}
|
2015-12-14 12:31:24 +00:00
|
|
|
|
|
|
|
if [ ! -e ${cfg.gcRootsDir} ]; then
|
|
|
|
|
|
|
|
# Move legacy roots directory.
|
|
|
|
if [ -e /nix/var/nix/gcroots/per-user/hydra/hydra-roots ]; then
|
|
|
|
mv /nix/var/nix/gcroots/per-user/hydra/hydra-roots ${cfg.gcRootsDir}
|
|
|
|
fi
|
|
|
|
|
|
|
|
mkdir -p ${cfg.gcRootsDir}
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Move legacy hydra-www roots.
|
|
|
|
if [ -e /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots ]; then
|
|
|
|
find /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots/ -type f \
|
|
|
|
| xargs -r mv -f -t ${cfg.gcRootsDir}/
|
|
|
|
rmdir /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots
|
|
|
|
fi
|
|
|
|
|
|
|
|
chown hydra.hydra ${cfg.gcRootsDir}
|
|
|
|
chmod 2775 ${cfg.gcRootsDir}
|
2011-05-05 06:27:38 +00:00
|
|
|
'';
|
2014-04-10 18:09:29 +00:00
|
|
|
serviceConfig.ExecStart = "${cfg.package}/bin/hydra-init";
|
2014-04-10 22:06:31 +00:00
|
|
|
serviceConfig.PermissionsStartOnly = true;
|
2014-04-10 18:09:29 +00:00
|
|
|
serviceConfig.User = "hydra";
|
2013-03-22 17:22:00 +00:00
|
|
|
serviceConfig.Type = "oneshot";
|
2013-07-28 15:05:03 +00:00
|
|
|
serviceConfig.RemainAfterExit = true;
|
2013-03-22 12:58:08 +00:00
|
|
|
};
|
2013-11-06 15:17:11 +00:00
|
|
|
|
2015-06-26 13:24:12 +00:00
|
|
|
systemd.services.hydra-server =
|
2013-03-22 12:58:08 +00:00
|
|
|
{ wantedBy = [ "multi-user.target" ];
|
2013-11-06 16:09:24 +00:00
|
|
|
requires = [ "hydra-init.service" ];
|
2013-03-22 12:58:08 +00:00
|
|
|
after = [ "hydra-init.service" ];
|
2021-03-03 23:23:30 +00:00
|
|
|
environment = serverEnv // {
|
|
|
|
HYDRA_DBI = "${serverEnv.HYDRA_DBI};application_name=hydra-server";
|
|
|
|
};
|
2017-06-27 14:01:06 +00:00
|
|
|
restartTriggers = [ hydraConf ];
|
2013-03-22 12:58:08 +00:00
|
|
|
serviceConfig =
|
2013-11-06 16:19:57 +00:00
|
|
|
{ ExecStart =
|
|
|
|
"@${cfg.package}/bin/hydra-server hydra-server -f -h '${cfg.listenHost}' "
|
|
|
|
+ "-p ${toString cfg.port} --max_spare_servers 5 --max_servers 25 "
|
|
|
|
+ "--max_requests 100 ${optionalString cfg.debugServer "-d"}";
|
2015-07-01 23:01:44 +00:00
|
|
|
User = "hydra-www";
|
|
|
|
PermissionsStartOnly = true;
|
2013-03-22 12:58:08 +00:00
|
|
|
Restart = "always";
|
|
|
|
};
|
2011-05-05 06:27:38 +00:00
|
|
|
};
|
|
|
|
|
2015-06-26 13:24:12 +00:00
|
|
|
systemd.services.hydra-queue-runner =
|
2013-03-22 12:58:08 +00:00
|
|
|
{ wantedBy = [ "multi-user.target" ];
|
2013-11-06 16:09:24 +00:00
|
|
|
requires = [ "hydra-init.service" ];
|
2013-03-22 12:58:08 +00:00
|
|
|
after = [ "hydra-init.service" "network.target" ];
|
2016-03-25 15:05:58 +00:00
|
|
|
path = [ cfg.package pkgs.nettools pkgs.openssh pkgs.bzip2 config.nix.package ];
|
2017-06-27 14:01:06 +00:00
|
|
|
restartTriggers = [ hydraConf ];
|
2015-07-02 00:55:15 +00:00
|
|
|
environment = env // {
|
|
|
|
PGPASSFILE = "${baseDir}/pgpass-queue-runner"; # grrr
|
2015-07-20 23:53:56 +00:00
|
|
|
IN_SYSTEMD = "1"; # to get log severity levels
|
2021-03-03 23:23:30 +00:00
|
|
|
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-queue-runner";
|
2015-07-02 00:55:15 +00:00
|
|
|
};
|
2013-03-22 12:58:08 +00:00
|
|
|
serviceConfig =
|
2016-10-07 18:23:05 +00:00
|
|
|
{ ExecStart = "@${cfg.package}/bin/hydra-queue-runner hydra-queue-runner -v";
|
2015-06-26 09:29:30 +00:00
|
|
|
ExecStopPost = "${cfg.package}/bin/hydra-queue-runner --unlock";
|
2015-07-01 23:01:44 +00:00
|
|
|
User = "hydra-queue-runner";
|
2013-03-22 12:58:08 +00:00
|
|
|
Restart = "always";
|
2016-02-28 13:09:04 +00:00
|
|
|
|
|
|
|
# Ensure we can get core dumps.
|
|
|
|
LimitCORE = "infinity";
|
|
|
|
WorkingDirectory = "${baseDir}/queue-runner";
|
2013-03-22 12:58:08 +00:00
|
|
|
};
|
2011-05-05 06:27:38 +00:00
|
|
|
};
|
|
|
|
|
2015-06-26 13:24:12 +00:00
|
|
|
systemd.services.hydra-evaluator =
|
2013-03-22 12:58:08 +00:00
|
|
|
{ wantedBy = [ "multi-user.target" ];
|
2013-11-06 16:09:24 +00:00
|
|
|
requires = [ "hydra-init.service" ];
|
2017-06-27 14:01:06 +00:00
|
|
|
restartTriggers = [ hydraConf ];
|
2013-03-22 12:58:08 +00:00
|
|
|
after = [ "hydra-init.service" "network.target" ];
|
2017-06-21 12:35:26 +00:00
|
|
|
path = with pkgs; [ nettools cfg.package jq ];
|
2021-03-03 23:23:30 +00:00
|
|
|
environment = env // {
|
|
|
|
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-evaluator";
|
|
|
|
};
|
2013-03-22 12:58:08 +00:00
|
|
|
serviceConfig =
|
2013-11-06 15:34:16 +00:00
|
|
|
{ ExecStart = "@${cfg.package}/bin/hydra-evaluator hydra-evaluator";
|
2017-03-13 15:19:22 +00:00
|
|
|
ExecStopPost = "${cfg.package}/bin/hydra-evaluator --unlock";
|
2013-03-22 16:16:05 +00:00
|
|
|
User = "hydra";
|
2013-03-22 12:58:08 +00:00
|
|
|
Restart = "always";
|
2016-03-25 14:41:38 +00:00
|
|
|
WorkingDirectory = baseDir;
|
2013-03-22 12:58:08 +00:00
|
|
|
};
|
2011-05-05 06:27:38 +00:00
|
|
|
};
|
|
|
|
|
2015-06-26 13:24:12 +00:00
|
|
|
systemd.services.hydra-update-gc-roots =
|
2013-11-06 16:09:24 +00:00
|
|
|
{ requires = [ "hydra-init.service" ];
|
2013-03-22 12:58:08 +00:00
|
|
|
after = [ "hydra-init.service" ];
|
2021-03-03 23:23:30 +00:00
|
|
|
environment = env // {
|
|
|
|
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-update-gc-roots";
|
|
|
|
};
|
2013-03-22 12:58:08 +00:00
|
|
|
serviceConfig =
|
2013-11-06 15:34:16 +00:00
|
|
|
{ ExecStart = "@${cfg.package}/bin/hydra-update-gc-roots hydra-update-gc-roots";
|
2013-03-22 16:16:05 +00:00
|
|
|
User = "hydra";
|
2013-03-22 12:58:08 +00:00
|
|
|
};
|
2015-07-01 23:01:44 +00:00
|
|
|
startAt = "2,14:15";
|
2011-05-05 06:27:38 +00:00
|
|
|
};
|
|
|
|
|
2015-06-26 13:24:12 +00:00
|
|
|
systemd.services.hydra-send-stats =
|
|
|
|
{ wantedBy = [ "multi-user.target" ];
|
|
|
|
after = [ "hydra-init.service" ];
|
2021-03-03 23:23:30 +00:00
|
|
|
environment = env // {
|
|
|
|
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-send-stats";
|
|
|
|
};
|
2015-06-26 13:24:12 +00:00
|
|
|
serviceConfig =
|
|
|
|
{ ExecStart = "@${cfg.package}/bin/hydra-send-stats hydra-send-stats";
|
|
|
|
User = "hydra";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2019-08-09 17:26:44 +00:00
|
|
|
systemd.services.hydra-notify =
|
|
|
|
{ wantedBy = [ "multi-user.target" ];
|
|
|
|
requires = [ "hydra-init.service" ];
|
|
|
|
after = [ "hydra-init.service" ];
|
|
|
|
restartTriggers = [ hydraConf ];
|
|
|
|
environment = env // {
|
|
|
|
PGPASSFILE = "${baseDir}/pgpass-queue-runner"; # grrr
|
2021-03-03 23:23:30 +00:00
|
|
|
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-notify";
|
2019-08-09 17:26:44 +00:00
|
|
|
};
|
|
|
|
serviceConfig =
|
|
|
|
{ ExecStart = "@${cfg.package}/bin/hydra-notify hydra-notify";
|
|
|
|
# FIXME: run this under a less privileged user?
|
|
|
|
User = "hydra-queue-runner";
|
2019-08-13 09:19:10 +00:00
|
|
|
Restart = "always";
|
|
|
|
RestartSec = 5;
|
2019-08-09 17:26:44 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-07-01 23:01:44 +00:00
|
|
|
# If there is less than a certain amount of free disk space, stop
|
|
|
|
# the queue/evaluator to prevent builds from failing or aborting.
|
2020-07-27 19:46:57 +00:00
|
|
|
# Leaves a tag file indicating this reason; if the tag file exists
|
|
|
|
# and disk space is above the threshold + 10GB, the queue/evaluator will be
|
|
|
|
# restarted; starting it if it is already started is not harmful.
|
2015-07-01 23:01:44 +00:00
|
|
|
systemd.services.hydra-check-space =
|
|
|
|
{ script =
|
2012-06-14 08:57:12 +00:00
|
|
|
''
|
2020-07-27 19:46:57 +00:00
|
|
|
spaceleft=$(($(stat -f -c '%a' /nix/store) * $(stat -f -c '%S' /nix/store)))
|
|
|
|
spacestopstart() {
|
|
|
|
service=$1
|
|
|
|
minFreeGB=$2
|
|
|
|
if [ $spaceleft -lt $(($minFreeGB * 1024**3)) ]; then
|
|
|
|
if [ $(systemctl is-active $service) == active ]; then
|
|
|
|
echo "stopping $service due to lack of free space..."
|
|
|
|
systemctl stop $service
|
2022-01-28 20:59:11 +00:00
|
|
|
date > ${baseDir}/.$service-stopped-minspace
|
2020-07-27 19:46:57 +00:00
|
|
|
fi
|
|
|
|
else
|
|
|
|
if [ $spaceleft -gt $(( ($minFreeGB + 10) * 1024**3)) -a \
|
2022-01-28 20:59:11 +00:00
|
|
|
-r ${baseDir}/.$service-stopped-minspace ] ; then
|
|
|
|
rm ${baseDir}/.$service-stopped-minspace
|
2020-07-27 19:46:57 +00:00
|
|
|
echo "restarting $service due to newly available free space..."
|
|
|
|
systemctl start $service
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
spacestopstart hydra-queue-runner ${toString cfg.minimumDiskFree}
|
|
|
|
spacestopstart hydra-evaluator ${toString cfg.minimumDiskFreeEvaluator}
|
2012-06-14 08:57:12 +00:00
|
|
|
'';
|
2015-07-01 23:01:44 +00:00
|
|
|
startAt = "*:0/5";
|
|
|
|
};
|
|
|
|
|
2015-10-07 11:12:24 +00:00
|
|
|
# Periodically compress build logs. The queue runner compresses
|
|
|
|
# logs automatically after a step finishes, but this doesn't work
|
|
|
|
# if the queue runner is stopped prematurely.
|
|
|
|
systemd.services.hydra-compress-logs =
|
|
|
|
{ path = [ pkgs.bzip2 ];
|
|
|
|
script =
|
|
|
|
''
|
2022-01-28 20:59:11 +00:00
|
|
|
find ${baseDir}/build-logs -type f -name "*.drv" -mtime +3 -size +0c | xargs -r bzip2 -v -f
|
2022-01-25 19:04:18 +00:00
|
|
|
find ${baseDir}/runcommand-logs -type f -mtime +3 -size +0c | xargs -r bzip2 -v -f
|
2015-10-07 11:12:24 +00:00
|
|
|
'';
|
|
|
|
startAt = "Sun 01:45";
|
|
|
|
};
|
|
|
|
|
2015-07-01 23:01:44 +00:00
|
|
|
services.postgresql.enable = mkIf haveLocalDB true;
|
|
|
|
|
|
|
|
services.postgresql.identMap = optionalString haveLocalDB
|
|
|
|
''
|
|
|
|
hydra-users hydra hydra
|
|
|
|
hydra-users hydra-queue-runner hydra
|
|
|
|
hydra-users hydra-www hydra
|
|
|
|
hydra-users root hydra
|
2019-06-20 12:53:43 +00:00
|
|
|
# The postgres user is used to create the pg_trgm extension for the hydra database
|
|
|
|
hydra-users postgres postgres
|
2015-07-01 23:01:44 +00:00
|
|
|
'';
|
|
|
|
|
|
|
|
services.postgresql.authentication = optionalString haveLocalDB
|
|
|
|
''
|
|
|
|
local hydra all ident map=hydra-users
|
|
|
|
'';
|
|
|
|
|
2012-06-14 08:57:12 +00:00
|
|
|
};
|
2015-07-01 23:01:44 +00:00
|
|
|
|
2011-05-05 06:27:38 +00:00
|
|
|
}
|