1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.gitlab-runner;
7 configFile =
8 if (cfg.configFile == null) then
9 (pkgs.runCommand "config.toml" {
10 buildInputs = [ pkgs.remarshal ];
11 } ''
12 remarshal -if json -of toml \
13 < ${pkgs.writeText "config.json" (builtins.toJSON cfg.configOptions)} \
14 > $out
15 '')
16 else
17 cfg.configFile;
18 hasDocker = config.virtualisation.docker.enable;
19in
20{
21 options.services.gitlab-runner = {
22 enable = mkEnableOption "Gitlab Runner";
23
24 configFile = mkOption {
25 default = null;
26 description = ''
27 Configuration file for gitlab-runner.
28 Use this option in favor of configOptions to avoid placing CI tokens in the nix store.
29
30 <option>configFile</option> takes precedence over <option>configOptions</option>.
31
32 Warning: Not using <option>configFile</option> will potentially result in secrets
33 leaking into the WORLD-READABLE nix store.
34 '';
35 type = types.nullOr types.path;
36 };
37
38 configOptions = mkOption {
39 description = ''
40 Configuration for gitlab-runner
41 <option>configFile</option> will take precedence over this option.
42
43 Warning: all Configuration, especially CI token, will be stored in a
44 WORLD-READABLE file in the Nix Store.
45
46 If you want to protect your CI token use <option>configFile</option> instead.
47 '';
48 type = types.attrs;
49 example = {
50 concurrent = 2;
51 runners = [{
52 name = "docker-nix-1.11";
53 url = "https://CI/";
54 token = "TOKEN";
55 executor = "docker";
56 builds_dir = "";
57 docker = {
58 host = "";
59 image = "nixos/nix:1.11";
60 privileged = true;
61 disable_cache = true;
62 cache_dir = "";
63 };
64 }];
65 };
66 };
67
68 gracefulTermination = mkOption {
69 default = false;
70 type = types.bool;
71 description = ''
72 Finish all remaining jobs before stopping, restarting or reconfiguring.
73 If not set gitlab-runner will stop immediatly without waiting for jobs to finish,
74 which will lead to failed builds.
75 '';
76 };
77
78 gracefulTimeout = mkOption {
79 default = "infinity";
80 type = types.str;
81 example = "5min 20s";
82 description = ''Time to wait until a graceful shutdown is turned into a forceful one.'';
83 };
84
85 workDir = mkOption {
86 default = "/var/lib/gitlab-runner";
87 type = types.path;
88 description = "The working directory used";
89 };
90
91 package = mkOption {
92 description = "Gitlab Runner package to use";
93 default = pkgs.gitlab-runner;
94 defaultText = "pkgs.gitlab-runner";
95 type = types.package;
96 example = literalExample "pkgs.gitlab-runner_1_11";
97 };
98
99 packages = mkOption {
100 default = [ pkgs.bash pkgs.docker-machine ];
101 defaultText = "[ pkgs.bash pkgs.docker-machine ]";
102 type = types.listOf types.package;
103 description = ''
104 Packages to add to PATH for the gitlab-runner process.
105 '';
106 };
107
108 };
109
110 config = mkIf cfg.enable {
111 systemd.services.gitlab-runner = {
112 path = cfg.packages;
113 environment = config.networking.proxy.envVars;
114 description = "Gitlab Runner";
115 after = [ "network.target" ]
116 ++ optional hasDocker "docker.service";
117 requires = optional hasDocker "docker.service";
118 wantedBy = [ "multi-user.target" ];
119 serviceConfig = {
120 ExecStart = ''${cfg.package.bin}/bin/gitlab-runner run \
121 --working-directory ${cfg.workDir} \
122 --config ${configFile} \
123 --service gitlab-runner \
124 --user gitlab-runner \
125 '';
126
127 } // optionalAttrs (cfg.gracefulTermination) {
128 TimeoutStopSec = "${cfg.gracefulTimeout}";
129 KillSignal = "SIGQUIT";
130 KillMode = "process";
131 };
132 };
133
134 # Make the gitlab-runner command availabe so users can query the runner
135 environment.systemPackages = [ cfg.package ];
136
137 users.users.gitlab-runner = {
138 group = "gitlab-runner";
139 extraGroups = optional hasDocker "docker";
140 uid = config.ids.uids.gitlab-runner;
141 home = cfg.workDir;
142 createHome = true;
143 };
144
145 users.groups.gitlab-runner.gid = config.ids.gids.gitlab-runner;
146 };
147}