nix

configuration files that power my machines
Log | Files | Refs | README | LICENSE

commit 3490014d2ad3e9507394118f13f75d9dda3ccbdf
parent d93980ab23c96bd05baffcc8111187943f37b693
Author: mtmn <miro@haravara.org>
Date:   Wed, 24 Jun 2026 00:02:12 +0200

stagit: init

Diffstat:
Mflake.lock | 12++++++------
Mhosts/nixaran/configuration.nix | 0
Mhosts/void/default.nix | 8+-------
Mmodules/mixins/dotfiles/config/newsraft/feeds | 1+
Mmodules/mixins/dotfiles/config/shell/rc/aliased-short-names | 10++--------
Amodules/services/stagit.nix | 179+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 189 insertions(+), 21 deletions(-)

diff --git a/flake.lock b/flake.lock @@ -162,11 +162,11 @@ ] }, "locked": { - "lastModified": 1782166451, - "narHash": "sha256-SA7LyrayyZBvtzZnesnSLV7haciFuVLeZaX2hd5v4j4=", + "lastModified": 1782233665, + "narHash": "sha256-h/xOtrByoA/Ak1lWHn0O1lVZz4qWYbwOSLQ8YSwQO0I=", "owner": "nix-community", "repo": "home-manager", - "rev": "471a1d2f840eb7fcbdfd541d99c13a64096f46db", + "rev": "062581938b4a378a82dfbb294b494808157153a1", "type": "github" }, "original": { @@ -248,11 +248,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1781607440, - "narHash": "sha256-rxO+uc/KFbSJp+pgyXRuAX6QlG9hJdnt0BXpEQRXY+U=", + "lastModified": 1782118813, + "narHash": "sha256-BnbXO5s5EhV89lLXMAGCzPdEN5a6vNqvMk71obeTEUw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3e41b24abd260e8f71dbe2f5737d24122f972158", + "rev": "b3c092d3c36d91e2f61f3dfb39a159f180a56659", "type": "github" }, "original": { diff --git a/hosts/nixaran/configuration.nix b/hosts/nixaran/configuration.nix Binary files differ. diff --git a/hosts/void/default.nix b/hosts/void/default.nix @@ -20,7 +20,6 @@ tiny khard chawan - iamb ]; data = [ @@ -51,8 +50,6 @@ git-crypt git-absorb git-bug - jujutsu - jjui prek hut got @@ -80,8 +77,6 @@ iperf3 sshuttle sshs - riemann - riemann-tools flyctl bore-cli ] @@ -132,7 +127,6 @@ cloc hyperfine duf - watchman sysbench fswatch lf @@ -141,7 +135,6 @@ nix = [ nixd - lorri cachix statix deadnix @@ -183,6 +176,7 @@ ghostty halloy avidemux + mpv ]; llm = [ diff --git a/modules/mixins/dotfiles/config/newsraft/feeds b/modules/mixins/dotfiles/config/newsraft/feeds @@ -239,3 +239,4 @@ https://www.youtube.com/feeds/videos.xml?channel_id=UCfzlCWGWYyIQ0aLC5w48gBQ sen https://www.youtube.com/feeds/videos.xml?channel_id=UC4a9LfdavRlVMaSSWFdIciA RobWords https://www.youtube.com/feeds/videos.xml?channel_id=UCDetdM5XDZD1xrQHDPgEg5w Dictionary of Obscure Sorrows https://www.youtube.com/feeds/videos.xml?channel_id=UCB2ATFiszUNmw6z1x67GnYw zach +https://www.youtube.com/feeds/videos.xml?channel_id=UCW7jUEpYT_t0Gsf632d6_wQ clabretro diff --git a/modules/mixins/dotfiles/config/shell/rc/aliased-short-names b/modules/mixins/dotfiles/config/shell/rc/aliased-short-names @@ -15,11 +15,7 @@ alias tst='tmux set status' alias tls='tmux list-sessions' alias tms="tmux display-message -p '#{session_name}'" -alias s='sshs' -alias oc='isolate opencode' - alias mgr='magdalena grep' -alias mgrf='cdg && magdalena grep && cd -' alias mrd='magdalena recent-dirs' alias mrf='magdalena recent-files' @@ -58,7 +54,6 @@ alias qq='mpc playlist' alias n='nota' alias no='nota' -alias nor='NOTA_READ_ONLY=1 nota' alias to='nota today' alias ye='nota yesterday' @@ -95,8 +90,7 @@ alias apc='ansible-playbook --check --diff' alias yt_dlp_audio_url='yt-dlp -f bestaudio -g' alias yt_dlp_audio='yt-dlp --embed-thumbnail --write-thumbnail --extract-audio --audio-format mp3 --audio-quality 0' -alias nbd='nix build' -alias nds='nix develop' +alias nd='nix develop' alias hms='just --justfile ~/src/sr.ht/nix/justfile home' alias hmd='just --justfile ~/src/sr.ht/nix/justfile diff' @@ -104,7 +98,7 @@ alias hmd='just --justfile ~/src/sr.ht/nix/justfile diff' alias nmdr='just --justfile ~/src/sr.ht/nix/justfile diffr' alias ndpj='just --justfile ~/src/sr.ht/nix/justfile deploy' -alias nn='~/src/sr.ht/napkins/nn' +alias napkin='~/src/sr.ht/napkins/nn' alias amsp='mpva https://radio.stereoscenic.com/asp-s --no-resume-playback' alias nts1='mpva https://stream-relay-geo.ntslive.net/stream --no-resume-playback' diff --git a/modules/services/stagit.nix b/modules/services/stagit.nix @@ -0,0 +1,179 @@ +{ + config, + lib, + pkgs, + configData, + haravara, + ... +}: let + cfg = config.services.haravara.stagit; + + gitoliteUser = config.services.gitolite.user; + reposDir = "${config.services.gitolite.dataDir}/repositories"; + assets = "${pkgs.stagit}/share/doc/stagit"; + + excludeNames = ["gitolite-admin"] ++ cfg.excludeRepos; + excludeDirPattern = lib.concatMapStringsSep "|" (r: "${r}.git") excludeNames; + excludeNamePattern = lib.concatStringsSep "|" excludeNames; + + preamble = '' + export LC_CTYPE="C.UTF-8" + umask 022 + + reposdir="${reposDir}" + htmldir="${cfg.htmlDir}" + cloneurl="ssh://${gitoliteUser}@${cfg.domain}:${toString cfg.sshPort}" + + mkdir -p "$htmldir" + install -m644 "${assets}/style.css" "$htmldir/style.css" + install -m644 "${assets}/logo.png" "$htmldir/logo.png" + install -m644 "${assets}/favicon.png" "$htmldir/favicon.png" + + set -- + for dir in "$reposdir"/*.git; do + [ -d "$dir" ] || continue + case "$(basename "$dir")" in ${excludeDirPattern}) continue ;; esac + set -- "$@" "$dir" + done + ''; + + render_repo = '' + render_repo() { + dir="$1" + d=$(basename "$dir" .git) + mkdir -p "$htmldir/$d" + ( + cd "$htmldir/$d" || exit 1 + stagit -c .cache -u "$cloneurl/$d" "$dir" + ln -sf log.html index.html + ln -sf ../style.css style.css + ln -sf ../logo.png logo.png + ln -sf ../favicon.png favicon.png + ) || echo "stagit: failed to render $d" >&2 + } + ''; + + generate = pkgs.writeShellApplication { + name = "stagit-generate"; + runtimeInputs = [pkgs.stagit pkgs.git pkgs.coreutils]; + text = '' + ${preamble} + ${render_repo} + + stagit-index "$@" > "$htmldir/index.html" + for dir in "$@"; do + render_repo "$dir" + done + ''; + }; + + postReceive = pkgs.writeShellApplication { + name = "post-receive"; + runtimeInputs = [pkgs.stagit pkgs.git pkgs.coreutils]; + text = '' + ${preamble} + ${render_repo} + + name=$(basename "$(pwd)") + d=$(basename "$name" .git) + case "$d" in ${excludeNamePattern}) exit 0 ;; esac + + # Detect a force-push so the commit cache can be rebuilt from scratch. + force=0 + while read -r old new _ref; do + [ "$old" = "0000000000000000000000000000000000000000" ] && continue + [ "$new" = "0000000000000000000000000000000000000000" ] && continue + if [ -n "$(git rev-list "$old" "^$new" 2>/dev/null | sed 1q)" ]; then + force=1 + break + fi + done + + if [ "$force" = "1" ]; then + rm -f "$htmldir/$d/.cache" + rm -rf "$htmldir/$d/commit" + fi + + render_repo "$reposdir/$name" + stagit-index "$@" > "$htmldir/index.html" + ''; + }; +in { + options.services.haravara.stagit = { + enable = lib.mkEnableOption "stagit static git pages backed by gitolite"; + + domain = lib.mkOption { + type = lib.types.str; + }; + + htmlDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/stagit"; + }; + + sshPort = lib.mkOption { + type = lib.types.port; + default = 22; + }; + + authLabel = haravara.authLabelOption; + + excludeRepos = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + example = ["secret-notes" "wip"]; + }; + + adminPubkey = lib.mkOption { + type = lib.types.str; + default = builtins.head configData.users.${configData.defaultUser}.authorizedKeys; + }; + }; + + config = lib.mkIf cfg.enable { + services = { + gitolite = { + enable = true; + inherit (cfg) adminPubkey; + commonHooks = ["${postReceive}/bin/post-receive"]; + }; + + openssh.settings.AllowUsers = [gitoliteUser]; + + caddy.virtualHosts."${cfg.domain}".extraConfig = '' + ${haravara.mkAuthImport cfg.authLabel} + root * ${cfg.htmlDir} + encode gzip + file_server + ''; + }; + + systemd = { + tmpfiles.rules = [ + "d ${cfg.htmlDir} 0755 ${gitoliteUser} ${config.services.gitolite.group} -" + ]; + + services.stagit-generate = { + description = "Generate stagit static pages for all gitolite repos"; + after = ["gitolite-init.service"]; + wants = ["gitolite-init.service"]; + wantedBy = ["multi-user.target"]; + serviceConfig = { + Type = "oneshot"; + User = gitoliteUser; + Group = config.services.gitolite.group; + ExecStart = "${generate}/bin/stagit-generate"; + }; + }; + + timers.stagit-generate = { + description = "Periodic stagit regeneration"; + wantedBy = ["timers.target"]; + timerConfig = { + OnCalendar = "*:0/30"; + Persistent = true; + }; + }; + }; + }; +}