diff options
Diffstat (limited to 'modules/server/git-http-backend/default.nix')
-rw-r--r-- | modules/server/git-http-backend/default.nix | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/modules/server/git-http-backend/default.nix b/modules/server/git-http-backend/default.nix new file mode 100644 index 000000000000..32e20e603e61 --- /dev/null +++ b/modules/server/git-http-backend/default.nix @@ -0,0 +1,106 @@ +{ lib, pkgs, config, ... }: + +let + inherit (builtins) split; + inherit (lib) flip foldr groupBy head literalExpression mapAttrs mapAttrs' + mapAttrsToList mdDoc mkOption nameValuePair optionalAttrs types; + + cfg = config.services.git-http-backend; + + instancesByVhost = groupBy ({ value, ... }: value.vhost) + (mapAttrsToList nameValuePair cfg.instances); + + vhostConfigs = mapAttrs (vhost: instances: + foldr (l: r: l // r) {} (map ({ name, value }: let + path = head (split "/+$" value.path); + pathRegex = + "^${path}/.*?(\.git)?/(HEAD|info/refs|git-(upload|receive)-pack)$"; + in { + locations = { + "~ ${pathRegex}" = { + proxyPass = "http://unix:/run/cgiserver/git-http-backend/${name}.sock"; + + extraConfig = '' + client_max_body_size 0; + proxy_read_timeout 3600; + proxy_send_timeout 3600; + ''; + }; + }; + }) instances) + ) instancesByVhost; +in + +{ + options.services.git-http-backend = { + package = mkOption { + type = types.package; + default = pkgs.gitMinimal; + description = mdDoc "git package to use"; + }; + + instances = mkOption { + type = types.attrsOf (types.submodule { + options = { + vhost = mkOption { + type = types.str; + example = "spectrum-os.org"; + description = mdDoc "Nginx vhost for the git server"; + }; + + path = mkOption { + type = types.strMatching "/(.*[^/])?"; + default = "/"; + example = "/git"; + description = mdDoc '' + Path to be prepended to all clone URLs. + + Leading slashes are mandatory; trailing slashes are forbidden. + ''; + }; + + cgiserver = mkOption { + type = types.package; + default = pkgs.cgiserver; + defaultText = literalExpression "pkgs.cgiserver"; + description = mdDoc "cgiserver package to use"; + }; + + projectRoot = mkOption { + type = types.strMatching "/(.*[^/])?"; + example = "/var/www/git"; + description = mdDoc '' + Directory in which to look for git repositories. + + Leading slashes are mandatory; trailing slashes are forbidden. + ''; + }; + }; + }); + default = {}; + description = mdDoc "List of git-http-backend instances to run"; + }; + }; + + config = { + services.nginx.virtualHosts = vhostConfigs; + + systemd.services = flip mapAttrs' cfg.instances (name: instance: { + name = "git-http-backend-${name}"; + value = { + environment.GIT_HTTP_EXPORT_ALL = ""; + environment.GIT_PROJECT_ROOT = instance.projectRoot; + serviceConfig.DynamicUser = true; + serviceConfig.ExecStart = "${instance.cgiserver}/bin/cgiserver -r ${instance.path} ${cfg.package}/bin/git-http-backend"; + }; + }); + + systemd.sockets = flip mapAttrs' cfg.instances (name: instance: { + name = "git-http-backend-${name}"; + value = { + wantedBy = [ "sockets.target" ]; + socketConfig.ListenStream = "/run/cgiserver/git-http-backend/${name}.sock"; + }; + }); + }; +} |