From cc9ceb02550a62136e12ce9381f139388aa825c0 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 7 May 2025 22:17:49 +0200 Subject: [PATCH] fixup! WIP: enable gickup on bicep --- hosts/bicep/services/git-mirrors/default.nix | 94 ++++---- modules/gickup.nix | 224 ++++++++++++++++--- 2 files changed, 253 insertions(+), 65 deletions(-) diff --git a/hosts/bicep/services/git-mirrors/default.nix b/hosts/bicep/services/git-mirrors/default.nix index 4efabd9..4ab5fe2 100644 --- a/hosts/bicep/services/git-mirrors/default.nix +++ b/hosts/bicep/services/git-mirrors/default.nix @@ -3,47 +3,61 @@ services.gickup = { enable = true; - settings = { - source = { - github = [{ - # token_file = sops - include = [ - "go-gitea/gitea" - "unmojang/FjordLauncher" - "unmojang/drasl" - "NixOS/nixpkgs" - "saltstack/salt" - "heimdal/heimdal" - "yushijinhun/authlib-injector" - "Git-Mediawiki/Git-Mediawiki" - ]; - wiki = true; - issues = true; - }]; - gitlab = [{ - include = [ - "mx-puppet/discord/better-discord.js" - "mx-puppet/discord/matrix-discord-parser" - "mx-puppet/discord/discord-markdown" - "mx-puppet/discord/mx-puppet-discord" - "mx-puppet/mx-puppet-bridge" - ]; - }]; - any = [ - { - url = "https://sourceware.org/git/glibc.git"; - } - ]; - }; + destinationSettings = { + structured = true; + zip = false; + keep = 10; + bare = true; + lfs = true; + }; - destination.local = [{ - path = "/data/git-mirrors"; - structured = true; - zip = true; - keep = 5; - bare = true; - lfs = true; - }]; + instances = let + defaultGithubConfig = { + # settings.token_file = ... + }; + defaultGitlabConfig = { + # settings.token_file = ... + }; + in { + "github:go-gitea/gitea" = defaultGithubConfig; + "github:unmojang/FjordLauncher" = defaultGithubConfig; + "github:unmojang/drasl" = defaultGithubConfig; + "github:NixOS/nixpkgs" = defaultGithubConfig; + "github:saltstack/salt" = defaultGithubConfig; + "github:heimdal/heimdal" = defaultGithubConfig; + "github:yushijinhun/authlib-injector" = defaultGithubConfig; + "github:Git-Mediawiki/Git-Mediawiki" = defaultGithubConfig; + + "gitlab:mx-puppet/discord/better-discord.js" = defaultGitlabConfig; + "gitlab:mx-puppet/discord/matrix-discord-parser" = defaultGitlabConfig; + "gitlab:mx-puppet/discord/discord-markdown" = defaultGitlabConfig; + "gitlab:mx-puppet/discord/mx-puppet-discord" = defaultGitlabConfig; + "gitlab:mx-puppet/mx-puppet-bridge" = defaultGitlabConfig; + + "any:glibc" = { + settings.url = "https://sourceware.org/git/glibc.git"; + }; + }; + }; + + services.cgit = let + domain = "mirrors.pvv.ntnu.no"; + in { + ${domain} = { + enable = true; + group = "gickup"; + scanPath = "/var/lib/gickup"; + settings = { + enable-commit-graph = true; + enable-follow-links = true; + enable-http-clone = true; + enable-remote-branches = true; + clone-url = "https://${domain}/$CGIT_REPO_URL"; + remove-suffix = true; + root-title = "https://${domain}"; + root-desc = "PVV's repository mirroring service"; + snapshots = "all"; + }; }; }; } diff --git a/modules/gickup.nix b/modules/gickup.nix index 4834fc8..5b88d1c 100644 --- a/modules/gickup.nix +++ b/modules/gickup.nix @@ -1,4 +1,4 @@ -{ config, pkgs, lib, ... }: +{ config, pkgs, lib, utils, ... }: let cfg = config.services.gickup; format = pkgs.formats.yaml { }; @@ -6,30 +6,194 @@ in { options.services.gickup = { enable = lib.mkEnableOption "gickup, a git repository mirroring service"; - package = lib.mkPackageOption pkgs "gickup" { }; + package = lib.mkPackageOption pkgs "gickup" { }; gitPackage = lib.mkPackageOption pkgs "git" { }; gitLfsPackage = lib.mkPackageOption pkgs "git-lfs" { }; - settings = lib.mkOption { + destinationSettings = lib.mkOption { + description = '' + Settings for destination local, see gickup configuration file + + Note that `path` will be set automatically to `/var/lib/gickup` + ''; type = lib.types.submodule { freeformType = format.type; }; + default = { }; + example = { + structured = true; + zip = false; + keep = 10; + bare = true; + lfs = true; + }; + }; + + instances = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule (submoduleInputs@{ name, ... }: let + submoduleName = name; + + nameParts = rec { + repoType = builtins.head (lib.splitString ":" submoduleName); + + owner = if repoType == "any" + then null + else lib.pipe submoduleName [ + (lib.removePrefix "${repoType}:") + (lib.splitString "/") + builtins.head + lib.toLower + ]; + + repo = if repoType == "any" + then null + else lib.pipe submoduleName [ + (lib.removePrefix "${repoType}:") + (lib.splitString "/") + lib.last + lib.toLower + ]; + + slug = if repoType == "any" + then builtins.replaceStrings [ ":" "/" ] [ "-" "-" ] submoduleName + else "${repoType}-${owner}-${repo}"; + }; + in { + options = { + interval = lib.mkOption { + type = lib.types.str; + default = "daily"; + example = "weekly"; + description = '' + Specification (in the format described by {manpage}`systemd.time(7)`) of the time + interval at which to run the service. + ''; + }; + + type = lib.mkOption { + type = lib.types.enum [ + "github" + "gitlab" + "gitea" + "gogs" + "bitbucket" + "onedev" + "sourcehut" + "any" + ]; + example = "github"; + default = nameParts.repoType; + description = '' + The type of the repository to mirror. + ''; + }; + + owner = lib.mkOption { + type = with lib.types; nullOr str; + example = "go-gitea"; + default = nameParts.owner; + description = '' + The owner of the repository to mirror (if applicable) + ''; + }; + + repo = lib.mkOption { + type = with lib.types; nullOr str; + example = "gitea"; + default = nameParts.repo; + description = '' + The name of the repository to mirror (if applicable) + ''; + }; + + slug = lib.mkOption { + type = lib.types.str; + default = nameParts.slug; + example = "github-go-gitea-gitea"; + description = '' + The slug of the repository to mirror. + ''; + }; + + settings = lib.mkOption { + description = "Instance specific settings, see gickup configuration file"; + type = lib.types.submodule { + freeformType = format.type; + }; + default = { }; + example = { + username = "gickup"; + password = "hunter2"; + wiki = true; + issues = true; + }; + }; + }; + })); }; }; config = lib.mkIf cfg.enable { - users.users.gickup = { - isSystemUser = true; - group = "gickup"; - home = "/var/lib/gickup"; + services.gickup.destinationSettings.path = "/var/lib/gickup"; + + systemd.slices."system-gickup" = { + description = "Gickup git repository mirroring service"; + after = [ "network.target" ]; }; - users.groups.gickup = { }; - - systemd.services.gickup = { + systemd.targets.gickup = { description = "Gickup git repository mirroring service"; - wantedBy = [ "multi-user.target" ]; + wants = map ({ slug, ... }: "gickup@${slug}.service") (lib.attrValues cfg.instances); + }; + + systemd.timers = { + "gickup@" = { + description = "Gickup git repository mirroring service for %i"; + + timerConfig = { + OnCalendar = "daily"; + RandomizedDelaySec = "1h"; + Persistent = true; + AccuracySec = "1s"; + }; + }; + } + // + # Overrides for mirrors which are not "daily" + (lib.pipe cfg.instances [ + builtins.attrValues + (builtins.filter (instance: instance.interval != "daily")) + (map ({ slug, interval, ... }: { + name = "gickup@${slug}"; + value = { + overrideStrategy = "asDropin"; + timerConfig.OnCalendar = interval; + }; + })) + builtins.listToAttrs + ]); + + systemd.targets.timers.wants = map ({ slug, ... }: "gickup@${slug}.timer") (lib.attrValues cfg.instances); + + systemd.services."gickup@" = let + configDir = lib.pipe cfg.instances [ + (lib.mapAttrsToList (name: instance: { + name = "${instance.slug}.yml"; + path = format.generate "gickup-configuration-${name}.yml" { + destination.local = [ cfg.destinationSettings ]; + source.${instance.type} = [ + ({ + includeorgs = [ instance.owner ]; + include = [ instance.repo ]; + } // instance.settings) + ]; + }; + })) + (pkgs.linkFarm "gickup-configuration-files") + ]; + in { + description = "Gickup git repository mirroring service for %i"; after = [ "network.target" ]; path = [ @@ -38,15 +202,17 @@ in ]; serviceConfig = { - ExecStart = utils.escapeSystemdExecArgs [ - (lib.getExe cfg.package) - (format.generate "gickup-settings.conf" cfg.settings) - ]; + Slice = "system-gickup.slice"; + ExecStart = "'${pkgs.gickup}/bin/gickup' '${configDir}/%i.yml' --debug"; + User = "gickup"; + Group = "gickup"; + + SyslogIdentifier = "gickup-%i"; StateDirectory = "gickup"; - WorkingDirectory = "gickup"; - RuntimeDirectory = "gickup"; - RuntimeDirectoryMode = "0700"; + # WorkingDirectory = "gickup"; + # RuntimeDirectory = "gickup"; + # RuntimeDirectoryMode = "0700"; # Hardening options AmbientCapabilities = []; @@ -64,8 +230,8 @@ in ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; - ProtectProc = "invisible"; - ProtectSystem = "strict"; + # ProtectProc = "invisible"; + # ProtectSystem = "strict"; RemoveIPC = true; RestrictAddressFamilies = [ "AF_INET" @@ -75,14 +241,22 @@ in RestrictRealtime = true; RestrictSUIDSGID = true; SystemCallArchitectures = "native"; - SystemCallFilter = [ - "@system-service" - "~@resources" - "~@privileged" - ]; + # SystemCallFilter = [ + # "@system-service" + # "~@resources" + # "~@privileged" + # ]; UMask = "0002"; CapabilityBoundingSet = []; }; }; + + users.users.gickup = { + isSystemUser = true; + group = "gickup"; + home = "/var/lib/gickup"; + }; + + users.groups.gickup = { }; }; }