all repos — nixfiles @ e0ad1fb58beea7e7cb5f5047d1203ff68d39c7d5

System and user configuration, managed by nix and home-manager

system/settings/services/git-server.nix (view raw)

{
  config,
  lib,
  pkgs,
  ...
}:
let
  inherit (lib)
    pipe
    flatten
    concatMapAttrs
    mapAttrsToList
    ;
  inherit (import ../../../lib/caddy.nix { inherit lib; }) security-headers;

  domain = "alin.ovh";
  serverName = "git.${domain}";
  gitoliteCfg = config.services.gitolite;
  repos = "${gitoliteCfg.dataDir}/repositories";

  mirrors = {
    sourcehut = {
      hostname = "git.sr.ht";
      username = "~alanpearce";
    };
    codeberg = {
      hostname = "codeberg.org";
      username = "alanpearce";
    };
    github = {
      hostname = "github.com";
      username = "alanpearce";
    };
  };

  repoMirrors = {
    nixfiles = [
      "sourcehut"
      "codeberg"
    ];
    searchix = [
      "sourcehut"
      "codeberg"
    ];
    website = [ "sourcehut" ];
    homestead = [ "sourcehut" ];
    legit = [ "github" ];
    elgit = [ "codeberg" ];
    gomponents = [
      "sourcehut"
      "github"
    ];
    nix-packages = [
      "sourcehut"
      "github"
    ];
    zola-bearblog = [
      "sourcehut"
      "codeberg"
    ];
  };

  createMirrorService =
    name:
    { hostname, username }:
    {
      "mirror-to-${name}@" = {
        path = with pkgs; [
          gitMinimal
          openssh
        ];
        serviceConfig = {
          Type = "oneshot";
          User = "gitolite";
          WorkingDirectory = "${repos}/%i.git";
          ExecStart = "${pkgs.gitMinimal}/bin/git push --mirror git@${hostname}:${username}/%i";
        };
        unitConfig = {
          # only mirror public repositories
          ConditionPathExists = "${repos}/%i.git/git-daemon-export-ok";
        };
      };
    };

  createMirrorPath =
    name:
    { ... }:
    {
      "mirror-to-${name}@" = {
        pathConfig = {
          PathChanged = "${repos}/%i.git/refs/heads";
          StartLimitIntervalSec = "1h";
          StartLimitBurst = 5;
        };
      };
    };

  mkMirrorWants = repo: map (target: "mirror-to-${target}@${repo}.path");
in
{
  services.gitolite = {
    enable = true;
    adminPubkey = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHYUyDdw92TNXguAxcmcmZmn/7ECGdRp6ckjxU+5zCw3BCnsS5+xEvHBVnnFdJRoH2XpfMeJjE+fi67zFVhlbn4= root@secretive.marvin";
    extraGitoliteRc = ''
      $RC{UMASK} = 0027;
      $RC{LOG_EXTRA} = 0;
      $RC{HOSTNAME} = "${config.networking.hostName}";
      $RC{LOCAL_CODE} = "$rc{GL_ADMIN_BASE}/local";
      push( @{$RC{ENABLE}}, 'D' );
      push( @{$RC{ENABLE}}, 'Shell alan' );
      push( @{$RC{ENABLE}}, 'cgit' );
      push( @{$RC{ENABLE}}, 'repo-specific-hooks' );
    '';
  };
  services.elgit = {
    enable = true;
    group = gitoliteCfg.group;
    settings = {
      server.name = serverName;
      repo = {
        root = gitoliteCfg.dataDir;
      };
      dirs.static = "/srv/http/elgit/static";
    };
  };
  services.gitDaemon = {
    enable = true;
    user = "gitolite";
    group = gitoliteCfg.group;
    basePath = repos;
  };

  services.caddy.virtualHosts = {
    "${serverName}" =
      let
        settings = config.services.elgit.settings;
        server = settings.server;
      in
      {
        extraConfig = ''
          encode zstd gzip
          ${security-headers {
            overrides.content-security-policy = {
              default-src = [ "none" ];
              base-uri = [ "none" ];
              style-src = [ "self" ];
              script-src = [ "none" ];
              form-action = [ "self" ];
              connect-src = [ "self" ];
              img-src = [ "https:" ];
              object-src = [ "none" ];
            };
          }}
          reverse_proxy ${server.host}:${toString server.port}
        '';
      };
    "git.alanpearce.eu" = {
      extraConfig = ''
        redir https://${serverName}{uri} 301 permanent
      '';
    };
  };

  systemd.services = concatMapAttrs createMirrorService mirrors;
  systemd.paths = concatMapAttrs createMirrorPath mirrors;
  systemd.targets.git-mirroring = {
    wantedBy = [ "multi-user.target" ];
    wants = pipe repoMirrors [
      (mapAttrsToList mkMirrorWants)
      flatten
    ];
  };
}