grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / misc / gitolite.nix
blob779a9ac9929db75c5409f066c3008cb4d4c1e368
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.gitolite;
4   # Use writeTextDir to not leak Nix store hash into file name
5   pubkeyFile = (pkgs.writeTextDir "gitolite-admin.pub" cfg.adminPubkey) + "/gitolite-admin.pub";
6   hooks = lib.concatMapStrings (hook: "${hook} ") cfg.commonHooks;
7 in
9   options = {
10     services.gitolite = {
11       enable = lib.mkOption {
12         type = lib.types.bool;
13         default = false;
14         description = ''
15           Enable gitolite management under the
16           `gitolite` user. After
17           switching to a configuration with Gitolite enabled, you can
18           then run `git clone gitolite@host:gitolite-admin.git` to manage it further.
19         '';
20       };
22       dataDir = lib.mkOption {
23         type = lib.types.str;
24         default = "/var/lib/gitolite";
25         description = ''
26           The gitolite home directory used to store all repositories. If left as the default value
27           this directory will automatically be created before the gitolite server starts, otherwise
28           the sysadmin is responsible for ensuring the directory exists with appropriate ownership
29           and permissions.
30         '';
31       };
33       adminPubkey = lib.mkOption {
34         type = lib.types.str;
35         description = ''
36           Initial administrative public key for Gitolite. This should
37           be an SSH Public Key. Note that this key will only be used
38           once, upon the first initialization of the Gitolite user.
39           The key string cannot have any line breaks in it.
40         '';
41       };
43       enableGitAnnex = lib.mkOption {
44         type = lib.types.bool;
45         default = false;
46         description = ''
47           Enable git-annex support. Uses the `extraGitoliteRc` option
48           to apply the necessary configuration.
49         '';
50       };
52       commonHooks = lib.mkOption {
53         type = lib.types.listOf lib.types.path;
54         default = [];
55         description = ''
56           A list of custom git hooks that get copied to `~/.gitolite/hooks/common`.
57         '';
58       };
60       extraGitoliteRc = lib.mkOption {
61         type = lib.types.lines;
62         default = "";
63         example = lib.literalExpression ''
64           '''
65             $RC{UMASK} = 0027;
66             $RC{SITE_INFO} = 'This is our private repository host';
67             push( @{$RC{ENABLE}}, 'Kindergarten' ); # enable the command/feature
68             @{$RC{ENABLE}} = grep { $_ ne 'desc' } @{$RC{ENABLE}}; # disable the command/feature
69           '''
70         '';
71         description = ''
72           Extra configuration to append to the default `~/.gitolite.rc`.
74           This should be Perl code that modifies the `%RC`
75           configuration variable. The default `~/.gitolite.rc`
76           content is generated by invoking `gitolite print-default-rc`,
77           and extra configuration from this option is appended to it. The result
78           is placed to Nix store, and the `~/.gitolite.rc` file
79           becomes a symlink to it.
81           If you already have a customized (or otherwise changed)
82           `~/.gitolite.rc` file, NixOS will refuse to replace
83           it with a symlink, and the `gitolite-init` initialization service
84           will fail. In this situation, in order to use this option, you
85           will need to take any customizations you may have in
86           `~/.gitolite.rc`, convert them to appropriate Perl
87           statements, add them to this option, and remove the file.
89           See also the `enableGitAnnex` option.
90         '';
91       };
93       user = lib.mkOption {
94         type = lib.types.str;
95         default = "gitolite";
96         description = ''
97           Gitolite user account. This is the username of the gitolite endpoint.
98         '';
99       };
101       description = lib.mkOption {
102         type = lib.types.str;
103         default = "Gitolite user";
104         description = ''
105           Gitolite user account's description.
106         '';
107       };
109       group = lib.mkOption {
110         type = lib.types.str;
111         default = "gitolite";
112         description = ''
113           Primary group of the Gitolite user account.
114         '';
115       };
116     };
117   };
119   config = lib.mkIf cfg.enable (
120   let
121     manageGitoliteRc = cfg.extraGitoliteRc != "";
122     rcDir = pkgs.runCommand "gitolite-rc" { preferLocalBuild = true; } rcDirScript;
123     rcDirScript =
124       ''
125         mkdir "$out"
126         export HOME=temp-home
127         mkdir -p "$HOME/.gitolite/logs" # gitolite can't run without it
128         '${pkgs.gitolite}'/bin/gitolite print-default-rc >>"$out/gitolite.rc.default"
129         cat <<END >>"$out/gitolite.rc"
130         # This file is managed by NixOS.
131         # Use services.gitolite options to control it.
133         END
134         cat "$out/gitolite.rc.default" >>"$out/gitolite.rc"
135       '' +
136       lib.optionalString (cfg.extraGitoliteRc != "") ''
137         echo -n ${lib.escapeShellArg ''
139           # Added by NixOS:
140           ${lib.removeSuffix "\n" cfg.extraGitoliteRc}
142           # per perl rules, this should be the last line in such a file:
143           1;
144         ''} >>"$out/gitolite.rc"
145       '';
146   in {
147     services.gitolite.extraGitoliteRc = lib.optionalString cfg.enableGitAnnex ''
148       # Enable git-annex support:
149       push( @{$RC{ENABLE}}, 'git-annex-shell ua');
150     '';
152     users.users.${cfg.user} = {
153       description     = cfg.description;
154       home            = cfg.dataDir;
155       uid             = config.ids.uids.gitolite;
156       group           = cfg.group;
157       useDefaultShell = true;
158     };
159     users.groups.${cfg.group}.gid = config.ids.gids.gitolite;
161     systemd.services.gitolite-init = {
162       description = "Gitolite initialization";
163       wantedBy    = [ "multi-user.target" ];
164       unitConfig.RequiresMountsFor = cfg.dataDir;
166       environment = {
167         GITOLITE_RC = ".gitolite.rc";
168         GITOLITE_RC_DEFAULT = "${rcDir}/gitolite.rc.default";
169       };
171       serviceConfig = lib.mkMerge [
172         (lib.mkIf (cfg.dataDir == "/var/lib/gitolite") {
173           StateDirectory = "gitolite gitolite/.gitolite gitolite/.gitolite/logs";
174           StateDirectoryMode = "0750";
175         })
176         {
177           Type = "oneshot";
178           User = cfg.user;
179           Group = cfg.group;
180           WorkingDirectory = "~";
181           RemainAfterExit = true;
182         }
183       ];
185       path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ];
186       script =
187       let
188         rcSetupScriptIfCustomFile =
189           if manageGitoliteRc then ''
190             cat <<END
191             <3>ERROR: NixOS can't apply declarative configuration
192             <3>to your .gitolite.rc file, because it seems to be
193             <3>already customized manually.
194             <3>See the services.gitolite.extraGitoliteRc option
195             <3>in "man configuration.nix" for more information.
196             END
197             # Not sure if the line below addresses the issue directly or just
198             # adds a delay, but without it our error message often doesn't
199             # show up in `systemctl status gitolite-init`.
200             journalctl --flush
201             exit 1
202           '' else ''
203             :
204           '';
205         rcSetupScriptIfDefaultFileOrStoreSymlink =
206           if manageGitoliteRc then ''
207             ln -sf "${rcDir}/gitolite.rc" "$GITOLITE_RC"
208           '' else ''
209             [[ -L "$GITOLITE_RC" ]] && rm -f "$GITOLITE_RC"
210           '';
211       in
212         ''
213           if ( [[ ! -e "$GITOLITE_RC" ]] && [[ ! -L "$GITOLITE_RC" ]] ) ||
214              ( [[ -f "$GITOLITE_RC" ]] && diff -q "$GITOLITE_RC" "$GITOLITE_RC_DEFAULT" >/dev/null ) ||
215              ( [[ -L "$GITOLITE_RC" ]] && [[ "$(readlink "$GITOLITE_RC")" =~ ^/nix/store/ ]] )
216           then
217         '' + rcSetupScriptIfDefaultFileOrStoreSymlink +
218         ''
219           else
220         '' + rcSetupScriptIfCustomFile +
221         ''
222           fi
224           if [ ! -d repositories ]; then
225             gitolite setup -pk ${pubkeyFile}
226           fi
227           if [ -n "${hooks}" ]; then
228             cp -f ${hooks} .gitolite/hooks/common/
229             chmod +x .gitolite/hooks/common/*
230           fi
231           gitolite setup # Upgrade if needed
232         '';
233     };
235     environment.systemPackages = [ pkgs.gitolite pkgs.git ]
236         ++ lib.optional cfg.enableGitAnnex pkgs.git-annex;
237   });