greenhouse

kore

my public infrastructure monorepo

git clone [email protected]:kore.git

feat(nixos/roles/git): serve petal on git.lostduk.com

commit1066bbafb0983b49ebb5972535c3184a686686b7
parent072756556de767559d058588618d263b78cd4d9f
authorlostduk <[email protected]>
date2026-10-14 11:45 +0000
flake.lock17++++++++++
flake.nix3++
kore.json9++++-
nixos/features/kore.nix10+++++-
nixos/roles/git.nix75++++++++++++++++++++++++++++++++++++++--

5 files changed, -5/+109

flake.lock

@@ -36,6 +36,22 @@         "type": "github"       }     },+    "greenhouse": {+      "flake": false,+      "locked": {+        "lastModified": 1791977330,+        "narHash": "sha256-U5b02FLOLbIri0IHjkc9rbmqMKFahGvs1XJ1iwj11KI=",+        "ref": "refs/heads/main",+        "rev": "3d35447859ea3605eed5b6300b61736fce6eeedd",+        "revCount": 1,+        "type": "git",+        "url": "ssh://[email protected]/greenhouse"+      },+      "original": {+        "type": "git",+        "url": "ssh://[email protected]/greenhouse"+      }+    },     "home-manager": {       "inputs": {         "nixpkgs": [@@ -152,6 +168,7 @@     "root": {       "inputs": {         "disko": "disko",+        "greenhouse": "greenhouse",         "home-manager": "home-manager",         "impermanence": "impermanence",         "nixos-wsl": "nixos-wsl",

flake.nix

@@ -12,6 +12,9 @@          home-manager.url = "sourcehut:~rycee/home-manager";     home-manager.inputs.nixpkgs.follows = "nixpkgs";++    greenhouse.url = "git+ssh://[email protected]/greenhouse";+    greenhouse.flake = false;   };    outputs = inputs@{ self, nixpkgs, ... }:

kore.json

@@ -23,6 +23,13 @@     }   },   "repos": {-    "kore": { "write": ["lostduk"] }+    "kore": {+      "write": ["lostduk"],+      "description": "my public infrastructure monorepo"+    },+    "greenhouse": {+      "write": ["lostduk"],+      "description": "forge suite"+    }   } }

nixos/features/kore.nix

@@ -69,6 +69,14 @@ let       type = types.listOf types.str;       default = [];     };+    description = mkOption {+      type = types.str;+      default = "";+    };+    owner = mkOption {+      type = types.nullOr types.str;+      default = null;+    };   };    hostNames = name: host:@@ -117,7 +125,7 @@ in {     }] ++ map (id: {       assertion = cfg.identities ? ${id};       message = "kore: repo ${repo} lists ${id}, but kore.json has no identity for it";-    }) (acl.write ++ acl.read)) cfg.repos);+    }) (acl.write ++ acl.read ++ lib.optional (acl.owner != null) acl.owner)) cfg.repos);      nixpkgs.hostPlatform = cfg.currentHost.system;     system.stateVersion = cfg.currentHost.stateVersion;

nixos/roles/git.nix

@@ -1,9 +1,32 @@-{ config, lib, pkgs, ... }:+{ inputs, config, lib, pkgs, ... }:  let   inherit (config.kore) identities repos;+  inherit (config.networking) domain;   root = "/srv/git"; +  petal = pkgs.stdenv.mkDerivation {+    pname = "petal";+    version = "0-${inputs.greenhouse.shortRev or "dirty"}";++    src = "${inputs.greenhouse}/petal";++    buildInputs = [ pkgs.libgit2 ];++    makeFlags = [+      "PREFIX=$(out)"+      "CC=${pkgs.stdenv.cc.targetPrefix}cc"+      "GIT2INC=${lib.getDev pkgs.libgit2}/include"+      "GIT2LIB=${lib.getLib pkgs.libgit2}/lib"+    ];+  };++  petalHome = pkgs.writeTextDir ".gitconfig" (lib.generators.toGitINI {+    safe.directory = map (repo: "${root}/${repo}.git") (lib.attrNames repos);+  });++  owner = access: if access.owner != null then access.owner else lib.findFirst (_: true) "" access.write;+   acl = pkgs.writeText "kore-git-acl" (lib.concatLines (lib.concatLists (lib.mapAttrsToList (repo: access:     map (id: "${repo} write ${id}") access.write     ++ map (id: "${repo} read ${id}") access.read@@ -50,11 +73,17 @@ let    members = lib.unique (lib.concatLists (lib.mapAttrsToList (_: access: access.write ++ access.read) repos)); in {+  assertions = [{+    assertion = lib.elem "web" config.kore.currentHost.roles;+    message = "kore: the git role needs the web role for petal";+  }];+   users.groups.git = {};   users.users.git = {     isSystemUser = true;     group = "git";     home = root;+    homeMode = "750";     createHome = true;     shell = pkgs.bash; @@ -72,11 +101,51 @@ in {       Group = "git";     };     path = [ pkgs.git pkgs.coreutils ];-    script = lib.concatMapStrings (repo: ''+    script = lib.concatStrings (lib.mapAttrsToList (repo: access: ''       if [ ! -d '${root}/${repo}.git' ]; then         mkdir -p "$(dirname '${root}/${repo}.git')"         git init --quiet --bare --initial-branch=main '${root}/${repo}.git'       fi-    '') (lib.attrNames repos);+      printf '%s\n' ${lib.escapeShellArg access.description} > '${root}/${repo}.git/description'+      printf '%s\n' ${lib.escapeShellArg (owner access)} > '${root}/${repo}.git/owner'+    '') repos);+  };++  systemd.tmpfiles.rules = [ "z ${root} 0750 git git -" ];++  users.users.petal = {+    isSystemUser = true;+    group = "git";+  };++  services.fcgiwrap.instances.petal = {+    process.user = "petal";+    process.group = "git";+    socket.user = config.services.nginx.user;+    socket.group = config.services.nginx.group;+  };++  services.nginx.virtualHosts."git.${domain}" = {+    enableACME = true;+    forceSSL = true;++    locations."= /style.css".alias = "${petal}/share/petal/style.css";++    locations."/".extraConfig = ''+      fastcgi_param GATEWAY_INTERFACE CGI/1.1;+      fastcgi_param SERVER_PROTOCOL $server_protocol;+      fastcgi_param SERVER_NAME $server_name;+      fastcgi_param SERVER_PORT $server_port;+      fastcgi_param REQUEST_METHOD $request_method;+      fastcgi_param REQUEST_URI $request_uri;+      fastcgi_param QUERY_STRING $query_string;+      fastcgi_param REMOTE_ADDR $remote_addr;+      fastcgi_param HTTPS $https if_not_empty;+      fastcgi_param SCRIPT_FILENAME ${petal}/bin/petal;+      fastcgi_param SCRIPT_NAME "";+      fastcgi_param PATH_INFO $uri;+      fastcgi_param HOME ${petalHome};+      fastcgi_pass unix:${config.services.fcgiwrap.instances.petal.socket.address};+    '';   }; }