{
  config,
  lib,
  pkgs,
  ...
}:
with lib;
let
  cfg = config.modules.customs.cgit;

  mkCgitrc =
    cfg:
    pkgs.writeText "cgitrc" (
      let
        cgitConfig = {
          css = "/cgit.css";
          logo = "/cgit.png";
          favicon = "/favicon.ico";
          about-filter = "${cfg.package}/lib/cgit/filters/about-formatting.sh";
          source-filter = "${cfg.package}/lib/cgit/filters/syntax-highlighting.py";
          enable-git-config = 1;
          enable-http-clone = 1;
          remove-suffix = 1;
          clone-url = "https://${cfg.url}/$CGIT_REPO_URL";
          scan-path = cfg.scanPath;
        };
      in
      generators.toKeyValue { } (cfg.settings // cgitConfig)
    );

  mkCgitAssets =
    pkg: files:
    strings.concatStringsSep "\n" (
      builtins.map (f: ''
        handle_path /${f} {
          root * ${pkg}/cgit/${f}
          file_server
        }
      '') files
    );
in
{
  disabledModules = [ "services/networking/cgit.nix" ];

  options.modules.customs.cgit = {
    enable = mkEnableOption "cgit";
    package = mkPackageOption pkgs "cgit" { };
    user = mkOption {
      default = "git";
      type = types.str;
    };
    group = mkOption {
      default = "git";
      type = types.str;
    };
    scanPath = mkOption {
      default = "/var/lib/cgit";
      type = types.path;
    };
    url = mkOption {
      default = null;
      type = types.str;
    };
    authorizedKeys = mkOption {
      default = [ ];
      type = types.listOf types.str;
    };
    settings = mkOption {
      default = { };
      type =
        with types;
        let
          settingType = oneOf [
            bool
            int
            str
          ];
        in
        attrsOf (oneOf [
          settingType
          (listOf settingType)
        ]);
    };
  };

  config = mkIf cfg.enable {
    programs.git = {
      enable = true;
      config.init.defaultBranch = "main";
    };

    # Setup git user with git-shell for authenticated pushes.
    users.users.${cfg.user} = {
      isSystemUser = true;
      home = cfg.scanPath;
      group = cfg.group;
      shell = "${pkgs.git}/bin/git-shell";
      openssh.authorizedKeys.keys = cfg.authorizedKeys;
    };

    users.groups.${cfg.group} = { };

    # Harden git user to prevent SSH port forwarding to other servers.
    services.openssh = {
      enable = true;
      openFirewall = true;
      startWhenNeeded = true;
      settings = {
        AllowUsers = [ cfg.user ];
        PermitRootLogin = "no";
        PasswordAuthentication = false;
      };
      extraConfig = ''
        Match user ${cfg.user}
          AllowTCPForwarding no
          AllowAgentForwarding no
          PermitTTY no
          X11Forwarding no
      '';
    };

    # Configure fcgiwrap instance for caddy to properly serve cgi scripts.
    # Reference: https://github.com/NixOS/nixpkgs/blob/nixos-24.11/nixos/modules/services/networking/cgit.nix
    services.fcgiwrap.instances.cgit = {
      process = { inherit (cfg) user group; };
      socket = { inherit (config.services.caddy) user group; };
    };

    networking.firewall.allowedTCPPorts = mkIf (cfg.url != null) [
      80
      443
    ];

    services.caddy = mkIf (cfg.url != null) {
      enable = true;
      virtualHosts = {
        ${cfg.url}.extraConfig =
          let
            socket = config.services.fcgiwrap.instances.cgit.socket.address;
          in
          ''
            encode zstd gzip

            reverse_proxy unix/${socket} {
              transport fastcgi {
                env SCRIPT_FILENAME ${cfg.package}/cgit/cgit.cgi
                env CGIT_CONFIG ${mkCgitrc cfg}
              }
            }

            ${mkCgitAssets cfg.package [
              "cgit.css"
              "cgit.png"
              "favicon.ico"
              "robots.txt"
            ]}
          '';
      };
    };
  };
}