1 { config, lib, pkgs, ... }:
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;
11 enable = lib.mkOption {
12 type = lib.types.bool;
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.
22 dataDir = lib.mkOption {
24 default = "/var/lib/gitolite";
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
33 adminPubkey = lib.mkOption {
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.
43 enableGitAnnex = lib.mkOption {
44 type = lib.types.bool;
47 Enable git-annex support. Uses the `extraGitoliteRc` option
48 to apply the necessary configuration.
52 commonHooks = lib.mkOption {
53 type = lib.types.listOf lib.types.path;
56 A list of custom git hooks that get copied to `~/.gitolite/hooks/common`.
60 extraGitoliteRc = lib.mkOption {
61 type = lib.types.lines;
63 example = lib.literalExpression ''
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
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.
97 Gitolite user account. This is the username of the gitolite endpoint.
101 description = lib.mkOption {
102 type = lib.types.str;
103 default = "Gitolite user";
105 Gitolite user account's description.
109 group = lib.mkOption {
110 type = lib.types.str;
111 default = "gitolite";
113 Primary group of the Gitolite user account.
119 config = lib.mkIf cfg.enable (
121 manageGitoliteRc = cfg.extraGitoliteRc != "";
122 rcDir = pkgs.runCommand "gitolite-rc" { preferLocalBuild = true; } rcDirScript;
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.
134 cat "$out/gitolite.rc.default" >>"$out/gitolite.rc"
136 lib.optionalString (cfg.extraGitoliteRc != "") ''
137 echo -n ${lib.escapeShellArg ''
140 ${lib.removeSuffix "\n" cfg.extraGitoliteRc}
142 # per perl rules, this should be the last line in such a file:
144 ''} >>"$out/gitolite.rc"
147 services.gitolite.extraGitoliteRc = lib.optionalString cfg.enableGitAnnex ''
148 # Enable git-annex support:
149 push( @{$RC{ENABLE}}, 'git-annex-shell ua');
152 users.users.${cfg.user} = {
153 description = cfg.description;
155 uid = config.ids.uids.gitolite;
157 useDefaultShell = true;
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;
167 GITOLITE_RC = ".gitolite.rc";
168 GITOLITE_RC_DEFAULT = "${rcDir}/gitolite.rc.default";
171 serviceConfig = lib.mkMerge [
172 (lib.mkIf (cfg.dataDir == "/var/lib/gitolite") {
173 StateDirectory = "gitolite gitolite/.gitolite gitolite/.gitolite/logs";
174 StateDirectoryMode = "0750";
180 WorkingDirectory = "~";
181 RemainAfterExit = true;
185 path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ];
188 rcSetupScriptIfCustomFile =
189 if manageGitoliteRc then ''
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.
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`.
205 rcSetupScriptIfDefaultFileOrStoreSymlink =
206 if manageGitoliteRc then ''
207 ln -sf "${rcDir}/gitolite.rc" "$GITOLITE_RC"
209 [[ -L "$GITOLITE_RC" ]] && rm -f "$GITOLITE_RC"
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/ ]] )
217 '' + rcSetupScriptIfDefaultFileOrStoreSymlink +
220 '' + rcSetupScriptIfCustomFile +
224 if [ ! -d repositories ]; then
225 gitolite setup -pk ${pubkeyFile}
227 if [ -n "${hooks}" ]; then
228 cp -f ${hooks} .gitolite/hooks/common/
229 chmod +x .gitolite/hooks/common/*
231 gitolite setup # Upgrade if needed
235 environment.systemPackages = [ pkgs.gitolite pkgs.git ]
236 ++ lib.optional cfg.enableGitAnnex pkgs.git-annex;