1 { config, lib, pkgs, ... }:
6 cfg = config.services.gitolite;
7 # Use writeTextDir to not leak Nix store hash into file name
8 pubkeyFile = (pkgs.writeTextDir "gitolite-admin.pub" cfg.adminPubkey) + "/gitolite-admin.pub";
9 hooks = lib.concatMapStrings (hook: "${hook} ") cfg.commonHooks;
17 description = lib.mdDoc ''
18 Enable gitolite management under the
19 `gitolite` user. After
20 switching to a configuration with Gitolite enabled, you can
21 then run `git clone gitolite@host:gitolite-admin.git` to manage it further.
27 default = "/var/lib/gitolite";
28 description = lib.mdDoc ''
29 The gitolite home directory used to store all repositories. If left as the default value
30 this directory will automatically be created before the gitolite server starts, otherwise
31 the sysadmin is responsible for ensuring the directory exists with appropriate ownership
36 adminPubkey = mkOption {
38 description = lib.mdDoc ''
39 Initial administrative public key for Gitolite. This should
40 be an SSH Public Key. Note that this key will only be used
41 once, upon the first initialization of the Gitolite user.
42 The key string cannot have any line breaks in it.
46 enableGitAnnex = mkOption {
49 description = lib.mdDoc ''
50 Enable git-annex support. Uses the `extraGitoliteRc` option
51 to apply the necessary configuration.
55 commonHooks = mkOption {
56 type = types.listOf types.path;
58 description = lib.mdDoc ''
59 A list of custom git hooks that get copied to `~/.gitolite/hooks/common`.
63 extraGitoliteRc = mkOption {
66 example = literalExpression ''
69 $RC{SITE_INFO} = 'This is our private repository host';
70 push( @{$RC{ENABLE}}, 'Kindergarten' ); # enable the command/feature
71 @{$RC{ENABLE}} = grep { $_ ne 'desc' } @{$RC{ENABLE}}; # disable the command/feature
74 description = lib.mdDoc ''
75 Extra configuration to append to the default `~/.gitolite.rc`.
77 This should be Perl code that modifies the `%RC`
78 configuration variable. The default `~/.gitolite.rc`
79 content is generated by invoking `gitolite print-default-rc`,
80 and extra configuration from this option is appended to it. The result
81 is placed to Nix store, and the `~/.gitolite.rc` file
82 becomes a symlink to it.
84 If you already have a customized (or otherwise changed)
85 `~/.gitolite.rc` file, NixOS will refuse to replace
86 it with a symlink, and the `gitolite-init` initialization service
87 will fail. In this situation, in order to use this option, you
88 will need to take any customizations you may have in
89 `~/.gitolite.rc`, convert them to appropriate Perl
90 statements, add them to this option, and remove the file.
92 See also the `enableGitAnnex` option.
99 description = lib.mdDoc ''
100 Gitolite user account. This is the username of the gitolite endpoint.
104 description = mkOption {
106 default = "Gitolite user";
107 description = lib.mdDoc ''
108 Gitolite user account's description.
114 default = "gitolite";
115 description = lib.mdDoc ''
116 Primary group of the Gitolite user account.
122 config = mkIf cfg.enable (
124 manageGitoliteRc = cfg.extraGitoliteRc != "";
125 rcDir = pkgs.runCommand "gitolite-rc" { preferLocalBuild = true; } rcDirScript;
129 export HOME=temp-home
130 mkdir -p "$HOME/.gitolite/logs" # gitolite can't run without it
131 '${pkgs.gitolite}'/bin/gitolite print-default-rc >>"$out/gitolite.rc.default"
132 cat <<END >>"$out/gitolite.rc"
133 # This file is managed by NixOS.
134 # Use services.gitolite options to control it.
137 cat "$out/gitolite.rc.default" >>"$out/gitolite.rc"
139 optionalString (cfg.extraGitoliteRc != "") ''
140 echo -n ${escapeShellArg ''
143 ${removeSuffix "\n" cfg.extraGitoliteRc}
145 # per perl rules, this should be the last line in such a file:
147 ''} >>"$out/gitolite.rc"
150 services.gitolite.extraGitoliteRc = optionalString cfg.enableGitAnnex ''
151 # Enable git-annex support:
152 push( @{$RC{ENABLE}}, 'git-annex-shell ua');
155 users.users.${cfg.user} = {
156 description = cfg.description;
158 uid = config.ids.uids.gitolite;
160 useDefaultShell = true;
162 users.groups.${cfg.group}.gid = config.ids.gids.gitolite;
164 systemd.services.gitolite-init = {
165 description = "Gitolite initialization";
166 wantedBy = [ "multi-user.target" ];
167 unitConfig.RequiresMountsFor = cfg.dataDir;
170 GITOLITE_RC = ".gitolite.rc";
171 GITOLITE_RC_DEFAULT = "${rcDir}/gitolite.rc.default";
174 serviceConfig = mkMerge [
175 (mkIf (cfg.dataDir == "/var/lib/gitolite") {
176 StateDirectory = "gitolite gitolite/.gitolite gitolite/.gitolite/logs";
177 StateDirectoryMode = "0750";
183 WorkingDirectory = "~";
184 RemainAfterExit = true;
188 path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ];
191 rcSetupScriptIfCustomFile =
192 if manageGitoliteRc then ''
194 <3>ERROR: NixOS can't apply declarative configuration
195 <3>to your .gitolite.rc file, because it seems to be
196 <3>already customized manually.
197 <3>See the services.gitolite.extraGitoliteRc option
198 <3>in "man configuration.nix" for more information.
200 # Not sure if the line below addresses the issue directly or just
201 # adds a delay, but without it our error message often doesn't
202 # show up in `systemctl status gitolite-init`.
208 rcSetupScriptIfDefaultFileOrStoreSymlink =
209 if manageGitoliteRc then ''
210 ln -sf "${rcDir}/gitolite.rc" "$GITOLITE_RC"
212 [[ -L "$GITOLITE_RC" ]] && rm -f "$GITOLITE_RC"
216 if ( [[ ! -e "$GITOLITE_RC" ]] && [[ ! -L "$GITOLITE_RC" ]] ) ||
217 ( [[ -f "$GITOLITE_RC" ]] && diff -q "$GITOLITE_RC" "$GITOLITE_RC_DEFAULT" >/dev/null ) ||
218 ( [[ -L "$GITOLITE_RC" ]] && [[ "$(readlink "$GITOLITE_RC")" =~ ^/nix/store/ ]] )
220 '' + rcSetupScriptIfDefaultFileOrStoreSymlink +
223 '' + rcSetupScriptIfCustomFile +
227 if [ ! -d repositories ]; then
228 gitolite setup -pk ${pubkeyFile}
230 if [ -n "${hooks}" ]; then
231 cp -f ${hooks} .gitolite/hooks/common/
232 chmod +x .gitolite/hooks/common/*
234 gitolite setup # Upgrade if needed
238 environment.systemPackages = [ pkgs.gitolite pkgs.git ]
239 ++ optional cfg.enableGitAnnex pkgs.git-annex;