diff --git a/AGENTS.md b/AGENTS.md index 9f9618b..b548b62 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,7 +8,7 @@ Levantine food-themed hostnames: fatteh, kabsa, kibbeh, makanek, manakish, tabul ## Repository Structure ``` -flake.nix # 636 lines — everything: inputs, overlay, nixosConfigurations, apps, packages +flake.nix # ~650 lines — everything: inputs, overlay, nixosConfigurations, apps, packages configs/ # ~50 NixOS config fragments imported by systems (desktop defaults, programs, services) default.nix # 200+ line mega-module for desktop machines (user, shell, gnupg, i18n, etc.) graphical/ # Hyprland + home-manager config (415 lines in home-manager.nix) @@ -17,11 +17,10 @@ configs/ # ~50 NixOS config fragments imported by systems (desktop def keyboard/ # XKB layouts (Coptic, Avestan, Gothic, etc.) configs/*.nix # Individual concerns: bluetooth, sound, printing, ssh, fonts, etc. modules/ # Proper NixOS modules with options (retiolum, telegram-bot, passport, power-action, etc.) -packages/ # ~93 package files (many small scripts/wrappers) +packages/ # ~107 package files (scripts, wrappers, small tools) systems// # Per-machine: configuration.nix + hardware-configuration.nix + extras lib/ # default.nix (niveum helpers), machines.nix (IP/key inventory), panoptikon.nix secrets/ # agenix-encrypted .age files (empty dir in checkout, tracked via secrets.txt) -.bin/ # toposort.nix (seems unused/experimental) ``` ## Key Relationships diff --git a/flake.lock b/flake.lock index 6f74347..25f1347 100644 --- a/flake.lock +++ b/flake.lock @@ -753,7 +753,6 @@ "tinc-graph": "tinc-graph", "treefmt-nix": "treefmt-nix_4", "voidrice": "voidrice", - "wallpapers": "wallpapers", "wetter": "wetter", "wrappers": "wrappers_2" } @@ -1130,22 +1129,6 @@ "type": "github" } }, - "wallpapers": { - "flake": false, - "locked": { - "lastModified": 1589319718, - "narHash": "sha256-2NruGq3z37vY3uAH8S4sLqHvFAGi8gaDJAgEzMIvM/4=", - "owner": "kmein", - "repo": "wallpapers", - "rev": "7c553bc6bd78afa6dbf2824691466bbad0d8e6e9", - "type": "github" - }, - "original": { - "owner": "kmein", - "repo": "wallpapers", - "type": "github" - } - }, "wetter": { "inputs": { "nixpkgs": [ diff --git a/packages/avesta.nix b/packages/avesta.nix index 85ac887..2634159 100644 --- a/packages/avesta.nix +++ b/packages/avesta.nix @@ -1,5 +1,6 @@ # Transliterate Latin-script Avestan to Avestan Unicode script { + lib, writers, gnused, }: @@ -61,5 +62,5 @@ let ''; in writers.writeDashBin "avesta" '' - exec ${gnused}/bin/sed -f ${sedScript} "$@" + exec ${lib.getExe gnused} -f ${sedScript} "$@" '' diff --git a/packages/bvg.nix b/packages/bvg.nix index 2a73ccf..c6cfbb2 100644 --- a/packages/bvg.nix +++ b/packages/bvg.nix @@ -1,13 +1,12 @@ # Berlin BVG transit disruption checker { + lib, writers, curl, jq, }: writers.writeDashBin "bvg" '' - interesting="U6 N6 140 M46 184 N84" - - ${curl}/bin/curl -sSL 'https://www.bvg.de/disruption-reports/q' \ + ${lib.getExe curl} -sSL 'https://www.bvg.de/disruption-reports/q' \ --data-raw '{"variables":{},"query":"{ allDisruptions { disruptions { @@ -40,7 +39,7 @@ writers.writeDashBin "bvg" '' __typename } }"}' \ - | ${jq}/bin/jq --arg interesting "$interesting" ' + | ${lib.getExe jq} --arg interesting "$interesting" ' .data.allDisruptions.disruptions | map(select( (.linie as $linie diff --git a/packages/chunk-pdf.nix b/packages/chunk-pdf.nix index 3c951ce..0e63710 100644 --- a/packages/chunk-pdf.nix +++ b/packages/chunk-pdf.nix @@ -1,5 +1,6 @@ # Split a PDF into chunks of N pages { + lib, writers, pdftk, gnugrep, @@ -16,15 +17,15 @@ writers.writeDashBin "chunk-pdf" '' exit 1 fi - TOTAL_PAGES="$(${pdftk}/bin/pdftk "$INPUT_FILE" dump_data | ${gnugrep}/bin/grep NumberOfPages | ${coreutils}/bin/cut -f2 -d' ')" + TOTAL_PAGES="$(${lib.getExe pdftk} "$INPUT_FILE" dump_data | ${lib.getExe gnugrep} NumberOfPages | ${lib.getExe' coreutils "cut"} -f2 -d' ')" RUNS=$((TOTAL_PAGES/PAGES_PER_REPORT)) - for run in $(${coreutils}/bin/seq 0 "$((RUNS-1))"); do + for run in $(${lib.getExe' coreutils "seq"} 0 "$((RUNS-1))"); do start_page=$((run*PAGES_PER_REPORT+1)) end_page=$(((run+1)*PAGES_PER_REPORT)) output_file="chunk_$((run+1)).pdf" echo "splitting $INPUT_FILE from $start_page to $end_page into $output_file" - ${pdftk}/bin/pdftk "$INPUT_FILE" cat "$start_page-$end_page" output "$output_file" + ${lib.getExe pdftk} "$INPUT_FILE" cat "$start_page-$end_page" output "$output_file" done '' diff --git a/packages/fix-sd.nix b/packages/fix-sd.nix index eaf6b98..9e89c5a 100644 --- a/packages/fix-sd.nix +++ b/packages/fix-sd.nix @@ -1,5 +1,6 @@ # Recover files from a corrupted exFAT SD card { + lib, writers, exfatprogs, util-linux, @@ -11,24 +12,24 @@ writers.writeDashBin "fix-sd" '' set -efu drive="''${1:?Usage: fix-sd /dev/sdX [output-dir]}" - output_dir="''${2:-$(${coreutils}/bin/mktemp -d "''${TMPDIR:-/tmp}/fix-sd-XXXXXX")}" - mountpoint="$(${coreutils}/bin/mktemp -d "''${TMPDIR:-/tmp}/fix-sd-mount-XXXXXX")" + output_dir="''${2:-$(${lib.getExe' coreutils "mktemp"} -d "''${TMPDIR:-/tmp}/fix-sd-XXXXXX")}" + mountpoint="$(${lib.getExe' coreutils "mktemp"} -d "''${TMPDIR:-/tmp}/fix-sd-mount-XXXXXX")" trap clean EXIT clean() { - ${util-linux}/bin/umount "$mountpoint" 2>/dev/null || true - ${coreutils}/bin/rmdir "$mountpoint" 2>/dev/null || true + ${lib.getExe' util-linux "umount"} "$mountpoint" 2>/dev/null || true + ${lib.getExe' coreutils "rmdir"} "$mountpoint" 2>/dev/null || true } - filenames="$(${exfatprogs}/bin/fsck.exfat "$drive" 2>&1 | ${gnused}/bin/sed -nE "s/.* file '(.*?)' is not allocated.*/\1/p")" - ${coreutils}/bin/mkdir -p "$mountpoint" "$output_dir" - ${util-linux}/bin/mount "$drive" "$mountpoint" + filenames="$(${lib.getExe' exfatprogs "fsck.exfat"} "$drive" 2>&1 | ${lib.getExe gnused} -nE "s/.* file '(.*?)' is not allocated.*/\1/p")" + ${lib.getExe' coreutils "mkdir"} -p "$mountpoint" "$output_dir" + ${lib.getExe' util-linux "mount"} "$drive" "$mountpoint" echo "$filenames" | while read -r filename; do [ -n "$filename" ] || continue - ${findutils}/bin/find "$mountpoint" -type f -name "$filename" -exec ${coreutils}/bin/cp {} "$output_dir" \; + ${lib.getExe' findutils "find"} "$mountpoint" -type f -name "$filename" -exec ${lib.getExe' coreutils "cp"} {} "$output_dir" \; done echo "Recovered files saved to $output_dir" - ${exfatprogs}/bin/fsck.exfat "$drive" + ${lib.getExe' exfatprogs "fsck.exfat"} "$drive" '' diff --git a/packages/mp3player-write.nix b/packages/mp3player-write.nix index 97108d2..65995ff 100644 --- a/packages/mp3player-write.nix +++ b/packages/mp3player-write.nix @@ -1,10 +1,11 @@ # Convert and transfer audio files to an MP3 player { + lib, writers, ffmpeg, coreutils, gnugrep, - bash, + gnused, }: writers.writeBashBin "mp3player-write" '' set -e @@ -40,11 +41,11 @@ writers.writeBashBin "mp3player-write" '' echo "Warning: File '$f' does not exist, skipping." continue fi - FILE_SIZE=$(${coreutils}/bin/stat --printf="%s" "$f") + FILE_SIZE=$(${lib.getExe' coreutils "stat"} --printf="%s" "$f") TOTAL_SIZE=$((TOTAL_SIZE + FILE_SIZE / 2)) done - AVAILABLE=$(${coreutils}/bin/df --output=avail "$MOUNT_POINT" | ${coreutils}/bin/tail -n 1) + AVAILABLE=$(${lib.getExe' coreutils "df"} --output=avail "$MOUNT_POINT" | ${lib.getExe' coreutils "tail"} -n 1) AVAILABLE=$((AVAILABLE * 1024)) if [ "$TOTAL_SIZE" -gt "$AVAILABLE" ]; then @@ -56,18 +57,18 @@ writers.writeBashBin "mp3player-write" '' sanitize_filename() { local name - name=$(${coreutils}/bin/basename "$1") + name=$(${lib.getExe' coreutils "basename"} "$1") name=''${name%.*} - name=$(echo "$name" | ${coreutils}/bin/tr ' ' '_' | ${coreutils}/bin/tr -cd '[:alnum:]_-') + name=$(echo "$name" | ${lib.getExe' coreutils "tr"} ' ' '_' | ${lib.getExe' coreutils "tr"} -cd '[:alnum:]_-') echo "''${name:0:50}" } for f in "''${FILES[@]}"; do [ -f "$f" ] || continue - existing_prefixes=$(${coreutils}/bin/ls "$MOUNT_POINT" | ${gnugrep}/bin/grep -E '^[0-9].*\.mp3$' | ${coreutils}/bin/sed -E 's/^([0-9]).*/\1/' | ${coreutils}/bin/sort -n | ${coreutils}/bin/uniq) + existing_prefixes=$(${lib.getExe' coreutils "ls"} "$MOUNT_POINT" | ${lib.getExe gnugrep} -E '^[0-9].*\.mp3$' | ${lib.getExe gnused} -E 's/^([0-9]).*/\1/' | ${lib.getExe' coreutils "sort"} -n | ${lib.getExe' coreutils "uniq"}) for i in {0..9}; do - if ! echo "$existing_prefixes" | ${gnugrep}/bin/grep -q "^$i$"; then + if ! echo "$existing_prefixes" | ${lib.getExe gnugrep} -q "^$i$"; then PREFIX=$i break fi @@ -78,7 +79,7 @@ writers.writeBashBin "mp3player-write" '' echo "Converting '$f' to '$OUT_PATTERN' at speed $SPEED..." - ${ffmpeg}/bin/ffmpeg -nostdin -i "$f" \ + ${lib.getExe ffmpeg} -nostdin -i "$f" \ -filter:a "atempo=$SPEED" \ -ar 22050 -ac 1 -c:a libmp3lame -b:a 32k \ -f segment -segment_time 300 \ diff --git a/packages/mushakkil.nix b/packages/mushakkil.nix index 0c53d61..12c7ee9 100644 --- a/packages/mushakkil.nix +++ b/packages/mushakkil.nix @@ -1,13 +1,14 @@ # Add Arabic diacritics (tashkeel) to text via alsharekh.org { + lib, writers, curl, jq, }: writers.writeDashBin "mushakkil" '' - ${curl}/bin/curl -sSL 'https://diac.alsharekh.org/Diac/DiacText' \ + ${lib.getExe curl} -sSL 'https://diac.alsharekh.org/Diac/DiacText' \ -H "Content-Type: application/json" \ - --data-raw "$(${jq}/bin/jq --raw-input '{word: ., type: 1}')" \ + --data-raw "$(${lib.getExe jq} --raw-input '{word: ., type: 1}')" \ --compressed \ - | ${jq}/bin/jq -r .diacWord + | ${lib.getExe jq} -r .diacWord '' diff --git a/packages/nix-haddock-index.nix b/packages/nix-haddock-index.nix index 98c562e..8556cf9 100644 --- a/packages/nix-haddock-index.nix +++ b/packages/nix-haddock-index.nix @@ -1,20 +1,20 @@ # Generate a Haddock index page for all packages visible to the current GHC { + lib, writers, coreutils, gnugrep, gnused, graphviz, - bash, }: writers.writeBashBin "nix-haddock-index" '' set -efux if test -z "''${NIX_GHC-}"; then - NIX_GHC=$(${coreutils}/bin/readlink -f "$(type -P ghc)") + NIX_GHC=$(${lib.getExe' coreutils "readlink"} -f "$(type -P ghc)") fi - if ! echo $NIX_GHC | ${gnugrep}/bin/grep -q '^/nix/store/'; then + if ! echo $NIX_GHC | ${lib.getExe gnugrep} -q '^/nix/store/'; then printf '%s: error: unsupported GHC executable path (not in Nix store): %q\n' \ "$0" \ "$NIX_GHC" \ @@ -22,11 +22,11 @@ writers.writeBashBin "nix-haddock-index" '' exit 1 fi - NIX_GHC_PREFIX=$(${coreutils}/bin/dirname "$(${coreutils}/bin/dirname "$NIX_GHC")") + NIX_GHC_PREFIX=$(${lib.getExe' coreutils "dirname"} "$(${lib.getExe' coreutils "dirname"} "$NIX_GHC")") NIX_GHC_DOCDIR=$NIX_GHC_PREFIX/share/doc/ghc/html main() { - hash=$(echo $NIX_GHC_PREFIX | ${gnused}/bin/sed -n 's|^/nix/store/\([a-z0-9]\+\).*|\1|p') + hash=$(echo $NIX_GHC_PREFIX | ${lib.getExe gnused} -n 's|^/nix/store/\([a-z0-9]\+\).*|\1|p') title="Haddock index for $NIX_GHC_PREFIX" header=$( @@ -42,7 +42,7 @@ writers.writeBashBin "nix-haddock-index" '' eval "$( echo 'gen_index() {' echo ' html_head' - "$NIX_GHC_PREFIX"/bin/ghc-pkg dump | ${gnused}/bin/sed -n ' + "$NIX_GHC_PREFIX"/bin/ghc-pkg dump | ${lib.getExe gnused} -n ' s/^---$/ reset/p s/^\(name\|version\):\s*\([-A-Za-z0-9_.]\+\)$/ \1=\2/p s/^haddock-html:\s*\([-A-Za-z0-9_./]\+\)$/ haddock_html \1/p @@ -53,7 +53,7 @@ writers.writeBashBin "nix-haddock-index" '' gen_index > $index_file - "$NIX_GHC_PREFIX"/bin/ghc-pkg dot | ${graphviz}/bin/tred | ${graphviz}/bin/dot -Tsvg | ${gnused}/bin/sed ' + "$NIX_GHC_PREFIX"/bin/ghc-pkg dot | ${lib.getExe' graphviz "tred"} | ${lib.getExe' graphviz "dot"} -Tsvg | ${lib.getExe gnused} ' s/ $svg_file diff --git a/packages/pdf-ocr.nix b/packages/pdf-ocr.nix index d6448f8..676f901 100644 --- a/packages/pdf-ocr.nix +++ b/packages/pdf-ocr.nix @@ -1,5 +1,6 @@ # OCR a PDF file to text using tesseract { + lib, writers, poppler_utils, tesseract, @@ -8,21 +9,21 @@ writers.writeDashBin "pdf-ocr" '' set -efu - pdf_path="$(${coreutils}/bin/realpath "$1")" + pdf_path="$(${lib.getExe' coreutils "realpath"} "$1")" [ -f "$pdf_path" ] || { echo "Usage: pdf-ocr FILE.pdf" >&2 exit 1 } - tmpdir="$(${coreutils}/bin/mktemp -d)" + tmpdir="$(${lib.getExe' coreutils "mktemp"} -d)" trap 'rm -rf $tmpdir' EXIT cd "$tmpdir" - ${poppler_utils}/bin/pdftoppm -png "$pdf_path" pdf-ocr + ${lib.getExe' poppler_utils "pdftoppm"} -png "$pdf_path" pdf-ocr for png in pdf-ocr*.png; do - ${tesseract}/bin/tesseract "$png" "$png.txt" 2>/dev/null + ${lib.getExe tesseract} "$png" "$png.txt" 2>/dev/null done cat pdf-ocr-*.txt diff --git a/packages/readme.nix b/packages/readme.nix index b69ac46..9c5fbcf 100644 --- a/packages/readme.nix +++ b/packages/readme.nix @@ -1,12 +1,13 @@ # Render a GitHub repo's README.md as a man page { + lib, writers, curl, pandoc, man, }: writers.writeDashBin "readme" '' - ${curl}/bin/curl -sSL "https://raw.githubusercontent.com/$*/master/README.md" \ - | ${pandoc}/bin/pandoc -f gfm -t man -s \ - | ${man}/bin/man -l - + ${lib.getExe curl} -sSL "https://raw.githubusercontent.com/$*/master/README.md" \ + | ${lib.getExe pandoc} -f gfm -t man -s \ + | ${lib.getExe man} -l - '' diff --git a/secrets.txt b/secrets.txt index bb2bd7e..e69de29 100644 --- a/secrets.txt +++ b/secrets.txt @@ -1,87 +0,0 @@ -secrets/alertmanager-token-reporters.age -secrets/brevo-key.age -secrets/cifs-credentials-zodiac.age -secrets/copecart-ipn.age -secrets/di-fm-key.age -secrets/email-password-cock.age -secrets/email-password-fysi.age -secrets/email-password-ical-ephemeris.age -secrets/email-password-letos.age -secrets/email-password-meinhak99.age -secrets/email-password-posteo.age -secrets/fatteh-retiolum-privateKey-ed25519.age -secrets/fatteh-retiolum-privateKey-rsa.age -secrets/fatteh-syncthing-cert.age -secrets/fatteh-syncthing-key.age -secrets/fatteh-wireguard-aether-key.age -secrets/fatteh-wireguard-aether-psk.age -secrets/ful-retiolum-privateKey-ed25519.age -secrets/ful-retiolum-privateKey-rsa.age -secrets/ful-root.age -secrets/fu-sftp-key.age -secrets/gemini-api-key.age -secrets/github-token-i3status-rust.age -secrets/grafana-password-admin.age -secrets/hetzner-storagebox-credentials.age -secrets/home-assistant-token.age -secrets/kabsa-retiolum-privateKey-ed25519.age -secrets/kabsa-retiolum-privateKey-rsa.age -secrets/kabsa-syncthing-cert.age -secrets/kabsa-syncthing-key.age -secrets/kabsa-wireguard-aether-key.age -secrets/kabsa-wireguard-aether-psk.age -secrets/kfm-password.age -secrets/kibbeh-retiolum-privateKey-ed25519.age -secrets/kibbeh-retiolum-privateKey-rsa.age -secrets/kibbeh-syncthing-cert.age -secrets/kibbeh-syncthing-key.age -secrets/ledger-basicAuth.age -secrets/makanek-retiolum-privateKey-ed25519.age -secrets/makanek-retiolum-privateKey-rsa.age -secrets/manakish-retiolum-privateKey-ed25519.age -secrets/manakish-retiolum-privateKey-rsa.age -secrets/manakish-syncthing-cert.age -secrets/manakish-syncthing-key.age -secrets/manakish-wireguard-aether-key.age -secrets/manakish-wireguard-aether-psk.age -secrets/mastodon-token-celan.age -secrets/mastodon-token-hesychius.age -secrets/mastodon-token-nietzsche.age -secrets/mastodon-token-smyth.age -secrets/mastodon-token-tlgwotd.age -secrets/mastodon-token-transits.age -secrets/matrix-token-lakai.age -secrets/matrix-token-lakai-env.age -secrets/maxmind-license-key.age -secrets/mega-password.age -secrets/miniflux-api-token.age -secrets/miniflux-credentials.age -secrets/nextcloud-password-admin.age -secrets/nextcloud-password-database.age -secrets/nextcloud-password-fysi.age -secrets/nextcloud-password-kieran.age -secrets/onlyoffice-jwt-key.age -secrets/openweathermap-api-key.age -secrets/restic.age -secrets/secrets.nix -secrets/spotify-password.age -secrets/spotify-username.age -secrets/stw-berlin-card-code.age -secrets/tabula-retiolum-privateKey-ed25519.age -secrets/tabula-retiolum-privateKey-rsa.age -secrets/tahina-retiolum-privateKey-ed25519.age -secrets/tahina-retiolum-privateKey-rsa.age -secrets/telegram-token-betacode.age -secrets/telegram-token-kmein.age -secrets/telegram-token-menstruation.age -secrets/telegram-token-nachtischsatan.age -secrets/telegram-token-proverb.age -secrets/telegram-token-reverse.age -secrets/telegram-token-streaming-link.age -secrets/weechat-sec.conf.age -secrets/wifi.age -secrets/zaatar-moodle-dl-basicAuth.age -secrets/zaatar-moodle-dl-tokens.json.age -secrets/zaatar-retiolum-privateKey-ed25519.age -secrets/zaatar-retiolum-privateKey-rsa.age -secrets/zaatar-ympd-basicAuth.age