/** cgit module taken from git.qyliss.net/nixlib */ { lib, pkgs, config, ... }: let inherit (builtins) split; inherit (lib) foldr groupBy head mapAttrs mapAttrsToList mkOption nameValuePair optionalAttrs types; cfg = config.services.cgit; instancesByVhost = groupBy ({ value, ... }: value.vhost) (mapAttrsToList nameValuePair cfg.instances); vhostConfigs = mapAttrs (vhost: instances: foldr (l: r: l // r) {} (map ({ name, value }: let unslashedPath = head (split "/+$" value.path); # We'll be dealing almost exclusively with paths ending in /, # since otherwise Nginx likes to do simple prefix matching. path = "${unslashedPath}/"; in { locations = { ${path} = { alias = "${value.package}/cgit/"; tryFiles = "$uri @${name}-cgit"; }; "@${name}-cgit" = { root = "${value.package}/cgit"; fastcgiParams.CGIT_CONFIG = "${value.config}"; fastcgiParams.SCRIPT_FILENAME = "$document_root/cgit.cgi"; fastcgiParams.PATH_INFO = "$fastcgi_path_info"; fastcgiParams.QUERY_STRING = "$args"; fastcgiParams.HTTP_HOST = "$server_name"; extraConfig = '' fastcgi_split_path_info ^(${path})(.*)$; fastcgi_pass unix:/run/fcgiwrap.sock; ''; }; } // optionalAttrs (unslashedPath != "") { ${unslashedPath} = { return = "301 ${path}"; }; }; }) instances) ) instancesByVhost; in { options.services.cgit = { instances = mkOption { type = types.attrsOf (types.submodule { options = { vhost = mkOption { type = types.str; example = "spectrum-os.org"; description = "Nginx vhost for the cgit"; }; path = mkOption { type = types.strMatching "/(.*[^/])?"; default = "/"; example = "/git"; description = '' Path to be appended to all cgit URLs. Leading slashes are mandatory; trailing slashes are forbidden. ''; }; package = mkOption { type = types.package; default = pkgs.cgit; description = "cgit package to use"; }; config = mkOption { type = types.package; description = '' Configuration file for cgit. See <citerefentry><refentrytitle>cgitrc</refentrytitle> <manvolnum>5</manvolnum></citerefentry>. ''; }; }; }); default = {}; description = "List of cgit instances to run"; }; }; config = { services.fcgiwrap = optionalAttrs (cfg.instances != {}) { enable = true; }; services.nginx.virtualHosts = vhostConfigs; }; }