feat(nixos/roles/git): serve petal on git.lostduk.com
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};+ ''; }; }