{ config, lib, pkgs, ... }: let inherit (lib) mkEnableOption mkIf mkOption ; cfg = config.my.services.forgejo; my = config.my; domain = config.networking.domain; hostname = config.networking.hostName; fqdn = "${hostname}.${domain}"; forgejoUser = "git"; in { options.my.services.forgejo = let inherit (lib) types; in { enable = mkEnableOption "Personal Git hosting with Forgejo"; privatePort = mkOption { type = types.port; default = 8082; example = 8082; description = "Port to serve the app"; }; }; config = mkIf cfg.enable { # use git as user to have `git clone git@git.domain` users.users.${forgejoUser} = { description = "Forgejo Service"; home = config.services.forgejo.stateDir; useDefaultShell = true; group = forgejoUser; # the systemd service for the forgejo module seems to hardcode the group as # forgejo, so, uh, just in case? extraGroups = ["forgejo"]; isSystemUser = true; }; users.groups.${forgejoUser} = {}; services.forgejo = { enable = true; user = forgejoUser; group = config.users.users.${forgejoUser}.group; stateDir = "/var/lib/${forgejoUser}"; lfs.enable = true; settings = { server = { ROOT_URL = "https://git.${domain}/"; DOMAIN = "git.${domain}"; HTTP_ADDR = "127.0.0.1"; HTTP_PORT = cfg.privatePort; }; log.LEVEL = "Warn"; # [ "Trace" "Debug" "Info" "Warn" "Error" "Critical" ] repository = { ENABLE_PUSH_CREATE_USER = true; DEFAULT_BRANCH = "main"; }; # NOTE: temporarily remove this for initial setup service.DISABLE_REGISTRATION = true; # only send cookies via HTTPS session.COOKIE_SECURE = true; DEFAULT.APP_NAME = "Personal Forge"; }; # NixOS module uses `forgejo dump` to backup repositories and the database, # but it produces a single .zip file that's not very restic friendly. # I configure my backup system manually below. dump.enable = false; database = { type = "postgres"; # user needs to be the same as forgejo user user = forgejoUser; name = forgejoUser; }; }; # FIXME: Borg *could* be backing up files while they're being edited by # forgejo, so it may produce corrupt files in the snapshot if I push stuff # around midnight. I'm not sure how `forgejo dump` handles this either, # though. my.services.restic-backup = { paths = [ config.services.forgejo.lfs.contentDir config.services.forgejo.repositoryRoot ]; }; # NOTE: no need to use postgresql.ensureDatabases because the forgejo module # takes care of this automatically services.postgresqlBackup = { databases = [config.services.forgejo.database.name]; }; services.nginx = { virtualHosts = { "git.${domain}" = { forceSSL = true; useACMEHost = fqdn; locations."/" = { proxyPass = "http://127.0.0.1:${toString cfg.privatePort}"; }; }; }; }; security.acme.certs.${fqdn}.extraDomainNames = ["git.${domain}"]; systemd.services.forgejo.preStart = "${pkgs.coreutils}/bin/ln -sfT ${./templates} ${config.services.forgejo.stateDir}/custom/templates"; }; }