commit 3490014d2ad3e9507394118f13f75d9dda3ccbdf
parent d93980ab23c96bd05baffcc8111187943f37b693
Author: mtmn <miro@haravara.org>
Date: Wed, 24 Jun 2026 00:02:12 +0200
stagit: init
Diffstat:
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;
+ };
+ };
+ };
+ };
+}