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