{
  lib,
  config,
  pkgs,
  ...
}: let
  forgejoPort = 8081;
  stateDir = "/var/lib/forgejo";
  db_user = "forgejo";
  sshPort = 22222;
in {
  options.services.forgejo = {
    subdomain = lib.mkOption {
      type = lib.types.str;
      description = "subdomain of base domain that forgejo will be hosted at";
      default = "forgejo";
    };
  };

  config = lib.mkIf config.services.forgejo.enable (lib.mkMerge [
    {
      host = {
        reverse_proxy.subdomains.${config.services.forgejo.subdomain} = {
          target = "http://localhost:${toString forgejoPort}";
        };
        postgres = {
          enable = true;
          extraUsers = {
            ${db_user} = {
              isClient = true;
            };
          };
        };
      };

      services.forgejo = {
        database = {
          type = "postgres";
          socket = "/run/postgresql";
        };
        lfs.enable = true;
        settings = {
          server = {
            DOMAIN = "${config.services.forgejo.subdomain}.${config.host.reverse_proxy.hostname}";
            HTTP_PORT = forgejoPort;
            START_SSH_SERVER = true;
            SSH_LISTEN_PORT = sshPort;
            SSH_PORT = 22;
            BUILTIN_SSH_SERVER_USER = config.users.users.git.name;
            ROOT_URL = "https://git.jan-leila.com";
          };
          service = {
            DISABLE_REGISTRATION = true;
          };
          database = {
            DB_TYPE = "postgres";
            NAME = db_user;
            USER = db_user;
          };
        };
      };

      networking.firewall.allowedTCPPorts = [
        config.services.forgejo.settings.server.SSH_LISTEN_PORT
      ];
    }
    (lib.mkIf config.services.fail2ban.enable {
      environment.etc = {
        "fail2ban/filter.d/forgejo.local".text = lib.mkIf config.services.forgejo.enable (
          pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
            [Definition]
            failregex = ".*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>"
          '')
        );
      };

      services.fail2ban = {
        jails = {
          forgejo-iptables.settings = lib.mkIf config.services.forgejo.enable {
            enabled = true;
            filter = "forgejo";
            action = ''iptables-multiport[name=HTTP, port="http,https"]'';
            logpath = "${config.services.forgejo.settings.log.ROOT_PATH}/*.log";
            backend = "auto";
            findtime = 600;
            bantime = 600;
            maxretry = 5;
          };
        };
      };
    })
    (lib.mkIf config.host.impermanence.enable {
      assertions = [
        {
          assertion = config.services.forgejo.stateDir == stateDir;
          message = "forgejo state directory does not match persistence";
        }
      ];
      environment.persistence."/persist/system/root" = {
        enable = true;
        hideMounts = true;
        directories = [
          {
            directory = stateDir;
            user = "forgejo";
            group = "forgejo";
          }
        ];
      };
    })
  ]);
}