From 82a977a61697b8021234ad2f2da0ed766cc506d6 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Tue, 5 Mar 2024 12:32:40 +0000 Subject: [PATCH] WIP: Forgejo --- .../porthos/secrets/forgejo/mail-password.age | 10 ++ hosts/nixos/porthos/secrets/secrets.nix | 5 + hosts/nixos/porthos/services.nix | 8 +- modules/nixos/services/default.nix | 1 + modules/nixos/services/forgejo/default.nix | 160 ++++++++++++++++++ 5 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 hosts/nixos/porthos/secrets/forgejo/mail-password.age create mode 100644 modules/nixos/services/forgejo/default.nix diff --git a/hosts/nixos/porthos/secrets/forgejo/mail-password.age b/hosts/nixos/porthos/secrets/forgejo/mail-password.age new file mode 100644 index 0000000..67ef695 --- /dev/null +++ b/hosts/nixos/porthos/secrets/forgejo/mail-password.age @@ -0,0 +1,10 @@ +age-encryption.org/v1 +-> ssh-ed25519 cKojmg Lhgx43wR8PtAMf5v1eJxKlUBSAoOLdOOn/QaQrwF8zA +jfUCpgNzkHCNTWCqtErDaLMmg1Oy+s9zUra1JLCi+J4 +-> ssh-ed25519 jPowng kSeQ/SmMrzd8ByVu3YHWeZyKmqFZvQSBnDunkB8e6wc +WRmnfrV5xcRXA9t0ZXx6YvbRl0sX4PTrw63VVKX4Ei4 +--- a+LLM1gP9g1AbUapbeeKaS4cEcRBmPo3MHU2DSWTAds +,F6⬘ ix̏e| + +Ϝ,{ v!z$P;TKW + qG \ No newline at end of file diff --git a/hosts/nixos/porthos/secrets/secrets.nix b/hosts/nixos/porthos/secrets/secrets.nix index 3545e3a..bea380c 100644 --- a/hosts/nixos/porthos/secrets/secrets.nix +++ b/hosts/nixos/porthos/secrets/secrets.nix @@ -21,6 +21,11 @@ in "drone/secret.age".publicKeys = all; "drone/ssh/private-key.age".publicKeys = all; + "forgejo/mail-password.age" = { + owner = "git"; + publicKeys = all; + }; + "gitea/mail-password.age" = { owner = "git"; publicKeys = all; diff --git a/hosts/nixos/porthos/services.nix b/hosts/nixos/porthos/services.nix index c872160..a67ae3b 100644 --- a/hosts/nixos/porthos/services.nix +++ b/hosts/nixos/porthos/services.nix @@ -36,14 +36,14 @@ in flood = { enable = true; }; - # Gitea forge - gitea = { + # Forgejo forge + forgejo = { enable = true; mail = { enable = true; host = "smtp.migadu.com"; - user = lib.my.mkMailAddress "gitea" "belanyi.fr"; - passwordFile = secrets."gitea/mail-password".path; + user = lib.my.mkMailAddress "forgejo" "belanyi.fr"; + passwordFile = secrets."forgejo/mail-password".path; }; }; # Meta-indexers diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix index 90dd3e1..3b32d06 100644 --- a/modules/nixos/services/default.nix +++ b/modules/nixos/services/default.nix @@ -10,6 +10,7 @@ ./drone ./fail2ban ./flood + ./forgejo ./gitea ./grocy ./indexers diff --git a/modules/nixos/services/forgejo/default.nix b/modules/nixos/services/forgejo/default.nix new file mode 100644 index 0000000..69c5059 --- /dev/null +++ b/modules/nixos/services/forgejo/default.nix @@ -0,0 +1,160 @@ +# A low-ressource, full-featured git forge. +{ config, lib, ... }: +let + cfg = config.my.services.forgejo; +in +{ + options.my.services.forgejo = with lib; { + enable = mkEnableOption "Forgejo"; + port = mkOption { + type = types.port; + default = 3042; + example = 8080; + description = "Internal port"; + }; + mail = { + enable = mkEnableOption { + description = "mailer configuration"; + }; + host = mkOption { + type = types.str; + example = "smtp.example.com"; + description = "Host for the mail account"; + }; + port = mkOption { + type = types.port; + default = 465; + example = 587; + description = "Port for the mail account"; + }; + user = mkOption { + type = types.str; + example = "forgejo@example.com"; + description = "User for the mail account"; + }; + passwordFile = mkOption { + type = types.str; + example = "/run/secrets/forgejo-mail-password.txt"; + description = "Password for the mail account"; + }; + protocol = mkOption { + type = types.str; + default = "smtps"; + example = "smtp"; + description = "Protocol for connection"; + }; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = cfg.enable -> !config.my.services.gitea.enable; + message = '' + `config.my.services.forgejo` is incompatible with + `config.my.services.gitea`. + ''; + } + ]; + + services.forgejo = + let + inherit (config.networking) domain; + forgejoDomain = "git.${domain}"; + in + { + enable = true; + + appName = "Ambroisie's forge"; + + user = "git"; + group = "git"; + + lfs.enable = true; + + useWizard = false; + + database = { + type = "postgres"; # Automatic setup + user = "git"; # User needs to be the same as forgejo user + name = "git"; # Name must be the same as user for `ensureDBOwnership` + }; + + # NixOS module uses `forgejo dump` to backup repositories and the database, + # but it produces a single .zip file that's not very backup friendly. + # I configure my backup system manually below. + dump.enable = false; + + mailerPasswordFile = lib.mkIf cfg.mail.enable cfg.mail.passwordFile; + + settings = { + server = { + HTTP_PORT = cfg.port; + DOMAIN = forgejoDomain; + ROOT_URL = "https://${forgejoDomain}"; + }; + + mailer = lib.mkIf cfg.mail.enable { + ENABLED = true; + SMTP_ADDR = cfg.mail.host; + SMTP_PORT = cfg.mail.port; + FROM = "Forgejo <${cfg.mail.user}>"; + USER = cfg.mail.user; + PROTOCOL = cfg.mail.protocol; + }; + + service = { + DISABLE_REGISTRATION = true; + }; + + session = { + # only send cookies via HTTPS + COOKIE_SECURE = true; + }; + }; + }; + + users.users.git = { + description = "Forgejo Service"; + home = config.services.forgejo.stateDir; + useDefaultShell = true; + group = "git"; + isSystemUser = true; + }; + users.groups.git = { }; + + my.services.nginx.virtualHosts = { + # Proxy to Forgejo + git = { + inherit (cfg) port; + }; + # Redirect `forgejo.` to actual forge subdomain + forgejo = { + redirect = config.services.forgejo.settings.server.ROOT_URL; + }; + }; + + my.services.backup = { + paths = [ + config.services.forgejo.lfs.contentDir + config.services.forgejo.repositoryRoot + ]; + }; + + services.fail2ban.jails = { + forgejo = '' + enabled = true + filter = forgejo + action = iptables-allports + ''; + }; + + environment.etc = { + "fail2ban/filter.d/forgejo.conf".text = '' + [Definition] + failregex = ^.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from $ + journalmatch = _SYSTEMD_UNIT=forgejo.service + ''; + }; + }; +}