{ pkgs, config, lib, ... }: let domain = "gitea.${config.services.nginx.domain}"; in { services.gitea = { enable = true; database.type = "postgres"; appName = "Gitea: Git with a cup of tea"; 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; }; }; systemd.services.gitea.serviceConfig.ExecStartPre = let replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret"; secretPath = config.sops.secrets."gitea/metrics-token".path; runConfig = "${config.services.gitea.customDir}/conf/app.ini"; in [ "+${replaceSecretBin} '#metricstoken#' '${secretPath}' '${runConfig}'" ]; # Set up SSL services.nginx.virtualHosts."${domain}" = let httpAddress = config.services.gitea.settings.server.HTTP_ADDR; httpPort = config.services.gitea.settings.server.HTTP_PORT; in { forceSSL = true; enableACME = true; extraConfig = '' add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; access_log /var/log/nginx/${domain}/access.log upstream_time; ''; 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; ''; }; }; # Block repeated failed login attempts # # TODO(tlater): Update to the new regex, since apparently this one # is deprecated (but the new one doesn't work on the current version # of gitea yet): https://docs.gitea.io/en-us/fail2ban-setup/ environment.etc = { "fail2ban/filter.d/gitea.conf".text = '' [Definition] failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from journalmatch = _SYSTEMD_UNIT=gitea.service + _COMM=gitea + SYSLOG_IDENTIFIER=gitea ''; }; services.fail2ban.jails = { gitea = '' enabled = true ''; }; services.backups.gitea = { user = "gitea"; paths = [ "/var/lib/gitea/gitea-db.sql" "/var/lib/gitea/repositories/" "/var/lib/gitea/data/" "/var/lib/gitea/custom/" # Conf is backed up via nix ]; preparation = { packages = [config.services.postgresql.package]; text = "pg_dump ${config.services.gitea.database.name} --file=/var/lib/gitea/gitea-db.sql"; }; cleanup = { packages = [pkgs.coreutils]; text = "rm /var/lib/gitea/gitea-db.sql"; }; pauseServices = ["gitea.service"]; }; }