aboutsummaryrefslogtreecommitdiff
path: root/modules/services/nixos/cgit/default.nix
diff options
context:
space:
mode:
authorCollin Williams <96917990+bluedragon1221@users.noreply.github.com>2026-02-22 15:22:54 -0600
committerCollin Williams <96917990+bluedragon1221@users.noreply.github.com>2026-02-22 15:22:54 -0600
commit93ddc9cb616d1fcabd8f1b7cab338d1da8701fd4 (patch)
tree191a2af395a64f11d39bcca0937c335447c4d417 /modules/services/nixos/cgit/default.nix
parent64f1cfc792b3160e639c00478b58eca714536a60 (diff)
stuff
Diffstat (limited to 'modules/services/nixos/cgit/default.nix')
-rw-r--r--modules/services/nixos/cgit/default.nix139
1 files changed, 139 insertions, 0 deletions
diff --git a/modules/services/nixos/cgit/default.nix b/modules/services/nixos/cgit/default.nix
new file mode 100644
index 0000000..0f81958
--- /dev/null
+++ b/modules/services/nixos/cgit/default.nix
@@ -0,0 +1,139 @@
+{
+ pkgs,
+ config,
+ lib,
+ ...
+}: let
+ cfg = config.collinux.services.cgit;
+in {
+ config = lib.mkIf cfg.enable {
+ environment.shells = ["${pkgs.git}/bin/git-shell"];
+ users.groups."git" = {};
+ users.users."git" = {
+ isSystemUser = true;
+ group = "git";
+ shell = "${pkgs.git}/bin/git-shell";
+
+ home = "/var/lib/cgit";
+ createHome = true;
+ homeMode = "755";
+
+ openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC3SjzIs3YI8PWJaNrAuaEeRcTcvIVHOKyCh2VwHTHEF"];
+ };
+ hjem.users."git".files = {
+ "git-shell-commands/set-description" = {
+ executable = true;
+ text = ''
+ #!/usr/bin/env bash
+ set -euo pipefail
+ repo="$1"
+ desc="$2"
+ base="/var/lib/cgit"
+ repo_path="$base/$repo"
+
+ test -d "$repo_path" || { echo "Repository does not exist"; exit 1; }
+
+ # Prevent path traversal
+ real=$(realpath "$repo_path")
+ if [[ "$real" != "$base/"* ]]; then
+ echo "Invalid path"
+ exit 1
+ fi
+
+ echo "$desc" | head -n 1 > "$repo_path/description"
+
+ echo "Description updated for '$repo'"
+ '';
+ };
+ "git-shell-commands/create-repo" = {
+ executable = true;
+ text = ''
+ #!/usr/bin/env bash
+ set -euo pipefail
+ repo="$1"
+ base="/var/lib/cgit"
+ repo_path="$base/$repo"
+
+ test -d "$repo_path" && { echo "Repository already exists."; exit 1; }
+
+ git init --bare "$repo_path"
+ echo "Repository '$repo' created"
+ '';
+ };
+ };
+
+ services.openssh.extraConfig = lib.mkAfter ''
+ Match User git
+ AllowTcpForwarding no
+ X11Forwarding no
+ PermitTunnel no
+ PubkeyAuthentication yes
+ AuthenticationMethods publickey
+ '';
+
+ environment.etc."cgitrc".text = ''
+ logo=/favicon.svg
+ favicon=/favicon.svg
+
+ repo.sort=age
+ enable-http-clone=1
+ enable-commit-graph=1
+ side-by-side-diffs=1
+
+ root-title=git@ganymede
+ root-desc=Git repos associated with Ganymede
+
+ readme=:README.md
+ about-filter=${pkgs.cgit}/lib/cgit/filters/html-converters/md2html
+ source-filter=${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py
+ footer=
+
+ virtual-root=/
+ scan-path=/var/lib/cgit
+ '';
+
+ services.fcgiwrap.instances."cgit" = {
+ process = {
+ user = "git";
+ group = "git";
+ };
+
+ socket = {
+ user = "caddy";
+ group = "caddy";
+ type = "unix";
+ address = "/run/fcgiwrap-cgit.sock";
+ };
+ };
+
+ networking.extraHosts = "127.0.0.1 git.ganymede";
+ services.caddy.virtualHosts."git.ganymede".extraConfig = let
+ custom_cgit = pkgs.stdenv.mkDerivation {
+ name = "custom-cgit-assets";
+ src = pkgs.cgit;
+ installPhase = ''
+ mkdir -p $out
+ cp -pPR ./cgit/* $out/
+
+ rm -f $out/cgit.png $out/favicon.ico $out/cgit.css
+ cp -f ${./favicon.svg} $out/favicon.svg
+ cp -f ${./cgit.css} $out/cgit.css
+ '';
+ };
+ in ''
+ tls internal
+
+ @assets path /cgit.css /cgit.js /favicon.svg /robots.txt
+ handle @assets {
+ root * ${custom_cgit}
+ file_server
+ }
+
+ reverse_proxy unix//run/fcgiwrap-cgit.sock {
+ transport fastcgi {
+ env SCRIPT_FILENAME ${custom_cgit}/cgit.cgi
+ }
+ }
+ '';
+ };
+}