aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules/services/misc/gitolite.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/misc/gitolite.nix')
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitolite.nix231
1 files changed, 231 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/misc/gitolite.nix b/nixpkgs/nixos/modules/services/misc/gitolite.nix
new file mode 100644
index 00000000000..cc69f81bbcc
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/gitolite.nix
@@ -0,0 +1,231 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.gitolite;
+ # Use writeTextDir to not leak Nix store hash into file name
+ pubkeyFile = (pkgs.writeTextDir "gitolite-admin.pub" cfg.adminPubkey) + "/gitolite-admin.pub";
+ hooks = lib.concatMapStrings (hook: "${hook} ") cfg.commonHooks;
+in
+{
+ options = {
+ services.gitolite = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Enable gitolite management under the
+ <literal>gitolite</literal> user. After
+ switching to a configuration with Gitolite enabled, you can
+ then run <literal>git clone
+ gitolite@host:gitolite-admin.git</literal> to manage it further.
+ '';
+ };
+
+ dataDir = mkOption {
+ type = types.str;
+ default = "/var/lib/gitolite";
+ description = ''
+ Gitolite home directory (used to store all the repositories).
+ '';
+ };
+
+ adminPubkey = mkOption {
+ type = types.str;
+ description = ''
+ Initial administrative public key for Gitolite. This should
+ be an SSH Public Key. Note that this key will only be used
+ once, upon the first initialization of the Gitolite user.
+ The key string cannot have any line breaks in it.
+ '';
+ };
+
+ enableGitAnnex = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Enable git-annex support. Uses the <literal>extraGitoliteRc</literal> option
+ to apply the necessary configuration.
+ '';
+ };
+
+ commonHooks = mkOption {
+ type = types.listOf types.path;
+ default = [];
+ description = ''
+ A list of custom git hooks that get copied to <literal>~/.gitolite/hooks/common</literal>.
+ '';
+ };
+
+ extraGitoliteRc = mkOption {
+ type = types.lines;
+ default = "";
+ example = literalExample ''
+ $RC{UMASK} = 0027;
+ $RC{SITE_INFO} = 'This is our private repository host';
+ push( @{$RC{ENABLE}}, 'Kindergarten' ); # enable the command/feature
+ @{$RC{ENABLE}} = grep { $_ ne 'desc' } @{$RC{ENABLE}}; # disable the command/feature
+ '';
+ description = ''
+ Extra configuration to append to the default <literal>~/.gitolite.rc</literal>.
+
+ This should be Perl code that modifies the <literal>%RC</literal>
+ configuration variable. The default <literal>~/.gitolite.rc</literal>
+ content is generated by invoking <literal>gitolite print-default-rc</literal>,
+ and extra configuration from this option is appended to it. The result
+ is placed to Nix store, and the <literal>~/.gitolite.rc</literal> file
+ becomes a symlink to it.
+
+ If you already have a customized (or otherwise changed)
+ <literal>~/.gitolite.rc</literal> file, NixOS will refuse to replace
+ it with a symlink, and the `gitolite-init` initialization service
+ will fail. In this situation, in order to use this option, you
+ will need to take any customizations you may have in
+ <literal>~/.gitolite.rc</literal>, convert them to appropriate Perl
+ statements, add them to this option, and remove the file.
+
+ See also the <literal>enableGitAnnex</literal> option.
+ '';
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "gitolite";
+ description = ''
+ Gitolite user account. This is the username of the gitolite endpoint.
+ '';
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = "gitolite";
+ description = ''
+ Primary group of the Gitolite user account.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable (
+ let
+ manageGitoliteRc = cfg.extraGitoliteRc != "";
+ rcDir = pkgs.runCommand "gitolite-rc" { preferLocalBuild = true; } rcDirScript;
+ rcDirScript =
+ ''
+ mkdir "$out"
+ export HOME=temp-home
+ mkdir -p "$HOME/.gitolite/logs" # gitolite can't run without it
+ '${pkgs.gitolite}'/bin/gitolite print-default-rc >>"$out/gitolite.rc.default"
+ cat <<END >>"$out/gitolite.rc"
+ # This file is managed by NixOS.
+ # Use services.gitolite options to control it.
+
+ END
+ cat "$out/gitolite.rc.default" >>"$out/gitolite.rc"
+ '' +
+ optionalString (cfg.extraGitoliteRc != "") ''
+ echo -n ${escapeShellArg ''
+
+ # Added by NixOS:
+ ${removeSuffix "\n" cfg.extraGitoliteRc}
+
+ # per perl rules, this should be the last line in such a file:
+ 1;
+ ''} >>"$out/gitolite.rc"
+ '';
+ in {
+ services.gitolite.extraGitoliteRc = optionalString cfg.enableGitAnnex ''
+ # Enable git-annex support:
+ push( @{$RC{ENABLE}}, 'git-annex-shell ua');
+ '';
+
+ users.users.${cfg.user} = {
+ description = "Gitolite user";
+ home = cfg.dataDir;
+ uid = config.ids.uids.gitolite;
+ group = cfg.group;
+ useDefaultShell = true;
+ };
+ users.groups.${cfg.group}.gid = config.ids.gids.gitolite;
+
+ systemd.tmpfiles.rules = [
+ "d '${cfg.dataDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.dataDir}'/.gitolite - ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.dataDir}'/.gitolite/logs - ${cfg.user} ${cfg.group} - -"
+
+ "Z ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -"
+ ];
+
+ systemd.services.gitolite-init = {
+ description = "Gitolite initialization";
+ wantedBy = [ "multi-user.target" ];
+ unitConfig.RequiresMountsFor = cfg.dataDir;
+
+ environment = {
+ GITOLITE_RC = ".gitolite.rc";
+ GITOLITE_RC_DEFAULT = "${rcDir}/gitolite.rc.default";
+ };
+
+ serviceConfig = {
+ Type = "oneshot";
+ User = cfg.user;
+ Group = cfg.group;
+ WorkingDirectory = "~";
+ RemainAfterExit = true;
+ };
+
+ path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ];
+ script =
+ let
+ rcSetupScriptIfCustomFile =
+ if manageGitoliteRc then ''
+ cat <<END
+ <3>ERROR: NixOS can't apply declarative configuration
+ <3>to your .gitolite.rc file, because it seems to be
+ <3>already customized manually.
+ <3>See the services.gitolite.extraGitoliteRc option
+ <3>in "man configuration.nix" for more information.
+ END
+ # Not sure if the line below addresses the issue directly or just
+ # adds a delay, but without it our error message often doesn't
+ # show up in `systemctl status gitolite-init`.
+ journalctl --flush
+ exit 1
+ '' else ''
+ :
+ '';
+ rcSetupScriptIfDefaultFileOrStoreSymlink =
+ if manageGitoliteRc then ''
+ ln -sf "${rcDir}/gitolite.rc" "$GITOLITE_RC"
+ '' else ''
+ [[ -L "$GITOLITE_RC" ]] && rm -f "$GITOLITE_RC"
+ '';
+ in
+ ''
+ if ( [[ ! -e "$GITOLITE_RC" ]] && [[ ! -L "$GITOLITE_RC" ]] ) ||
+ ( [[ -f "$GITOLITE_RC" ]] && diff -q "$GITOLITE_RC" "$GITOLITE_RC_DEFAULT" >/dev/null ) ||
+ ( [[ -L "$GITOLITE_RC" ]] && [[ "$(readlink "$GITOLITE_RC")" =~ ^/nix/store/ ]] )
+ then
+ '' + rcSetupScriptIfDefaultFileOrStoreSymlink +
+ ''
+ else
+ '' + rcSetupScriptIfCustomFile +
+ ''
+ fi
+
+ if [ ! -d repositories ]; then
+ gitolite setup -pk ${pubkeyFile}
+ fi
+ if [ -n "${hooks}" ]; then
+ cp -f ${hooks} .gitolite/hooks/common/
+ chmod +x .gitolite/hooks/common/*
+ fi
+ gitolite setup # Upgrade if needed
+ '';
+ };
+
+ environment.systemPackages = [ pkgs.gitolite pkgs.git ]
+ ++ optional cfg.enableGitAnnex pkgs.gitAndTools.git-annex;
+ });
+}