{ config, lib, pkgs, ... }: let stagitFunctions = pkgs.writeShellScript "stagitFunctions" '' export LC_CTYPE="en_US.UTF-8" is_public_and_listed() { if [ ! -f "$1/git-daemon-export-ok" ]; then return 1 fi return 0 } is_forced_update() { test "$oldrev" = "0000000000000000000000000000000000000000" && return 1 test "$newrev" = "0000000000000000000000000000000000000000" && return 1 hasrevs="$(${pkgs.git}/bin/git rev-list "$oldrev" "^$newrev" | ${pkgs.gnused}/bin/sed 1q)" if test -n "$hasrevs"; then return 0 fi return 1 } build_stagit_repo() { reponame="$(basename "$1" ".git")" printf "[%s] Generate stagit HTML pages... " "$reponame" mkdir -p "/var/lib/gitolite/stagit-cache" mkdir -p "/var/lib/stagit/$reponame" cd "/var/lib/stagit/$reponame" || return 1 # build repo pages ${pkgs.stagit}/bin/stagit -c "/var/lib/gitolite/stagit-cache/$reponame" -n 'ctucx.git' -h 'https://git.ctu.cx/' -s 'git@${config.networking.hostName}.ctu.cx:' "$1" # set correct permissions chown git:git -R /var/lib/stagit/$reponame; chmod 755 -R /var/lib/stagit/$reponame; echo "done" } build_stagit_index() { printf "Generating stagit index... " # set assets if not already there ln -sf "${pkgs.stagit}/share/doc/stagit/style.css" "/var/lib/stagit/style.css" 2> /dev/null # generate index arguments args="-n 'ctucx.git' -e 'git@ctu.cx'" for category in "nix" "etc" "nimlang" "nimlang libraries" "archive"; do args="$args -c '$category'" for repo in "$HOME/repositories/"*.git/; do repo="''${repo%/}" is_public_and_listed "$repo" || continue [ "$(${pkgs.gawk}/bin/awk -F '=' '/category/ {print $2}' $repo/config | ${pkgs.gnused}/bin/sed -e 's/^[[:space:]]*//')" = "$category" ] && args="$args $repo" done done # build index echo "$args" | xargs ${pkgs.stagit}/bin/stagit-index > /var/lib/stagit/index.html # set correct permissions chown git:git /var/lib/stagit/index.html; chmod 755 /var/lib/stagit/index.html; echo "done" } update_stagit_repo() { repo="$(pwd)" reponame="$(basename "$repo" ".git")" cd "$repo" || return 1 is_public_and_listed "$repo" || return 0 # if forced update, remove directory and cache file is_forced_update && printf "[%s] Forced update, trigger complete regeneration of stagit-pages... \n" "$reponame" && rm -rf "/var/lib/stagit/$reponame" "/var/lib/gitolite/stagit-cache/$reponame" build_stagit_repo "$repo" build_stagit_index } ''; rebuildWebdir = '' source ${stagitFunctions} # clear webdir rm -rf /var/lib/stagit/* # clear cache rm -rf /var/lib/gitolite/stagit-cache/* # generate pages per repo for repo in "$HOME/repositories/"*.git/; do repo="''${repo%/}" is_public_and_listed "$repo" || continue build_stagit_repo "$repo" done # generate index page build_stagit_index ''; in { services.openssh.settings.Macs = [ "hmac-sha2-512" "hmac-sha2-512-etm@openssh.com" "hmac-sha2-256-etm@openssh.com" "umac-128-etm@openssh.com" ]; dns.zones."ctu.cx".subdomains = { cgit.CNAME = [ "${config.networking.fqdn}." ]; git.CNAME = [ "${config.networking.fqdn}." ]; }; age.secrets.restic-gitolite.file = ./. + "/../../secrets/${config.networking.hostName}/restic/gitolite.age"; restic-backups.gitolite = { user = "git"; passwordFile = config.age.secrets.restic-gitolite.path; paths = [ "/var/lib/gitolite" ]; }; services = { gitolite = { enable = true; user = "git"; group = "git"; adminPubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDb2eZ2ymt+Zsf0eTlmjW2jPdS013lbde1+EGkgu6bz9lVTR8aawshF2HcoaWp5a5dJr3SKyihDM8hbWSYB3qyTHihNGyCArqSvAtZRw301ailRVHGqiwUITTfcg1533TtmWvlJZgOIFM1VvSAfdueDRRRzbygmn749fS9nhUTDzLtjqX5LvhpqhzsD+eOqPrV6Ne8E1e42JxQb5AJPY1gj9mk6eAarvtEHQYEe+/hp9ERjtCdN5DfuOJnqfaKS0ytPj/NbQskbX/TMgeUVio11iC2NbXsnAtzMmtbLX4mxlDQrR6aZmU/rHQ4aeJqI/Tj2rrF46icri7s0tnnit1OjT5PSxXgifcOtn06qoxYZMT1x+Dyrt40vNkGmxmxCnirm8B+6MKXgd/Ys+7tnOm1ht8TmLm96x6KdOiF3Zq/tMxhPAzp8JriTKSo7k7U9XxStFghTbhhBNc7OX89ZbpalLEnvbQiz87gZxhcx8cLvzIjslOHmZOSWC5Pgr4wwuj3Akq63i4ya6/BzM6v4UoBuDAB6fz3NHKL4R5X20la7Pvt7OBysQkGClWfj6ipMR1bFE2mfYtlMioXNgTjC+NCpEl1+81MH7dv2565Hk8CLV8FMxv6GujbAZGjjcM47lpWM1cBQvpBMUA/lLkyiCPK0YxNWAB7Co+jYDl6CR0Ubew== cardno:6445161"; extraGitoliteRc = '' $RC{GIT_CONFIG_KEYS} = ".*"; $RC{UMASK} = 0027; push(@{$RC{ENABLE}}, 'cgit'); push(@{$RC{ENABLE}}, 'symbolic-ref'); push(@{$RC{ENABLE}}, 'rebuild-webdir'); push(@{$RC{ENABLE}}, 'rebuild-webdir'); $RC{NON_CORE} = "rebuild-webdir-trigger POST_COMPILE rebuild-stagit"; ''; triggers.rebuild-webdir = rebuildWebdir; commands.rebuild-webdir = rebuildWebdir; commonHooks.post-receive = '' # update stagit pages source ${stagitFunctions} update_stagit_repo "$1" ''; }; fcgiwrap = { enable = true; user = "git"; group = "git"; }; nginx = { enable = true; virtualHosts = { "cgit.ctu.cx" = { enableACME = true; forceSSL = true; kTLS = true; locations = { "~ '^/[a-zA-Z0-9._-]+/(git-(receive|upload)-pack|HEAD|info/refs|objects/(info/(http-)?alternates|packs)|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))$'".return = "307 https://git.ctu.cx$request_uri"; "~ '^/([a-zA-Z0-9_.]+)/*$'".return = "307 https://git.ctu.cx/$1"; "~ '^/([a-zA-Z0-9_.]+)/tree/([a-zA-Z0-9_./-]+[a-zA-Z0-9_-])/*$'".return = "307 https://git.ctu.cx/$1/tree/$2.html"; "~ '^/([a-zA-Z0-9_.]+)/tree/*$'".return = "307 https://git.ctu.cx/$1/tree.html"; "~ '^/([a-zA-Z0-9_.]+)/log/*$'".return = "307 https://git.ctu.cx/$1/log.html"; "~ '^/([a-zA-Z0-9_.]+)/commit/*$'".extraConfig = '' if ($arg_id) { return 307 https://git.ctu.cx/$1/commit/$arg_id.html; } return 307 https://git.ctu.cx/$1/log.html; ''; }; }; "git.ctu.cx" = { enableACME = true; forceSSL = true; kTLS = true; root = "/var/lib/stagit"; locations = { "@redir".return = "307 ../log.html"; "~ '^/([a-zA-Z0-9_.]+)/commit/.*$'".extraConfig = "error_page 404 = @redir;"; "~* \.html$".extraConfig = '' add_header Last-Modified $date_gmt; add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; if_modified_since off; expires off; etag off; ''; "~ '^/[a-zA-Z0-9._-]+/raw'".extraConfig = '' types { application/json json; application/wasm wasm; font/woff woff; font/woff2 woff2; application/pdf pdf; image/gif gif; image/jpeg jpeg jpg; image/png png; image/svg+xml svg svgz; image/webp webp; image/x-icon ico; } default_type text/plain; try_files $uri =404; ''; "~ '^/[a-zA-Z0-9._-]+/(git-(receive|upload)-pack|HEAD|info/refs|objects/(info/(http-)?alternates|packs)|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))$'".extraConfig = '' if ($query_string = service=git-receive-pack) { return 403; } include "${pkgs.nginx}/conf/fastcgi_params"; fastcgi_param SCRIPT_FILENAME "${pkgs.git}/libexec/git-core/git-http-backend"; fastcgi_param GIT_PROJECT_ROOT /var/lib/gitolite/repositories; fastcgi_param PATH_INFO $uri; fastcgi_pass unix:${config.services.fcgiwrap.socketAddress}; ''; }; }; }; }; }; }