{
  pkgs,
  config,
  lib,
  ...
}:
let
  domain = "gitea.${config.services.nginx.domain}";
in
{
  networking.firewall.allowedTCPPorts = [
    80
    443
  ];

  services = {
    forgejo = {
      enable = true;
      database.type = "postgres";

      settings = {
        server = {
          DOMAIN = domain;
          HTTP_ADDR = "127.0.0.1";
          ROOT_URL = "https://${domain}/";
          SSH_PORT = 2222;
        };

        metrics = {
          ENABLED = true;
          TOKEN = "#metricstoken#";
        };
        service.DISABLE_REGISTRATION = true;
        session.COOKIE_SECURE = true;
      };
    };

    # Set up SSL
    nginx.virtualHosts."${domain}" =
      let
        httpAddress = config.services.forgejo.settings.server.HTTP_ADDR;
        httpPort = config.services.forgejo.settings.server.HTTP_PORT;
      in
      {
        forceSSL = true;
        useACMEHost = "tlater.net";
        enableHSTS = true;

        locations."/".proxyPass = "http://${httpAddress}:${toString httpPort}";
        locations."/metrics" = {
          extraConfig = ''
            access_log off;
            allow 127.0.0.1;
            ${lib.optionalString config.networking.enableIPv6 "allow ::1;"}
            deny all;
          '';
        };
      };

    backups.forgejo = {
      user = "forgejo";
      paths = [
        "/var/lib/forgejo/forgejo-db.sql"
        "/var/lib/forgejo/repositories/"
        "/var/lib/forgejo/data/"
        "/var/lib/forgejo/custom/"
        # Conf is backed up via nix
      ];
      preparation = {
        packages = [ config.services.postgresql.package ];
        text = "pg_dump ${config.services.forgejo.database.name} --file=/var/lib/forgejo/forgejo-db.sql";
      };
      cleanup = {
        packages = [ pkgs.coreutils ];
        text = "rm /var/lib/forgejo/forgejo-db.sql";
      };
      pauseServices = [ "forgejo.service" ];
    };
  };

  systemd.services.forgejo.serviceConfig.ExecStartPre =
    let
      replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret";
      secretPath = config.sops.secrets."forgejo/metrics-token".path;
      runConfig = "${config.services.forgejo.customDir}/conf/app.ini";
    in
    [ "+${replaceSecretBin} '#metricstoken#' '${secretPath}' '${runConfig}'" ];
}
