1
0
mirror of https://github.com/kmein/niveum synced 2026-03-18 11:01:07 +01:00

134 Commits

Author SHA1 Message Date
6bceb298ad update 2026-03-17 21:06:14 +01:00
df3d15355a ferdium 2026-03-17 21:06:06 +01:00
696ed782b9 update secrets 2026-03-17 21:06:00 +01:00
d3d6a413e6 pi: use from @lassulus 2026-03-17 21:01:30 +01:00
b9a222855e pi: update plugins 2026-03-04 17:59:51 +01:00
f8bb3c04bf pdf-ocr: fix 2026-03-04 17:59:51 +01:00
dce42c7e80 mp3player-write: do not check disk space 2026-03-04 17:59:51 +01:00
5bedd897c9 switch manakish and kabsa 2026-03-04 17:59:51 +01:00
d952ecf17a meteora: host on ful 2026-03-04 17:59:51 +01:00
df36954fed kpaste: reenable 2026-03-04 17:59:51 +01:00
697100f85f cyberlocker-tools: reenable 2026-03-04 17:59:51 +01:00
8eccb752dc getty: always enable autologinOnce 2026-03-04 17:59:51 +01:00
6bb16ff6ed Revert "cuda: build ollama"
This reverts commit fb86f8c7f7.
2026-03-04 17:59:51 +01:00
8fe9e80522 panoptikon: use from new repo 2026-03-04 17:59:51 +01:00
314848d877 update secrets 2026-02-21 16:26:55 +01:00
377b338979 disable zram 2026-02-21 16:26:48 +01:00
26231912cf opencrow: use new agent 2026-02-21 16:26:36 +01:00
a5532f1e9d panoptikon: use from new repo 2026-02-21 16:26:19 +01:00
d878b73ab5 hyprland: use more niphas tools 2026-02-21 16:25:21 +01:00
3216cd19f5 openclaw: rip 2026-02-18 18:19:20 +01:00
14494ca1f7 wip: fix makanek deploy 2026-02-18 18:18:08 +01:00
201e9e5f60 opencrow 2026-02-18 18:17:45 +01:00
2b59d2a68e opencrow: open up 2026-02-17 23:08:26 +01:00
722b1e9d14 add opencrow Matrix bot on ful
Uses upstream NixOS module (systemd-nspawn container with sandboxing).

- User: @fable:4d2.org on matrix.4d2.org
- Provider: GitHub Copilot (OAuth, one-time interactive login)
- pkgs.pi added via extraPackages (available on PATH inside container)
- Secrets via agenix: matrix token as environmentFile,
  soul bind-mounted into the container
- Sessions + pi-agent state in /var/lib/opencrow, backed up via restic

To complete setup:
1. Create secrets/opencrow-matrix-token.age (OPENCROW_MATRIX_ACCESS_TOKEN=...)
2. Create secrets/opencrow-soul.age (SOUL.md content)
3. One-time Copilot login inside the container:
   sudo nixos-container root-login opencrow
   PI_CODING_AGENT_DIR=/var/lib/opencrow/pi-agent pi
   # Run /login, select GitHub Copilot, complete OAuth flow
2026-02-17 22:37:16 +01:00
bfbe2da850 openclaw: soften the hardening 2026-02-17 22:30:38 +01:00
c34647a800 pi llm 2026-02-17 22:30:38 +01:00
e5c86818d9 nextcloud: upgrade 2026-02-17 22:28:09 +01:00
e885753c7f weechat: run in screen 2026-02-17 22:28:09 +01:00
87e39cc30b aerc: use correct cock port 2026-02-17 22:28:09 +01:00
b46f06a462 add opencrow Matrix bot on ful
Uses upstream NixOS module (systemd-nspawn container with sandboxing).

- User: @fable:4d2.org on matrix.4d2.org
- Provider: GitHub Copilot (OAuth, one-time interactive login)
- Secrets via agenix: matrix token as environmentFile,
  soul bind-mounted into the container
- Sessions + pi-agent state in /var/lib/opencrow, backed up via restic

To complete setup:
1. Create secrets/opencrow-matrix-token.age (OPENCROW_MATRIX_ACCESS_TOKEN=...)
2. Create secrets/opencrow-soul.age (SOUL.md content)
3. One-time Copilot login inside the container:
   sudo nixos-container root-login opencrow
   PI_CODING_AGENT_DIR=/var/lib/opencrow/pi-agent pi
   # Run /login, select GitHub Copilot, complete OAuth flow
2026-02-17 22:25:42 +01:00
9041e4cb11 restore secrets.txt
Accidentally emptied by a previous 'git add -A' in a working tree
where the secrets submodule was not initialized.
2026-02-17 21:55:24 +01:00
6d2acd2e3c fix zaatar build: move printer groups to configs/default.nix
printing.nix can't conditionally set users.users.me.extraGroups —
any mention of users.users.me in the module system creates the user
entry and triggers the isNormalUser/isSystemUser assertion on machines
without a 'me' user (like zaatar).

Move lp/scanner groups to configs/default.nix where users.users.me is
defined. On zaatar, root gets lp/scanner groups directly.
2026-02-17 21:50:21 +01:00
ca6157a4f0 remove dead modules/retiolum.nix
This was an old copy of the krebs retiolum module with NIX_PATH lookups
(<retiolum/hosts>, <system-secrets/...>). It was never imported — the
upstream retiolum.nixosModules.retiolum from the flake input is used
instead (in profiles.default), with configs/retiolum.nix overriding
the key paths to agenix secrets.
2026-02-17 21:39:11 +01:00
6550c1c077 replace niveum-* aliases with direct niphas-* references
- configs/i3.nix: niveum-terminal → niphas-terminal, etc.
- configs/graphical/home-manager.nix: same
- configs/default.nix: same
- flake.nix: remove the three overlay aliases
2026-02-17 21:37:47 +01:00
6fe970ae3a update AGENTS.md with current state
- Remove resolved issues (broken refs, orphaned packages, dead code)
- Add coding conventions section (lib.getExe, writer patterns)
- Fix machine table (kibbeh/zaatar/tabula/tahina profiles are correct now)
- Trim improvement ideas to remaining items only
2026-02-17 21:36:09 +01:00
e67d6d7df2 use lib.getExe and lib.getExe' in packaged scripts
Replace all ${pkg}/bin/name patterns with:
- lib.getExe pkg (for main executables: curl, jq, gnused, ffmpeg, etc.)
- lib.getExe' pkg "name" (for specific binaries: coreutils, util-linux, etc.)
2026-02-17 21:35:28 +01:00
4fc29ff0fe package .bin/ scripts as proper nix packages, delete .bin/
Packaged 14 scripts from .bin/ into packages/ with proper dependency
declarations (writers.writeDashBin/writeBashBin/writePython3Bin):
- 256color → two56color (terminal color chart)
- avesta.sed → avesta (Avestan transliteration)
- bvg.sh → bvg (Berlin transit disruptions)
- unicode → charinfo (Unicode character info)
- chunk-pdf → chunk-pdf (split PDFs by page count)
- csv2json → csv2json (CSV to JSON converter)
- fix-sd.sh → fix-sd (exFAT SD card recovery, improved output handling)
- json2csv → json2csv (JSON to CSV converter)
- mp3player-write → mp3player-write (audio conversion for MP3 players)
- mushakkil.sh → mushakkil (Arabic diacritization)
- nix-haddock-index → nix-haddock-index (GHC Haddock index generator)
- pdf-ocr.sh → pdf-ocr (OCR PDFs via tesseract)
- prospekte.sh → prospekte (German supermarket flyer browser)
- readme → readme (GitHub README as man page)

All added to overlay and packages output. .bin/ directory removed.
2026-02-17 21:32:10 +01:00
dbbad1e146 delete obsolete scripts from .bin/
Removed 27 scripts that are dead, obsolete, or no longer relevant:
- work-specific: elm-publish-private, watson2fdf.sh
- hardcoded creds/sessions: libib.sh, ttrss-unread
- broken/bitrotted: proxies.sh, dummy-alert, playlist_entries.sh, screencap.sh
- trivial/unused: toposort.nix, tuesday-1800, mud.sh, load.sh, calendars.sh
- no longer used: anki-poem.sh, browser, candyman, horoscope.sh, lieferando.sh,
  space.py, notetags.sh, sample-pdf.sh, lit.awk, countdown, json2csv.jq
- dead mail tooling: mail-current-part, mail-current-query-find-part-by-*

Remaining scripts will be packaged properly.
2026-02-17 21:25:40 +01:00
36132b0454 fix broken references to deleted files, remove dead code
Build-breaking fixes:
- kibbeh: remove imports of deleted admin-essentials, nix, zsh configs
  (all provided by niphas via profiles.default + profiles.desktop)
- tabula, tahina: remove imports of deleted admin-essentials, nix configs
  (provided by niphas via profiles.default)
- zaatar: remove import of deleted tmux config
  (provided by niphas via profiles.default)

Dead code removal:
- flake.nix: remove nixosModules.zsh-kmein (referenced deleted config/zsh.nix)
- flake.nix: remove unused wallpapers input
- packages/gpt.nix, hora.nix, k-lock.nix: orphaned, not in overlay or referenced
- configs/hledger.nix: remove hora reference (package deleted)
2026-02-17 21:10:27 +01:00
3bebe25adb remove duplicates already provided by niphas
- Delete configs/bash.nix (identical to niphas, was dead code)
- Delete configs/direnv.nix (dead code, niphas provides direnv)
- Delete packages/vimv.nix (identical to niphas)
- Remove vimv from overlay and packages output
- Alias niveum-terminal/browser/filemanager to niphas equivalents
- Remove 17 duplicate packages from configs/packages.nix
- Remove nil from configs/editor.nix (niphas provides it)
- Remove dead dmenu packageOverride from configs/default.nix
2026-02-17 20:53:52 +01:00
21029d3bbc openclaw: add backups 2026-02-15 22:39:47 +01:00
d8bad81090 openclaw: give it a browser to play with 2026-02-15 22:36:29 +01:00
f12beaa69e picoclaw 2026-02-15 22:14:20 +01:00
a94dacb64c openclaw 2026-02-15 22:13:26 +01:00
fb86f8c7f7 cuda: build ollama 2026-02-15 16:47:29 +01:00
86b5e4da9f radio-news: use newer gemini model 2026-02-15 16:47:29 +01:00
15ab8ac8a8 autologin: fix module use 2026-02-15 16:47:29 +01:00
f202be220b manakish: fix imports 2026-02-15 16:47:29 +01:00
267124dfd1 format 2026-02-15 16:47:29 +01:00
ca05785b26 yt-dlp-master 2026-02-15 16:47:29 +01:00
f1610d08dc mpv: configure with wrappers 2026-02-15 16:47:29 +01:00
9aaaaff724 lix: try out 2026-02-15 16:47:29 +01:00
c6a11c1d79 hold overlays correctly 2026-02-10 22:02:34 +01:00
8c6363881d niphas: update 2026-02-07 16:40:45 +01:00
01019fffac printing: enable scanning 2026-02-07 16:40:35 +01:00
84f1a2688f ensure ashell from unstable 2026-02-06 17:13:14 +01:00
d4cfb63a11 editor: enable copilot and colorscheme 2026-02-06 17:12:57 +01:00
b038278af3 use shared config from niphas 2026-02-04 17:07:52 +01:00
e264f13885 zsh: export config as module 2026-02-03 16:42:47 +01:00
b90cec1a73 update 2026-01-31 17:48:00 +01:00
8e47deb2ab remove legacy displaymanager settings 2026-01-31 15:45:07 +01:00
f883d0ce6f hyprland: fix configure Amo monitor 2026-01-31 14:51:04 +01:00
7aef7e7cf6 hyprland: configure Amo monitor 2026-01-27 09:00:53 +01:00
7d82e284cd applicative: fix config 2026-01-27 09:00:36 +01:00
e99103226d deploy scripts: use substitutes 2026-01-25 13:48:12 +01:00
8a0bf14e4e mp3player-write: turn into potato quality 2026-01-25 13:48:03 +01:00
91a650953a wetter 2026-01-25 13:47:49 +01:00
eae1a7a71b applicative: limit to fatteh 2026-01-25 13:47:28 +01:00
16f8cfbf4c applicative: enable auto-login if not present 2026-01-25 13:46:48 +01:00
e24fdaedf3 mp3player-write: default to length 3 prefix 2026-01-21 07:01:33 +01:00
09b28ce523 exodus 2026-01-20 18:02:39 +01:00
25f1a2ac1e update 2026-01-20 18:02:28 +01:00
db05a76863 waydroid 2026-01-20 18:02:06 +01:00
3155b8f2a5 let other users access The Good Music 2026-01-12 06:30:07 +01:00
3d59940948 hyprland: add some more rice 2026-01-10 11:57:26 +01:00
f373accdd5 hyprland: more sensible keybind for togglesplit 2026-01-10 07:44:22 +01:00
6e25f42def mako: timeout after 10 seconds 2026-01-10 07:13:02 +01:00
ff1b274d5e dawn-editor 2026-01-10 07:13:02 +01:00
7bdf78df40 hyprland: left-align all monitors 2026-01-10 07:12:37 +01:00
3c461efc41 cuda: enable opengl 2026-01-10 07:12:24 +01:00
34a7b6f905 hyprland: localisation 2026-01-10 07:12:13 +01:00
1e736dbfaa regreet: deduplicate libinput code 2026-01-09 12:39:21 +01:00
ab3404b356 ruff 2026-01-09 12:38:57 +01:00
a21583b199 stylix: decrease terminal size 2026-01-09 12:38:51 +01:00
a5db2944c6 hyprland: resize more courageously 2026-01-09 12:38:32 +01:00
98e95b1475 mpv: remove visualizer 2026-01-09 12:38:11 +01:00
8a9e8bf06a hyprland: defancy 2026-01-09 12:37:58 +01:00
e0b904b87a hyprland: disable touchscreen, position Samsung monitor correctly 2026-01-09 12:37:31 +01:00
b4c838d65d git: add pushf alias 2026-01-09 12:37:02 +01:00
028b282d0c dunst: remove 2026-01-09 12:36:55 +01:00
58d355e682 work profile 2026-01-09 12:36:46 +01:00
4701080f28 fatteh: enable cuda 2026-01-09 12:36:13 +01:00
cecc249daa move to wayland 2026-01-06 22:46:12 +01:00
3d9a48c65e hyprland 2026-01-04 14:30:06 +01:00
ad7fc115c6 himalaya: fix config and add neovim wrapper 2026-01-04 12:36:51 +01:00
c93806909f machines: add internal and tor 2026-01-03 11:41:44 +01:00
1ce21c9bcd update 2026-01-03 10:10:15 +01:00
ebd017cd20 tlp: disable 2026-01-03 10:10:05 +01:00
187d7ec12b remove more fysi 2026-01-03 10:09:48 +01:00
c05422c8e4 docker: remove 2026-01-02 21:50:00 +01:00
f0ec0e99c3 autoUpgrade all 2026-01-02 21:43:52 +01:00
9f806822a4 applicative user 2026-01-02 17:05:01 +01:00
d47de27423 wallabag: run on podman, autoupdate 2026-01-02 06:32:22 +01:00
fc4b32dd24 update 2026-01-02 06:21:48 +01:00
27be00fd34 machines: add zaatar local IP 2026-01-01 10:29:30 +01:00
35f309e4b4 dawn editor 2026-01-01 10:29:07 +01:00
6d931c589f kabsa, fatteh: add internal IP 2025-12-30 21:28:01 +01:00
8ab1ec895f kabsa: add tor address 2025-12-30 20:20:52 +01:00
8d1ec7b1ef streams: add byte fm 2025-12-30 19:45:57 +01:00
65ced40c4c gimp: fix 2025-12-29 23:18:01 +01:00
b4f8503c16 use more lib.getExe 2025-12-29 21:05:02 +01:00
30e54f5e4e comma 2025-12-29 17:56:07 +01:00
e5d2bda7ad clean up flake.lock 2025-12-29 17:54:39 +01:00
98e9083763 nix-topology 2025-12-29 16:31:56 +01:00
ea61c3024a flake: remove empty lib 2025-12-29 16:21:49 +01:00
c5379bf926 nixos-hardware 2025-12-29 16:21:35 +01:00
31a6cb384e i3: remove old keybinds 2025-12-29 16:20:26 +01:00
fdff04c94b format 2025-12-29 15:26:13 +01:00
69e752bb6b flake: document ControlPath=none 2025-12-29 15:23:53 +01:00
be0a9620a4 niveum-ssh: install 2025-12-29 13:35:17 +01:00
afb621a98e try-connect: check localhost first 2025-12-29 13:32:13 +01:00
6259075f40 try-connect: use for deploy scripts 2025-12-29 13:17:42 +01:00
f70383c732 tor: enable ssh 2025-12-29 12:27:40 +01:00
c3dc7b9e51 unify profiles 2025-12-29 12:22:30 +01:00
4188968ee1 pun-sort 2025-12-28 22:34:42 +01:00
6a873fb764 writeHaskellBin: no need for readfile 2025-12-28 13:54:56 +01:00
bd92b75278 nixos-rebuild-ng 2025-12-28 13:50:45 +01:00
c15f5375e2 format 2025-12-28 13:39:42 +01:00
51533efeda use treefmt-nix 2025-12-28 13:39:36 +01:00
977e733ace vim-typewriter: fix 2025-12-28 13:29:27 +01:00
29571bce10 remove specialArgs inputs 2025-12-28 13:23:49 +01:00
ab895d9f7b systems -> machines 2025-12-28 12:49:10 +01:00
2d6294e44b ditch nixinate 2025-12-28 12:40:45 +01:00
c33cbe3817 update old system code 2025-12-28 12:05:59 +01:00
176 changed files with 4049 additions and 4647 deletions

View File

@@ -1,38 +0,0 @@
#! /bin/sh
set -euf
pl() {
for i in $(seq $1 $(expr $2 - 1)); do
printf '\e[38;5;%sm%03i\e[m ' $i $i
done
printf '\e[38;5;%sm%03i\e[m\n' $2 $2
}
p() {
printf '\e[38;5;%sm%03i\e[m ' $1 $1
}
pn() {
printf '\e[38;5;%sm%03i\e[m\n' $1 $1
}
p6x6() {
for i in $(seq 0 5); do
for j in $(seq 0 5); do
p $(expr $1 + $i + $j \* 6)
done
echo
done
}
pl 0 7
pl 8 15
p6x6 16
p6x6 52
p6x6 88
p6x6 124
p6x6 160
p6x6 196
pl 232 243
pl 244 255

View File

@@ -1,29 +0,0 @@
#!/bin/sh
file="${1?please supply a poetry file}"
[ -f "$file" ] || {
echo "'$file' is no file"
exit 1
}
poem="$(mktemp)"
clean () {
rm "$poem"
}
trap clean EXIT
sed '/^$/d' "$file" > "$poem"
htmlize() {
awk 'ORS="<br/>"' \
| head -c -5 # remove final <br/> characters
}
for line_number in $(seq 1 "$(wc -l "$poem" | cut -d' ' -f1)"); do
if [ "$line_number" -gt 3 ] && [ "$line_number" -gt 1 ]; then
sed -n "$((line_number - 3)),$((line_number - 1))p" "$poem"
else
sed -n "1,$((line_number - 1))p" "$poem"
fi | htmlize
printf '\t'
sed -n "${line_number},+1p" "$poem" | htmlize
printf '\n'
done

View File

@@ -1,54 +0,0 @@
#!/usr/bin/env -S sed -f
s/ā̊/𐬃/g
s//𐬝/g
s/ṣ̌/𐬴/g
s/š́/𐬳/g
s/ą̄/𐬅/g
s/ŋᵛ/𐬤/g
s/ə̄/𐬇/g
s/ŋ́/𐬣/g
s//𐬒/g
s/xᵛ/𐬓/g
s/a/𐬀/g
s/ā/𐬁/g
s/å/𐬂/g
s/ą/𐬄/g
s/ə/𐬆/g
s/e/𐬈/g
s/ē/𐬉/g
s/o/𐬊/g
s/ō/𐬋/g
s/i/𐬌/g
s/ī/𐬍/g
s/u/𐬎/g
s/ū/𐬏/g
s/k/𐬐/g
s/x/𐬑/g
s/g/𐬔/g
s/ġ/𐬕/g
s/γ/𐬖/g
s/c/𐬗/g
s/j/𐬘/g
s/t/𐬙/g
s/θ/𐬚/g
s/d/𐬛/g
s/δ/𐬜/g
s/p/𐬞/g
s/f/𐬟/g
s/b/𐬠/g
s/β/𐬡/g
s/ŋ/𐬢/g
s/n/𐬥/g
s/ń/𐬦/g
s//𐬧/g
s/m/𐬨/g
s//𐬩/g
s//𐬫/g
s/y/𐬪/g
s/v/𐬬/g
s/r/𐬭/g
s/s/𐬯/g
s/z/𐬰/g
s/š/𐬱/g
s/ž/𐬲/g
s/h/𐬵/g

View File

@@ -1,24 +0,0 @@
#!/bin/sh -e
#
# Usage: browser
# pipe html to a browser
# e.g.
# $ echo '<h1>hi mom!</h1>' | browser
# $ ron -5 man/rip.5.ron | browser
if [ -t 0 ]; then
if [ -n "$1" ]; then
open $1
else
cat <<usage
Usage: browser
pipe html to a browser
$ echo '<h1>hi mom!</h1>' | browser
$ ron -5 man/rip.5.ron | browser
usage
fi
else
f="/tmp/browser.$RANDOM.html"
cat /dev/stdin > $f
xdg-open $f
fi

View File

@@ -1,46 +0,0 @@
#!/bin/sh
interesting="U6 N6 140 M46 184 N84"
curl -sSL 'https://www.bvg.de/disruption-reports/q' \
--data-raw '{"variables":{},"query":"{
allDisruptions {
disruptions {
meldungsId
linie
verkehrsmittel
__typename
... on Traffic {
datum
gueltigVonDatum
gueltigVonZeit
gueltigBisDatum
gueltigBisZeit
richtungName
richtungHafasId
beginnAbschnittName
beginnAbschnittHafasId
endeAbschnittName
endeAbschnittHafasId
textIntUrsache
sev
textIntAuswirkung
umfahrung
textWAPSMSUrsache
textWAPSMSAuswirkung
prioritaet
__typename
}
}
__typename
}
}"}' \
| jq --arg interesting "$interesting" '
.data.allDisruptions.disruptions
| map(select(
(.linie as $linie
| $interesting
| split(" ")
| index($linie))
and (.["__typename"] == "Traffic")
))
'

View File

@@ -1,19 +0,0 @@
#!/bin/sh
directory="$(mktemp -d)"
trap clean EXIT
clean() {
rm -rf "$directory"
}
year=$(date +%Y)
output=/tmp/$year.pdf
for month in $(seq 1 12); do
printf "\r%d" "$month" 1>&2
astrolog -zN Berlin -qm "$month" "$year" -X -K -XA -Xr -Xm -Xb -Xo "$(printf "%s/%02d.bmp" "$directory" "$month")" -Xw 1080 720 2>/dev/null
done
printf "\r"
convert "$directory/*.bmp" "$output"
echo "$output"

View File

@@ -1,25 +0,0 @@
#!/bin/sh
set -efu
usage() {
echo >&2 "$0 add-{reddit,telegram,youtube,twitch,twitter} NAME"
exit 1
}
candyman() {
curl -fsSv http://news.r/api -H content-type:application/json -d "$(jq -n "
{
command: \"PRIVMSG\",
params: [\"#all\", \"candyman: $1 $2\"]
}
")"
}
[ $# -ge 2 ] || usage
case "$1" in
add-reddit|add-telegram|add-youtube|add-twitter|add-twitch)
candyman "$@"
;;
*) usage;;
esac

View File

@@ -1,23 +0,0 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p pdftk gnugrep
set -efu
INPUT_FILE="${2:?Pass the PDF path as second argument.}"
PAGES_PER_REPORT="${1:?Pass the chunk size as first argument.}"
if [ ! -f "$INPUT_FILE" ]; then
echo >&2 "File $INPUT_FILE does not exist."
exit 1
fi
TOTAL_PAGES="$(pdftk "$INPUT_FILE" dump_data | grep NumberOfPages | cut -f2 -d' ')"
RUNS=$((TOTAL_PAGES/PAGES_PER_REPORT))
for run in $(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 "$INPUT_FILE" cat "$start_page-$end_page" output "$output_file"
done

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env -S awk -f
function z() {
getline < "/proc/uptime"
close("/proc/uptime")
return $0
}
BEGIN {
x = z()
while (1) {
y = z()
printf "%02d:%05.2f\r", (y - x) / 60, (y - x) % 60
}
}

View File

@@ -1,14 +0,0 @@
#!/usr/bin/env python3
import csv
import json
import sys
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--delimiter", "-d", default=",", help="CSV field separator")
args = parser.parse_args()
if __name__ == "__main__":
json.dump(list(csv.DictReader(sys.stdin, delimiter=args.delimiter)), sys.stdout)

View File

@@ -1,43 +0,0 @@
#!/bin/bash
name=$RANDOM
url='http://localhost:9093/api/v1/alerts'
echo "firing up alert $name"
# change url o
curl -XPOST $url -d "[{
\"status\": \"firing\",
\"labels\": {
\"alertname\": \"$name\",
\"service\": \"my-service\",
\"severity\":\"warning\",
\"instance\": \"$name.example.net\"
},
\"annotations\": {
\"summary\": \"High latency is high!\"
},
\"generatorURL\": \"http://prometheus.int.example.net/<generating_expression>\"
}]"
echo ""
echo "press enter to resolve alert"
read
echo "sending resolve"
curl -XPOST $url -d "[{
\"status\": \"resolved\",
\"labels\": {
\"alertname\": \"$name\",
\"service\": \"my-service\",
\"severity\":\"warning\",
\"instance\": \"$name.example.net\"
},
\"annotations\": {
\"summary\": \"High latency is high!\"
},
\"generatorURL\": \"http://prometheus.int.example.net/<generating_expression>\"
}]"
echo ""

View File

@@ -1,7 +0,0 @@
#! /usr/bin/env nix-shell
#! nix-shell -p "(import <nixpkgs> { overlays = [ (import ~/work/fysiweb/engiadina-pwa/devops/pkgs) ]; }).elm-publish-private"
#! nix-shell -i bash
set -efux
exec elm-publish-private "$@"

View File

@@ -1,21 +0,0 @@
#!/bin/sh
set -xfu
drive="$1"
mountpoint="/media/sd-card-$(date +%s)"
backup_directory="$(pwd)"
trap clean EXIT
clean() {
umount "$mountpoint"
rmdir "$mountpoint"
fsck.exfat "$drive"
}
filenames="$(fsck.exfat "$drive" 2>&1 | sed -nE "s/.* file '(.*?)' is not allocated.*/\1/p")"
mkdir "$mountpoint"
mount "$drive" "$mountpoint"
echo "$filenames" | while read -r filename; do
find "$mountpoint" -type f -name "$filename" -exec mv {} "$backup_directory" \;
done

View File

@@ -1,34 +0,0 @@
#!/bin/sh
set -efu
# Berlin: -d lodeg=13 -d lomin=22 -d losec=41 -d lodir=E -d ladeg=52 -d lamin=27 -d lasec=42 -d ladir=N -d usecoords=1 \
# Kassel: -d lodeg=9 -d lomin=32 -d losec=5 -d lodir=E -d ladeg=51 -d lamin=18 -d lasec=17 -d ladir=N -d usecoords=1 \
[ $# -eq 1 ] || {
echo >&2 Usage: "$0" TIMESTAMP
exit 1
}
export TZ=UTC
chart_path="$(mktemp /tmp/chart_XXX.pdf)"
timestamp="$1"
year="$(date -d "@$timestamp" +%Y)"
month="$(date -d "@$timestamp" +%m)"
day="$(date -d "@$timestamp" +%d)"
hour="$(date -d "@$timestamp" +%H)"
minute="$(date -d "@$timestamp" +%M)"
curl -sSL 'https://edifyingfellowship.org/astro/' \
-d lodeg=9 -d lomin=32 -d losec=5 -d lodir=E -d ladeg=51 -d lamin=18 -d lasec=17 -d ladir=N -d usecoords=1 \
-d ybyr="$year" -d ybmo="$month" -d ybdy="$day" -d ybhr="$hour" -d ybmi="$minute" -d ybsc=0 -d ybtz="$TZ" \
-d currenttime=0 \
-d title="$timestamp" \
-d options[]=VancouverWheel -d options[]=Arrow -d options[]=XBold -d options[]=HouseLabels -d options[]=Placidus \
-d options[]=Sun -d options[]=Moon -d options[]=Mercury -d options[]=Venus -d options[]=Mars -d options[]=Jupiter -d options[]=Saturn -d options[]=Uranus -d options[]=Neptune -d options[]=Pluto -d options[]=Ascendant -d options[]=MC -d options[]=Lilith -d options[]=MeanNode -d options[]=TrueNode \
-d aspectpct=100 -d format=PDF -d Submit= -o "$chart_path"
zathura "$chart_path"

View File

@@ -1,24 +0,0 @@
#!/usr/bin/env python3
import csv
import json
import sys
if __name__ == "__main__":
json_list = json.load(sys.stdin)
if not isinstance(json_list, list):
print("JSON object is not a list.", file=sys.stderr)
sys.exit(1)
if len(json_list) == 0:
print("JSON list is empty.", file=sys.stderr)
sys.exit(1)
keys = set()
for element in json_list:
if isinstance(element, dict):
keys |= element.keys()
else:
print("Non-dict element:", element, file=sys.stderr)
sys.exit(1)
writer = csv.DictWriter(sys.stdout, fieldnames=list(keys))
writer.writeheader()
for element in json_list:
writer.writerow(element)

View File

@@ -1,5 +0,0 @@
#!/usr/bin/env -S jq -r -f
(map(keys) | add | unique) as $cols
| map(. as $row | $cols | map($row[.])) as $rows
| $cols, $rows[]
| @csv

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env bash
session_id=7b638c194d9bda74f80043045018cc9e
declare -A libraries
libraries["Literatur"]=344428
libraries["Sprache"]=344160
libraries["Miscellanea"]=344427
libraries["Wissenschaft"]=344429
libraries["Relicta"]=565920
for library in ${!libraries[@]}
do
curl -sSL 'https://www.libib.com/library/functions/csv-export.php' -H "Cookie: PHPSESSID=$session_id" -d export="${libraries[$library]}" > "$library.csv"
done

View File

@@ -1,81 +0,0 @@
#!/bin/sh
set -efu
if echo "$1" | grep -Eq '[[:digit:]]{5}'; then
PLZ="$1"
else
echo >&2 "Usage: $0 PLZ"
exit 1
fi
lieferando_dir=/tmp/lieferando
mkdir -p "$lieferando_dir/$PLZ"
fetch_restaurants() {
cache_path="$lieferando_dir/$PLZ.json"
if [ -r "$cache_path" ]; then
cat "$cache_path"
else
w3m -dump_source "http://www.lieferando.de/$PLZ" \
| gunzip \
| sed -n '/var restaurants/,/];$/p' \
| sed 's/var restaurants =//;$s/;$//' \
| prettier --parser=json \
| jq '
map({
name: .[30] | .name,
category: .[30] |.categories | split(", "),
url: "http://lieferando.de\(.[30] | .url)",
minutes: .[19],
minimum: .[10],
delivery: .[14]
})' \
| tee "$cache_path"
fi
}
fetch_menu() {
[ $# -eq 1 ] || exit 1
slug="$(echo "$1" | sed 's!.*/!!')"
cache_path="$lieferando_dir/$PLZ/$slug.json"
if [ -r "$cache_path" ]; then
cat "$cache_path"
else
w3m -dump_source "$1" \
| gunzip \
| sed -n '/var MenucardProducts/,/\];/p' \
| sed 's/var MenucardProducts =//;s/;$//' \
| jq -r '
unique_by(.productId)
| group_by(.categoryId)
| flatten
' \
| tee "$cache_path"
fi
}
data="$(fetch_restaurants)"
# echo "$data" | jq -c '.[]' | while read -r restaurant; do
# fetch_menu "$(echo "$restaurant" | jq -r .url)"
# done
selected_categories="$(echo "$data" | jq -r 'map(.category) | flatten | unique | .[]' | fzf -m)"
selected_restaurant_url="$(echo "$selected_categories" | jq --argjson restaurants "$data" -sRr '
split("\n")[:-1] as $categories
| $restaurants[]
| select(.category - $categories != .category)
| "\(.name) [🚴\(.minutes)min 💰\(.minimum)€ + \(.delivery)€] (\(.url))"
' \
| fzf \
| sed 's/.*(//;s/)$//'
)"
fetch_menu "$selected_restaurant_url" \
| jq -r '.[] | "\(.price)\t\(.name)"' \
| fzf -m \
| awk '{print $0; sum += $1} END {print "-----"; print sum}'

View File

@@ -1,17 +0,0 @@
BEGIN {
if (!comment) comment = "--";
if (!begin) begin = "\\begin{code}";
if (!end) end = "\\end{code}";
}
{
if ($0 == begin) {
code = 1;
print comment, $0;
} else if ($0 == end) {
code = 0;
print comment, $0;
} else {
if (code) print $0;
else print comment, $0;
}
}

View File

@@ -1,3 +0,0 @@
#! /bin/sh
set -efu
exec curl -fSs --unix-socket /tmp/much.api.sock http://localhost/current/part

View File

@@ -1,27 +0,0 @@
#! /bin/sh
# usage: mail-current-query-find-part-by-name NAME
set -efu
name=$1
query=$(mail-current-query)
result=$(notmuch show --entire-thread=false --format=json "$query")
part_id=$(printf %s "$result" | jq --arg name "$name" '
[
recurse |
select(type == "object") |
{ id, name: .filename } |
select(.id != null and .name != null)
] |
map(select(.name == $name))[0].id
')
if test "$part_id" = null; then
printf 'error: could not find part with name %s\n' \
"$name" \
>&2
exit 1
fi
exec notmuch show --part="$part_id" "$query"

View File

@@ -1,39 +0,0 @@
#! /bin/sh
# usage: mail-current-query-find-part-by-type TYPE
set -efu
type=$1
query=$(mail-current-query)
result=$(notmuch show --entire-thread=false --format=json "$query")
part_id=$(printf %s "$result" | jq --arg type "$type" '
#flatten|map(select(.!=null))[0].body[0] |
#
#if .["content-type"] == $type then
# .id
#elif .["content-type"] | test("^multipart/") then
# .content|map(select(.["content-type"]==$type))[0].id
#else
# null
#end
[
recurse |
select(type == "object") |
{ id, type: .["content-type"] } |
select(.id != null and .type != null)
] |
map(select(.type == $type))[0].id
')
if test "$part_id" = null; then
printf 'error: could not find part with type %s\n' \
"$type" \
>&2
exit 1
fi
exec notmuch show --part="$part_id" "$query"

View File

@@ -1,114 +0,0 @@
#!/usr/bin/env bash
# Usage:
# ./mp3_transfer.sh -s 1.3 /mnt/mp3player file1.m4a file2.m4a ...
set -e
# Default speed
SPEED=1.0
# Parse options
while getopts ":s:" opt; do
case $opt in
s)
SPEED=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires a value." >&2
exit 1
;;
esac
done
# Shift past the options
shift $((OPTIND -1))
# Check arguments
if [ "$#" -lt 2 ]; then
echo "Usage: $0 [-s speed] MOUNT_POINT FILE1 [FILE2 ...]"
exit 1
fi
MOUNT_POINT=$1
shift
FILES=("$@")
# Check mount point exists
if [ ! -d "$MOUNT_POINT" ]; then
echo "Error: Mount point '$MOUNT_POINT' does not exist."
exit 1
fi
# Estimate required space
TOTAL_SIZE=0
for f in "${FILES[@]}"; do
if [ ! -f "$f" ]; then
echo "Warning: File '$f' does not exist, skipping."
continue
fi
# Get file size in bytes
FILE_SIZE=$(stat --printf="%s" "$f")
# Estimate mp3 output size: roughly 1/2 of original m4a (adjust if needed)
TOTAL_SIZE=$((TOTAL_SIZE + FILE_SIZE / 2))
done
# Get available space in bytes
AVAILABLE=$(df --output=avail "$MOUNT_POINT" | tail -n 1)
AVAILABLE=$((AVAILABLE * 1024)) # df reports in KB
if [ "$TOTAL_SIZE" -gt "$AVAILABLE" ]; then
echo "Error: Not enough space on device. Required: $TOTAL_SIZE bytes, Available: $AVAILABLE bytes"
exit 1
fi
echo "Enough space available. Starting conversion..."
sanitize_filename() {
local name="$1"
# Remove path, keep only base name
name=$(basename "$name" .m4a)
# Replace spaces and special chars with underscore
name=$(echo "$name" | tr ' ' '_' | tr -cd '[:alnum:]_-')
# Truncate to max 50 chars
echo "${name:0:50}"
}
# Convert and copy files
for f in "${FILES[@]}"; do
if [ ! -f "$f" ]; then
continue
fi
# Determine the next prefix
existing_prefixes=$(ls "$MOUNT_POINT" | grep -E '^[0-9].*\.mp3$' | sed -E 's/^([0-9]).*/\1/' | sort -n | uniq)
for i in {0..9}; do
if ! echo "$existing_prefixes" | grep -q "^$i$"; then
PREFIX=$i
break
fi
done
echo "Using prefix: $PREFIX"
BASENAME=$(sanitize_filename "$f")
OUT_PATTERN="$MOUNT_POINT/${PREFIX}%02d_${BASENAME}.mp3"
echo "Converting '$f' to '$OUT_PATTERN' at speed $SPEED..."
ffmpeg -i "$f" \
-filter:a "atempo=$SPEED" -ar 44100 -ac 2 -c:a libmp3lame -b:a 128k \
-f segment -segment_time 300 \
"$OUT_PATTERN"
# Update prefix for next file
# Count how many segments were created
SEG_COUNT=$(ls "$MOUNT_POINT" | grep -E "^${PREFIX}[0-9]{2}_" | wc -l)
PREFIX=$((PREFIX + SEG_COUNT))
done
echo "All files processed successfully."

View File

@@ -1 +0,0 @@
ssh mud@hotdog.r -t "MUD_NICKNAME=$LOGNAME mud"

View File

@@ -1,6 +0,0 @@
#!/bin/sh
curl -sSL 'https://diac.alsharekh.org/Diac/DiacText' \
-H "Content-Type: application/json" \
--data-raw "$(jq --raw-input '{word: ., type: 1}')" \
--compressed \
| jq -r .diacWord

View File

@@ -1,93 +0,0 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p coreutils gnugrep gnused graphviz
#
# usage: nix-haddock-index
#
# Run this script in an environment where either NIX_GHC is set, or the ghc
# executable exists, to generate an HTML index file pointing to all Haddock
# files accessible to the respective ghc version.
#
# Additionally, an SVG dependency graph of all packages is linked at the
# bottom of the index file.
#
# Note: all files will be generated in /tmp, and won't be deleted automatically
#
set -efux
if test -z "${NIX_GHC-}"; then
NIX_GHC=$(readlink -f "$(type -P ghc)")
fi
if ! echo $NIX_GHC | grep -q '^/nix/store/'; then
printf '%s: error: unsupported GHC executable path (not in Nix store): %q\n' \
"$0" \
"$NIX_GHC" \
>&2
exit -1
fi
NIX_GHC_PREFIX=$(dirname "$(dirname "$NIX_GHC")")
NIX_GHC_DOCDIR=$NIX_GHC_PREFIX/share/doc/ghc/html
main() {
hash=$(echo $NIX_GHC_PREFIX | sed -n 's|^/nix/store/\([a-z0-9]\+\).*|\1|p')
title="Haddock index for $NIX_GHC_PREFIX"
header=$(
printf 'Haddock index for <a href="%s">%s</a>\n' \
$NIX_GHC_PREFIX \
$NIX_GHC_PREFIX \
)
suffix=${hash:+-$hash}
index_file=/tmp/haddock$suffix-index.html
svg_file=/tmp/haddock$suffix.svg
#if ! test -e $index_file; then
eval "$(
echo 'gen_index() {'
echo ' html_head'
"$NIX_GHC_PREFIX"/bin/ghc-pkg dump | sed -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
'
echo ' html_foot'
echo '}'
)"
gen_index > $index_file
#fi
#if ! test -e $svg_file; then
"$NIX_GHC_PREFIX"/bin/ghc-pkg dot | tred | dot -Tsvg | sed '
s/<svg width="[0-9]\+pt" height="[0-9]\+pt"/<svg width="3600px" height="100%"/
' > $svg_file
#fi
echo $index_file
}
reset() {
unset name version
}
haddock_html() {
printf '<li>'
printf '<a href="%s/index.html">%s</a>' "$1" "$name-$version"
printf '</li>\n'
}
html_head() {
printf '<!doctype html>\n'
printf '<title>%s</title>\n' "$title"
printf '<link href="%s" rel="stylesheet" type="text/css">\n' \
"$NIX_GHC_DOCDIR/libraries/ocean.css"
printf '<h1>%s</h1>\n' "$header"
printf '<ul>\n'
}
html_foot() {
printf '</ul>\n'
printf '<a href="%s">graph</a>\n' "$svg_file"
}
main "$@"

View File

@@ -1,15 +0,0 @@
#!/bin/sh
# inspired by https://github.com/connermcd/bin/blob/1d38cb98812906d8b95dc6e51e1149e29261617d/notetags
cd "$HOME/notes/" || exit
[ -f tags ] && rm tags
grep -r 'tags:' ./* | while read -r line; do
file=$(echo "$line" | cut -d: -f1)
unparsed_tags=$(echo "$line" | cut -d: -f3) #
tags=$(echo "$unparsed_tags" | sed -e 's/tags: *//g' -e 's/[][,]//g')
for tag in $tags; do
echo "$tag $file /^$unparsed_tags$/;" >> tags
done
done

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p poppler_utils tesseract4
set -eu
pdf_path="$(realpath "$1")"
[ -f "$pdf_path" ] || {
echo "Usage: $0 FILE.pdf" >&2
exit 1
}
tmpdir="$(mktemp -d)"
trap 'rm -rf $tmpdir' EXIT
cd "$tmpdir"
pdftoppm -png "$pdf_path" pdf-ocr
for png in pdf-ocr*.png; do
tesseract "$png" "$png.txt" 2>/dev/null
done
cat pdf-ocr-*.txt

View File

@@ -1,2 +0,0 @@
#!/bin/sh
youtube-dl -ij "$*" | jq -sr '.[] | .webpage_url'

View File

@@ -1,65 +0,0 @@
#!/bin/sh
lidl() {
echo LIDL
curl -sSL 'https://endpoints.lidl-flyer.com/v3/region-overview/lidl/de-DE/0.json' \
| jq -r '
.categories
| map(select(.name == "Filial-Angebote") | .subcategories | map(.flyers))
| flatten
| flatten
| .[]
| .pdfUrl
'
}
aldi_nord() {
echo ALDI nord
echo 'https://magazine.aldi-nord.de/aldi-nord/aldi-aktuell/GetPDF.ashx'
echo 'https://magazine.aldi-nord.de/aldi-nord/aldi-vorschau/GetPDF.ashx'
}
rewe_berlin() {(
store_id=662366923
publisher_id=1062
echo REWE
curl -sSL 'https://www.bonialserviceswidget.de/de/stores/'$store_id'/brochures?storeId='$store_id'&publisherId='$publisher_id | while read -r brochure_id; do
curl -sSL 'https://www.bonialserviceswidget.de/de/v5/brochureDetails/'"$brochure_id"'?publisherId='$publisher_id | jq -r .pdfUrl
done
)}
kaufland() {(
region_code=8920
echo KAUFLAND
curl -sSL https://filiale.kaufland.de/prospekte.html | htmlq --attribute href '.flyer a' | grep -Eo 'DE_de_KDZ[^/]*' | sed "s/_3000_/_${region_code}_/" | while read -r flyer_id; do
curl -sSL "https://endpoints.leaflets.kaufland.com/v3/$flyer_id/flyer.json?regionCode=$region_code" | jq -r .flyer.pdfUrl
done
)}
netto_schwarz() {
echo 'NETTO (schwarz)'
curl -sSL 'https://squid-api.tjek.com/v2/catalogs?dealer_ids=90f2VL&order_by=created' \
| jq -r '.[] | .id' \
| while read -r flyer_id; do
curl -sSL "https://squid-api.tjek.com/v2/catalogs/$flyer_id/download" \
| jq -r .pdf_url
done
}
dir="$(mktemp -d)"
trap clean EXIT
clean() {
rm -rf "$dir"
}
prospekt_url="$( (
lidl
aldi_nord
rewe_berlin
kaufland
netto_schwarz
) | fzf)"
curl -sSL "$prospekt_url" -o "$dir/prospekt.pdf"
zathura "$dir/prospekt.pdf"

View File

@@ -1,17 +0,0 @@
#!/bin/sh
curl -sSL https://www.netzwelt.de/proxy/index.html \
| pup ".tblc" \
| xml-to-json /dev/stdin \
| jq '
.div.table.tbody.tr
| map(
.td
| {
ip: .[0].a.value,
port: .[1],
country: .[2] | (if type == "string" then . else .a.value end),
security: .[3],
protocol: .[4]
}
)
'

View File

@@ -1,4 +0,0 @@
#!/bin/sh
curl -sSL "https://raw.githubusercontent.com/$*/master/README.md" \
| pandoc -f gfm -t man -s \
| man -l -

View File

@@ -1,6 +0,0 @@
#!/bin/sh
filepath="$(shuf --head-count=1)"
pages="$(pdfinfo "$filepath" | awk '/^Pages:/{print $2}')"
random_page="$(shuf --input-range="1-$pages" --head-count=1)"
zathura --page="$random_page" "$filepath"

View File

@@ -1,16 +0,0 @@
#! /usr/bin/env nix-shell
#! nix-shell -i sh -p coreutils byzanz xorg.xwininfo gnused
# shellcheck shell=sh
# ref https://gist.github.com/aforemny/0994cb7f06ea30d56c8b9681ff5d2054
set -eux
eval "$(xwininfo | \
sed -n -e 's/^ \+Absolute upper-left X: \+\([0-9]\+\).*/x=\1/p' \
-e 's/^ \+Absolute upper-left Y: \+\([0-9]\+\).*/y=\1/p' \
-e 's/^ \+Width: \+\([0-9]\+\).*/w=\1/p' \
-e 's/^ \+Height: \+\([0-9]\+\).*/h=\1/p')"
trap "pkill -f 'sleep 360d'" INT
byzanz-record -e "sleep 360d" -c -x $x -y $y -w $w -h $h "$@"

View File

@@ -1,49 +0,0 @@
import ephem
from datetime import datetime, date, timedelta
now = datetime.now()
limit = now + timedelta(days=365)
def events_until(limit):
initial_date = ephem.Date(datetime.now())
events = {}
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_full_moon(now)
events[now] = "🌕"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_new_moon(now)
events[now] = "🌑"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_vernal_equinox(now)
events[now] = "spring equinox"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_autumnal_equinox(now)
events[now] = "fall equinox"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_winter_solstice(now)
events[now] = "winter solstice"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_summer_solstice(now)
events[now] = "summer solstice"
return events
events = events_until(limit)
for date, event in sorted(events.items(), key=lambda x: x[0]):
if ephem.localtime(date) < limit:
print(ephem.localtime(date), event)

View File

@@ -1,81 +0,0 @@
let
lib = import <nixpkgs/lib>;
in
rec {
inherit lib;
input = [
{
x = [
"pool"
"zfs"
];
y = [
"mdadm"
"raid1"
];
}
{
x = [
"pool"
"zfs"
];
y = [
"disk"
"sda"
];
}
{
x = [
"mdadm"
"raid1"
];
y = [
"disk"
"sdb"
];
}
{
x = [
"mdadm"
"raid1"
];
y = [
"disk"
"sdc"
];
}
];
outNodes = node: graph: lib.unique (builtins.map (e: e.y) (builtins.filter (v: v.x == node) graph));
vertices = graph: lib.unique (builtins.map (x: x.y) graph ++ builtins.map (x: x.x) graph);
deleteVertex = node: graph: (builtins.filter (v: v.x != node && v.y != node) graph);
findSink =
graph:
lib.findFirst (v: outNodes v graph == [ ]) (lib.trace graph (builtins.abort "No sink found")) (
vertices graph
);
topSort =
graph:
if graph == [ ] then
[ ]
else if builtins.length graph == 1 then
let
only = builtins.head graph;
in
[
only.y
only.x
]
else
let
sink = findSink graph;
in
[ sink ] ++ topSort (deleteVertex sink graph);
output = topSort input;
}

View File

@@ -1,18 +0,0 @@
#/usr/bin/env -S deno run -A:q
set -x
session_cache="$HOME/.cache/tt-rss.session"
ttrss_endpoint=https://feed.kmein.de/api/
ttrss_user=k
ttrss_password=$(pass shared/tt-rss/password)
login() {
if [ -f "$session_cache" ]; then
session_id="$(cat "$session_cache")"
else
session_id="$(curl -d '{"op":"login","user":"'"$ttrss_user"'","password":"'"$ttrss_password"'"}' "$ttrss_endpoint" | jq -r .content.session_id)"
echo "$session_id" > "$session_cache"
fi
}
login
curl -d '{"sid":"'"$session_id"'","op":"getUnread"}' "$ttrss_endpoint" | jq .content

View File

@@ -1,16 +0,0 @@
#!/bin/sh
set -efux
expected_max_results=1024 # the upper bound on the number of restaurants
radius=250
echo '[out:json];node(id:260050809)->.cbase;
(
node(around.cbase:'$radius')[amenity=fast_food];
node(around.cbase:'$radius')[amenity=restaurant];
);out;' \
| curl -sSL -d @- -X POST http://overpass-api.de/api/interpreter \
| jq --argjson random "$(shuf -i 0-$expected_max_results -n 1)" '
.elements
| length as $length
| .[$random % $length]
'

View File

@@ -1,8 +0,0 @@
import sys
import unicodedata
for index, character in enumerate(sys.stdin.read().strip()):
try:
print(index, character, hex(ord(character)), unicodedata.category(character), unicodedata.name(character))
except:
print(index, character, hex(ord(character)))

View File

@@ -1,26 +0,0 @@
project=Filli
year=2022
for month in Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec; do
from="$(date +%F -d "$month 1, $year")"
to="$(date +%F -d "$month 1, $year + 1 month")"
watson report --json --from "$from" --to "$to" --project "$project"
done | jq --slurp '
def in_array($arr):
. as $value | any($arr[]; . == $value);
map(
["engadin-app","fysiweb","val-muestair","mia-engiadina","ol"] as $official_projects
| (.timespan.from | .[0:7]) as $timespan
| .projects | .[0]
| .time as $total_time
| .tags
| select(. != null)
| map(select(.name | in_array($official_projects)))
| (map(.time)|add) as $official_time
| map({key:.name, value:.time}) | from_entries
| .other |= ($total_time - $official_time)
| map_values(. / (60*60) | ceil)
| .month |= $timespan
)
'

View File

@@ -2,7 +2,7 @@ name: Update flake.lock
on: on:
workflow_dispatch: # allows manual triggering workflow_dispatch: # allows manual triggering
schedule: schedule:
- cron: '0 0 * * 0' # runs weekly on Sunday at 00:00 - cron: "0 0 * * 0" # runs weekly on Sunday at 00:00
jobs: jobs:
lockfile: lockfile:

View File

@@ -7,33 +7,33 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
system: [makanek,manakish,kabsa,zaatar,ful,fatteh] system: [makanek, manakish, kabsa, zaatar, ful, fatteh]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install QEMU (ARM) - name: Install QEMU (ARM)
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y qemu-user-static sudo apt-get install -y qemu-user-static
if: ${{ matrix.system == 'ful' }} if: ${{ matrix.system == 'ful' }}
- name: Install Nix (ARM) - name: Install Nix (ARM)
uses: cachix/install-nix-action@v16 uses: cachix/install-nix-action@v16
if: ${{ matrix.system == 'ful' }} if: ${{ matrix.system == 'ful' }}
with: with:
extra_nix_config: | extra_nix_config: |
system = aarch64-linux system = aarch64-linux
- name: Install Nix (x86_64) - name: Install Nix (x86_64)
uses: cachix/install-nix-action@v16 uses: cachix/install-nix-action@v16
if: ${{ matrix.system != 'ful' }} if: ${{ matrix.system != 'ful' }}
- name: nixos-rebuild dry-build - name: nixos-rebuild dry-build
run: | run: |
# remove secrets: ref https://stackoverflow.com/questions/1260748/how-do-i-remove-a-submodule/36593218 # remove secrets: ref https://stackoverflow.com/questions/1260748/how-do-i-remove-a-submodule/36593218
git submodule deinit -f secrets git submodule deinit -f secrets
rm -rf .git/modules/secrets rm -rf .git/modules/secrets
git rm -f secrets git rm -f secrets
# recreate secrets # recreate secrets
mkdir secrets mkdir secrets
cat secrets.txt | while read -r path; do touch $path; done cat secrets.txt | while read -r path; do touch $path; done
git add secrets git add secrets
nix run nixpkgs#nixos-rebuild -- dry-build --flake $GITHUB_WORKSPACE#${{matrix.system}} nix run nixpkgs#nixos-rebuild -- dry-build --flake $GITHUB_WORKSPACE#${{matrix.system}}

96
AGENTS.md Normal file
View File

@@ -0,0 +1,96 @@
# niveum — Agent Notes
## What This Is
A NixOS flake managing ~9 machines (desktops, servers, family laptops) for one user (kmein/kfm).
Levantine food-themed hostnames: fatteh, kabsa, kibbeh, makanek, manakish, tabula, tahina, zaatar, ful.
## Repository Structure
```
flake.nix # ~670 lines — inputs, overlay, nixosConfigurations, apps, packages output
configs/ # ~50 NixOS config fragments imported by systems
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)
packages.nix # ~250 lines of environment.systemPackages
bots/ # Telegram/Mastodon/Matrix bot configs
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/ # ~107 package files (scripts, wrappers, small tools)
systems/<name>/ # 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)
```
## Key Relationships
- **niphas** (input): Provides shared "how I like things" config — nixosModules (shell, editor, git, desktop, nix, udiskie) and overlay (niphas-* packages). Used in `profiles.default` and `profiles.desktop`.
- **configs/default.nix**: The "big desktop profile" — imported by fatteh, kabsa, manakish (the main desktop machines). NOT imported by servers or family laptops.
- **profiles** (in flake.nix): `profiles.default`, `profiles.desktop`, `profiles.server` — lists of modules composed per machine.
- **lib.niveum**: Custom lib injected via overlay (`pkgs.lib.niveum`) — used everywhere for machine addresses, SSH port, helper functions.
## Coding Conventions
- Packages use `writers.writeDashBin`, `writers.writeBashBin`, or `writers.writePython3Bin`
- Dependencies are referenced via `lib.getExe pkg` (main executable) or `lib.getExe' pkg "name"` (specific binary)
- For packages needing many commands via PATH, use `lib.makeBinPath` instead (see `packages/prospekte.nix`)
- Overlay entries use `prev.callPackage packages/foo.nix { }` pattern
- Packages are exported via `inherit (pkgs) ...` in the `packages` output
## Known Bugs / Broken References
All previously broken references have been fixed (see commits `36132b04`, `e67d6d7d`).
Remaining issues:
- `modules/retiolum.nix` uses `<retiolum/hosts>` and `<system-secrets/...>` NIX_PATH lookups — breaks flake purity but works with current `NIX_PATH` setup
## Architectural Issues
### 1. configs/default.nix is a grab-bag (200+ lines, ~15 inline anonymous modules)
It's a list of `imports` mixing inline `{ ... }` blocks with file imports. Hard to find what's defined where.
### 2. Retiolum secret boilerplate repeated 9 times
Every system has a near-identical block:
```nix
age.secrets.retiolum-rsa = { file = ../../secrets/${hostname}-retiolum-privateKey-rsa.age; mode = "400"; owner = "tinc-retiolum"; ... };
age.secrets.retiolum-ed25519 = { ... same ... };
```
Could be a function or module parameterized by hostname.
### 3. Nginx + ACME boilerplate duplicated
ful and makanek have identical nginx recommended settings + ACME config.
### 4. niveum-* overlay aliases
`niveum-terminal`, `niveum-browser`, `niveum-filemanager` are aliases to niphas equivalents. Could be removed by updating ~6 references in configs/ to use niphas-* names directly.
### 5. The `pkgs.lib.niveum` pattern
Custom lib injected via overlay into `pkgs.lib`. Unconventional — only available where overlay is applied. A `specialArgs` approach or standalone lib would be cleaner.
### 6. Restic backup config scattered
`services.restic.backups.niveum` is configured in configs/backup.nix, configs/applicative.nix, and extended in 5+ system files. Hard to see what a given machine backs up.
### 7. configs/ vs modules/ distinction blurry
`configs/` has both stateless config fragments (spacetime.nix = timezone) and stateful ones (backup.nix, cloud.nix). `modules/` has proper option-declaring modules. Some configs/ files import from modules/.
## Machines Overview
| Machine | Role | Profile | Arch | Notes |
|-----------|--------------|------------------|---------|---------------------------------------|
| fatteh | Desktop | default+desktop | x86_64 | ThinkPad T480, CUDA, main daily |
| kabsa | Desktop | default+desktop | x86_64 | ThinkPad X220, constrained (2 jobs) |
| manakish | Desktop | default+desktop | x86_64 | ThinkPad X230 |
| kibbeh | Desktop | default+desktop | x86_64 | Pantheon DE, travel laptop |
| ful | Server | default+server | aarch64 | Oracle/Hetzner, nginx, web services |
| makanek | Server | default+server | x86_64 | Hetzner, gitea, nextcloud, weechat |
| zaatar | Server/Home | default+server | x86_64 | Home assistant, backup server |
| tabula | Family laptop| default | x86_64 | LXQt, user "xenos" |
| tahina | Family laptop| default | x86_64 | Pantheon, user "xenos", German |
## Remaining Improvement Ideas
1. **Extract retiolum secret boilerplate** into a function/module
2. **Break up configs/default.nix** into proper named files
3. **Extract nginx+ACME server profile**
4. **Replace niveum-* aliases** with direct niphas-* references
5. **Fix modules/retiolum.nix** NIX_PATH usage for flake purity

View File

@@ -5,13 +5,14 @@
> [nĭvĕus](https://logeion.uchicago.edu/niveus), a, um, adj. [nix], _of_ or _from snow, snowy, snow-_ (poet.) > [nĭvĕus](https://logeion.uchicago.edu/niveus), a, um, adj. [nix], _of_ or _from snow, snowy, snow-_ (poet.)
> >
> 1. Lit.: aggeribus niveis informis, Verg. G. 3, 354: aqua, _cooled with snow_, Mart. 12, 17, 6; cf. id. 14, 104 and 117: mons, _covered with snow_, Cat. 64, 240.— > 1. Lit.: aggeribus niveis informis, Verg. G. 3, 354: aqua, _cooled with snow_, Mart. 12, 17, 6; cf. id. 14, 104 and 117: mons, _covered with snow_, Cat. 64, 240.—
>
> 2. Transf., _snow-white, snowy_ (mostly poet.): a similitudine sic: Corpore niveum candorem, aspectu igneum ardorem assequebatur, Auct. Her. 4, 33, 44: lacerti, Verg. A. 8, 387: lac, id. E. 2, 20: hanc si capite niveae agnae exorari judicas, Sen. Q. N. 2, 36: Briseis niveo colore, Hor. C. 2, 4, 3: vestis, Ov. M. 10, 432: candidior nivei folio, Galatea, ligustri, id. ib. 13, 789: dens, id. H. 18, 18: quā notam duxit niveus videri, Hor. C. 4, 2, 59: panis, Juv. 5, 70: flumen, _clear, pellucid_, Sen. Hippol. 504: undae, Mart. 7, 32, 11: tribuni, _clothed in white togas_, Calp. Ecl. 7, 29; so, Quirites, Juv. 10, 45. > 2. Transf., _snow-white, snowy_ (mostly poet.): a similitudine sic: Corpore niveum candorem, aspectu igneum ardorem assequebatur, Auct. Her. 4, 33, 44: lacerti, Verg. A. 8, 387: lac, id. E. 2, 20: hanc si capite niveae agnae exorari judicas, Sen. Q. N. 2, 36: Briseis niveo colore, Hor. C. 2, 4, 3: vestis, Ov. M. 10, 432: candidior nivei folio, Galatea, ligustri, id. ib. 13, 789: dens, id. H. 18, 18: quā notam duxit niveus videri, Hor. C. 4, 2, 59: panis, Juv. 5, 70: flumen, _clear, pellucid_, Sen. Hippol. 504: undae, Mart. 7, 32, 11: tribuni, _clothed in white togas_, Calp. Ecl. 7, 29; so, Quirites, Juv. 10, 45.
## Pressestimmen ## Pressestimmen
> das ist ja pure poesie —[riotbib](https://github.com/riotbib/) > das ist ja pure poesie —[riotbib](https://github.com/riotbib/)
> Deine Configs sind wunderschön <3 —[flxai](https://github.com/flxai/) > Deine Configs sind wunderschön <3 —[flxai](https://github.com/flxai/)
## To do ## To do
- [ ] get rid of `nixinate`
🦗

View File

@@ -1,127 +0,0 @@
{
pkgs,
lib,
...
}:
let
darwin = lib.strings.hasSuffix "-darwin" pkgs.stdenv.hostPlatform.system;
in
{
environment.systemPackages = [
pkgs.htop
pkgs.w3m
pkgs.wget
# ARCHIVE TOOLS
pkgs.unzip
pkgs.unrar
pkgs.p7zip
pkgs.sshuttle
pkgs.zip
# MONITORS
pkgs.iftop # interface bandwidth monitor
pkgs.lsof # list open files
# SHELL
pkgs.sqlite
pkgs.fd # better find
pkgs.tree
pkgs.parallel # for parallel, since moreutils shadows task spooler
pkgs.ripgrep # better grep
pkgs.rlwrap
pkgs.progress # display progress bars for pipes
pkgs.file # determine file type
pkgs.gdu # ncurses disk usage (ncdu is broken)
pkgs.rmlint # remove duplicate files
pkgs.jq # json toolkit
pkgs.jless # less(1) for json
pkgs.fq # toolkit for yaml, xml and binaries
pkgs.bc # calculator
pkgs.pari # gp -- better calculator
pkgs.ts
pkgs.vimv
pkgs.vg
pkgs.fkill
pkgs.cyberlocker-tools
pkgs.untilport
pkgs.kpaste
# HARDWARE
pkgs.pciutils # for lspci
]
++ lib.optionals (!darwin) [
pkgs.usbutils # for lsusb
pkgs.lshw # for lshw
pkgs.iotop # I/O load monitor
pkgs.psmisc # for killall, pstree
];
security.wrappers = {
pmount = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pmount}/bin/pmount";
};
pumount = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pmount}/bin/pumount";
};
};
environment.interactiveShellInit = ''
# Use XDG_RUNTIME_DIR for temporary files if available
if [ -d "$XDG_RUNTIME_DIR" ]; then
export TMPDIR="$XDG_RUNTIME_DIR"
fi
'';
environment.shellAliases =
let
take = pkgs.writers.writeDash "take" ''
mkdir "$1" && cd "$1"
'';
cdt = pkgs.writers.writeDash "cdt" ''
cd $(mktemp -p "$XDG_RUNTIME_DIR" -d "cdt-XXXXXX")
pwd
'';
wcd = pkgs.writers.writeDash "wcd" ''
cd "$(readlink "$(${pkgs.which}/bin/which --skip-alias "$1")" | xargs dirname)/.."
'';
where = pkgs.writers.writeDash "where" ''
readlink "$(${pkgs.which}/bin/which --skip-alias "$1")" | xargs dirname
'';
in
{
nixi = "nix repl nixpkgs";
take = "source ${take}";
wcd = "source ${wcd}";
where = "source ${where}";
# temporary files and directories
cdt = "source ${cdt}";
vit = "$EDITOR $(mktemp)";
# file safety
mv = "${pkgs.coreutils}/bin/mv --interactive";
rm = "${pkgs.coreutils}/bin/rm --interactive";
cp = "${pkgs.coreutils}/bin/cp --interactive";
# colours
cat = "${pkgs.bat}/bin/bat --theme=ansi --style=plain";
l = "${pkgs.coreutils}/bin/ls --color=auto --time-style=long-iso --almost-all";
ls = "${pkgs.coreutils}/bin/ls --color=auto --time-style=long-iso";
ll = "${pkgs.coreutils}/bin/ls --color=auto --time-style=long-iso -l";
la = "${pkgs.coreutils}/bin/ls --color=auto --time-style=long-iso --almost-all -l";
}
// (
if darwin then
{ }
else
{
"ß" = "${pkgs.util-linux}/bin/setsid";
ip = "${pkgs.iproute2}/bin/ip -c";
# systemd
s = "${pkgs.systemd}/bin/systemctl";
us = "${pkgs.systemd}/bin/systemctl --user";
j = "${pkgs.systemd}/bin/journalctl";
uj = "${pkgs.systemd}/bin/journalctl --user";
}
);
}

View File

@@ -91,7 +91,7 @@
imap.host = mailhost; imap.host = mailhost;
imap.port = 993; imap.port = 993;
smtp.host = mailhost; smtp.host = mailhost;
smtp.port = 25; smtp.port = 587;
smtp.tls.useStartTls = true; smtp.tls.useStartTls = true;
}; };
ical-ephemeris = ical-ephemeris =
@@ -128,7 +128,6 @@
passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-posteo.path}"; passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-posteo.path}";
himalaya = { himalaya = {
enable = true; enable = true;
settings.backend = "imap";
}; };
aerc.extraAccounts.pgp-key-id = "9EDE82CC72A343A95266D0F444857074A3ACC8B7"; aerc.extraAccounts.pgp-key-id = "9EDE82CC72A343A95266D0F444857074A3ACC8B7";
}; };

View File

@@ -1,35 +1,7 @@
{ {
pkgs,
lib,
...
}:
let
in
{
environment.variables.TERMINAL = "alacritty";
home-manager.users.me = { home-manager.users.me = {
programs.alacritty = { programs.alacritty = {
enable = true; enable = true;
settings = {
keyboard.bindings = [
{
key = "Plus";
mods = "Control";
action = "IncreaseFontSize";
}
{
key = "Minus";
mods = "Control";
action = "DecreaseFontSize";
}
{
key = "Key0";
mods = "Control";
action = "ResetFontSize";
}
];
};
}; };
}; };
} }

56
configs/applicative.nix Normal file
View File

@@ -0,0 +1,56 @@
{
config,
pkgs,
lib,
...
}:
{
users.users.applicative = {
name = "asg";
description = "Applicative Systems";
hashedPasswordFile = config.age.secrets.kfm-password.path;
home = "/home/applicative";
uid = 1001;
isNormalUser = true;
extraGroups = [
"pipewire"
"audio"
];
};
nixpkgs.overlays = [
(final: prev: {
niphas-wallpaper = prev.callPackage ../packages/applicative-wallpaper.nix {
inherit (config.lib.stylix) colors;
};
})
];
# to run nspawn in nix sandbox
nix.settings = {
auto-allocate-uids = true;
system-features = [ "uid-range" ];
experimental-features = [
"auto-allocate-uids"
"cgroups"
];
trusted-users = [ config.users.users.applicative.name ];
};
services.restic.backups.niveum = {
extraBackupArgs = [
"--exclude=${config.users.users.applicative.home}/src/nixpkgs/.git"
];
paths = [
config.users.users.applicative.home
];
};
security.sudo.extraRules = [
{
# still required for systemd-nspawn
users = [ config.users.users.applicative.name ];
commands = [ "ALL" ];
}
];
}

View File

@@ -1,10 +0,0 @@
{ pkgs, ... }:
{
programs.bash = {
promptInit = ''PS1="$(${pkgs.ncurses}/bin/tput bold)\w \$([[ \$? == 0 ]] && echo \"\[\033[1;32m\]\" || echo \"\[\033[1;31m\]\")\$$(${pkgs.ncurses}/bin/tput sgr0) "'';
interactiveShellInit = ''
set -o vi
'';
completion.enable = true;
};
}

View File

@@ -1,11 +1,8 @@
{ {
config, config,
inputs, pkgs,
... ...
}: }:
let
autorenkalender = inputs.autorenkalender.packages.x86_64-linux.default;
in
{ {
niveum.bots.autorenkalender = { niveum.bots.autorenkalender = {
enable = true; enable = true;
@@ -16,7 +13,7 @@ in
chatIds = [ "@autorenkalender" ]; chatIds = [ "@autorenkalender" ];
parseMode = "Markdown"; parseMode = "Markdown";
}; };
command = "${autorenkalender}/bin/autorenkalender"; command = "${pkgs.autorenkalender}/bin/autorenkalender";
}; };
niveum.passport.services = [ niveum.passport.services = [

View File

@@ -1,12 +1,9 @@
{ {
config, config,
pkgs, pkgs,
lib,
inputs,
... ...
}: }:
let let
telebots = inputs.telebots.defaultPackage.x86_64-linux;
reverseDirectory = "/run/telegram-reverse"; reverseDirectory = "/run/telegram-reverse";
proverbDirectory = "/run/telegram-proverb"; proverbDirectory = "/run/telegram-proverb";
in in
@@ -72,9 +69,9 @@ in
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
description = "Telegram reverse bot"; description = "Telegram reverse bot";
path = [ pkgs.ffmpeg ]; path = [ pkgs.ffmpeg ];
enable = true; enable = false;
script = '' script = ''
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${telebots}/bin/telegram-reverse TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${pkgs.telebots}/bin/telegram-reverse
''; '';
serviceConfig.Restart = "always"; serviceConfig.Restart = "always";
serviceConfig.WorkingDirectory = reverseDirectory; serviceConfig.WorkingDirectory = reverseDirectory;
@@ -84,9 +81,9 @@ in
systemd.services.telegram-streaming-link = { systemd.services.telegram-streaming-link = {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
description = "Telegram bot converting YouTube Music <-> Spotify"; description = "Telegram bot converting YouTube Music <-> Spotify";
enable = true; enable = false;
script = '' script = ''
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${telebots}/bin/telegram-streaming-link TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${pkgs.telebots}/bin/telegram-streaming-link
''; '';
serviceConfig.Restart = "always"; serviceConfig.Restart = "always";
serviceConfig.LoadCredential = "token:${config.age.secrets.telegram-token-streaming-link.path}"; serviceConfig.LoadCredential = "token:${config.age.secrets.telegram-token-streaming-link.path}";
@@ -95,9 +92,9 @@ in
systemd.services.telegram-betacode = { systemd.services.telegram-betacode = {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
description = "Telegram beta code bot"; description = "Telegram beta code bot";
enable = true; enable = false;
script = '' script = ''
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${telebots}/bin/telegram-betacode TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${pkgs.telebots}/bin/telegram-betacode
''; '';
serviceConfig.Restart = "always"; serviceConfig.Restart = "always";
serviceConfig.LoadCredential = "token:${config.age.secrets.telegram-token-betacode.path}"; serviceConfig.LoadCredential = "token:${config.age.secrets.telegram-token-betacode.path}";
@@ -106,9 +103,9 @@ in
systemd.services.telegram-proverb = { systemd.services.telegram-proverb = {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
description = "Telegram proverb bot"; description = "Telegram proverb bot";
enable = true; enable = false;
script = '' script = ''
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${telebots}/bin/telegram-proverb TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${pkgs.telebots}/bin/telegram-proverb
''; '';
serviceConfig.Restart = "always"; serviceConfig.Restart = "always";
serviceConfig.WorkingDirectory = proverbDirectory; serviceConfig.WorkingDirectory = proverbDirectory;

View File

@@ -1,13 +1,8 @@
{ {
pkgs, pkgs,
config, config,
inputs,
lib,
... ...
}: }:
let
hesychius = inputs.scripts.outPath + "/hesychius/hesychius.txt";
in
{ {
niveum.bots.hesychius = { niveum.bots.hesychius = {
enable = true; enable = true;
@@ -22,7 +17,7 @@ in
tokenFile = config.age.secrets.telegram-token-kmein.path; tokenFile = config.age.secrets.telegram-token-kmein.path;
chatIds = [ "@HesychiosAlexandreus" ]; chatIds = [ "@HesychiosAlexandreus" ];
}; };
command = "${pkgs.coreutils}/bin/shuf -n1 ${hesychius}"; command = "${pkgs.coreutils}/bin/shuf -n1 ${pkgs.hesychius}";
}; };
systemd.timers.bot-hesychius.timerConfig.RandomizedDelaySec = "10h"; systemd.timers.bot-hesychius.timerConfig.RandomizedDelaySec = "10h";

View File

@@ -2,7 +2,6 @@
pkgs, pkgs,
lib, lib,
config, config,
inputs,
... ...
}: }:
let let
@@ -10,8 +9,6 @@ let
in in
{ {
imports = [ imports = [
inputs.self.nixosModules.system-dependent
inputs.self.nixosModules.power-action
{ {
boot.supportedFilesystems = [ "ntfs" ]; boot.supportedFilesystems = [ "ntfs" ];
} }
@@ -19,9 +16,6 @@ in
nixpkgs = { nixpkgs = {
config = { config = {
allowUnfree = true; allowUnfree = true;
packageOverrides = pkgs: {
dmenu = pkgs.writers.writeDashBin "dmenu" ''exec ${pkgs.rofi}/bin/rofi -dmenu "$@"'';
};
permittedInsecurePackages = [ permittedInsecurePackages = [
]; ];
}; };
@@ -37,7 +31,7 @@ in
file = ../secrets/di-fm-key.age; file = ../secrets/di-fm-key.age;
owner = config.users.users.me.name; owner = config.users.users.me.name;
group = config.users.users.me.group; group = config.users.users.me.group;
mode = "400"; mode = "440";
}; };
restic = { restic = {
file = ../secrets/restic.age; file = ../secrets/restic.age;
@@ -72,6 +66,8 @@ in
extraGroups = [ extraGroups = [
"pipewire" "pipewire"
"audio" "audio"
"lp"
"scanner"
]; ];
}; };
@@ -90,14 +86,9 @@ in
swallow = command: "${pkgs.swallow}/bin/swallow ${command}"; swallow = command: "${pkgs.swallow}/bin/swallow ${command}";
in in
{ {
o = "${pkgs.xdg-utils}/bin/xdg-open";
ns = "nix-shell --run zsh";
pbcopy = "${pkgs.xclip}/bin/xclip -selection clipboard -in";
pbpaste = "${pkgs.xclip}/bin/xclip -selection clipboard -out";
tmux = "${pkgs.tmux}/bin/tmux -2";
sxiv = swallow "${pkgs.nsxiv}/bin/nsxiv"; sxiv = swallow "${pkgs.nsxiv}/bin/nsxiv";
zathura = swallow "${pkgs.zathura}/bin/zathura"; zathura = swallow "${pkgs.zathura}/bin/zathura";
im = "${pkgs.openssh}/bin/ssh weechat@makanek -t tmux attach-session -t IM"; im = "${pkgs.openssh}/bin/ssh weechat@makanek -t screen -x weechat";
yt = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata -ic"; # Download video link yt = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata -ic"; # Download video link
yta = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata --audio-format mp3 --audio-quality 0 -xic"; # Download with audio yta = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata --audio-format mp3 --audio-quality 0 -xic"; # Download with audio
}; };
@@ -109,28 +100,7 @@ in
}; };
} }
{ {
services.displayManager = { services.power-profiles-daemon.enable = true;
autoLogin = {
enable = true;
user = config.users.users.me.name;
};
};
services.xserver = {
enable = true;
displayManager.lightdm = {
enable = true;
greeters.gtk = {
enable = true;
indicators = [
"~spacer"
"~host"
"~spacer"
"~session"
"~power"
];
};
};
};
} }
{ {
programs.gnupg = { programs.gnupg = {
@@ -177,57 +147,39 @@ in
home-manager.backupFileExtension = "bak"; home-manager.backupFileExtension = "bak";
} }
{ {
systemd.user.services.udiskie = {
after = [ "udisks2.service" ];
wants = [ "udisks2.service" ];
wantedBy = [ "graphical-session.target" ];
serviceConfig = {
ExecStart = "${pkgs.udiskie}/bin/udiskie --verbose --no-config --notify";
};
};
services.udisks2.enable = true;
programs.dconf.enable = true; programs.dconf.enable = true;
home-manager.users.me = { home-manager.users.me = {
dconf.enable = true; dconf.enable = true;
dconf.settings = { dconf.settings = {
# Change the default terminal for Nemo # Change the default terminal for Nemo
"org/cinnamon/desktop/applications/terminal".exec = lib.getExe pkgs.niveum-terminal; "org/cinnamon/desktop/applications/terminal".exec = lib.getExe pkgs.niphas-terminal;
}; };
}; };
} }
./android.nix ./android.nix
./admin-essentials.nix
./stylix.nix ./stylix.nix
./alacritty.nix ./alacritty.nix
./backup.nix ./backup.nix
./bash.nix
./bluetooth.nix ./bluetooth.nix
./aerc.nix ./aerc.nix
./khal.nix ./khal.nix
./browser.nix ./browser.nix
./clipboard.nix ./clipboard.nix
./cloud.nix ./cloud.nix
./direnv.nix
./docker.nix
./dunst.nix
./fonts.nix ./fonts.nix
./fzf.nix
./git.nix
./hledger.nix ./hledger.nix
./htop.nix ./htop.nix
./lix.nix
./uni.nix ./uni.nix
./i3.nix # ./i3.nix
./i3status-rust.nix ./graphical
./keyboard ./keyboard
./mycelium.nix
./kdeconnect.nix ./kdeconnect.nix
{ services.upower.enable = true; } { services.upower.enable = true; }
./lb.nix ./lb.nix
./mpv.nix ./mpv.nix
./mime.nix ./mime.nix
./neovim.nix ./editor.nix
./nix.nix
./newsboat.nix
./flameshot.nix ./flameshot.nix
./packages.nix ./packages.nix
./virtualization.nix ./virtualization.nix
@@ -235,27 +187,23 @@ in
./polkit.nix ./polkit.nix
./printing.nix ./printing.nix
./redshift.nix ./redshift.nix
./retiolum.nix
./rofi.nix ./rofi.nix
./spacetime.nix
./ssh.nix ./ssh.nix
./sshd.nix
./sound.nix ./sound.nix
./sudo.nix ./sudo.nix
./tmux.nix
./unclutter.nix ./unclutter.nix
./vscode.nix ./vscode.nix
./watson.nix
./wallpaper.nix ./wallpaper.nix
./zsh.nix
{ {
home-manager.users.me.home.file.".zshrc".text = '' home-manager.users.me.home.file.".zshrc".text = ''
# nothing to see here # nothing to see here
''; '';
} }
./tor.nix
./mastodon-bot.nix
{ {
programs.zsh.interactiveShellInit = ''
hash -d nixos=/etc/nixos niveum=${config.users.users.me.home}/sync/src/niveum
'';
home-manager.users.me = { home-manager.users.me = {
xdg.userDirs = xdg.userDirs =
let let

View File

@@ -1,42 +0,0 @@
{ pkgs, ... }:
let
nixify = pkgs.writers.writeDashBin "nixify" ''
set -efuC
if [ ! -e ./.envrc ]; then
echo use_nix > .envrc
direnv allow
fi
if [ ! -e shell.nix ]; then
cat > shell.nix <<'EOF'
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
packages = [];
}
EOF
''${EDITOR:-vim} shell.nix
fi
'';
in
{
environment.systemPackages = [
pkgs.direnv
nixify
];
home-manager.users.me.programs.direnv = {
enable = true;
stdlib = builtins.readFile "${
pkgs.fetchFromGitHub {
owner = "Mic92";
repo = "dotfiles";
rev = "a0a9b7e358fa70a85cd468f8ca1fbb02ae0a91df";
sha256 = "1y9h5s1lf59sczsm0ksq2x1yhl98ba9lwk5yil3q53rg7n4574pg";
}
}/home/.direnvrc";
};
programs.zsh.interactiveShellInit = ''
eval "$(${pkgs.direnv}/bin/direnv hook zsh)"
'';
}

View File

@@ -1,20 +0,0 @@
{
lib,
pkgs,
...
}:
{
virtualisation.docker = {
enable = true;
# for ICE wifi, ref https://gist.github.com/sunsided/7840e89ff4e11b64a2d7503fafa0290c
extraOptions = lib.concatStringsSep " " [
"--bip=172.39.1.5/24"
"--fixed-cidr=172.39.1.0/25"
];
};
users.users.me.extraGroups = [ "docker" ];
environment.systemPackages = [
pkgs.docker
pkgs.docker-compose
];
}

View File

@@ -1,66 +0,0 @@
{
lib,
pkgs,
...
}:
let
sgr = code: string: ''\u001b[${code}m${string}\u001b[0m'';
in
{
environment.systemPackages = [
(pkgs.writers.writeDashBin "notifications" ''
${pkgs.dunst}/bin/dunstctl history \
| ${pkgs.jq}/bin/jq -r '
.data[]
| map("${sgr "90" ''\(.appname.data)''} ${sgr "1" ''\(.summary.data)''} ${sgr "31" ''\(.body.data | gsub("\n"; " | "))''}")
| join("\n")'
'')
];
home-manager.users.me.services.dunst = {
enable = true;
iconTheme = pkgs.lib.niveum.theme.icon;
settings = {
global = {
transparency = 10;
geometry = "200x5-30+20";
follow = "mouse";
indicate_hidden = true;
notification_height = 0;
separator_height = 2;
padding = 8;
horizontal_padding = 8;
sort = true;
markup = "full";
format = "%a\\n<b>%s</b>\\n%b";
alignment = "left";
show_age_threshold = 60;
bounce_freq = 0;
word_wrap = true;
ellipsize = "middle";
ignore_newline = false;
stack_duplicates = true;
hide_duplicate_count = false;
max_icon_size = 32;
sticky_history = true;
history_length = 20;
dmenu = "${pkgs.rofi}/bin/rofi -display-run dunst -show run";
browser = lib.getExe pkgs.niveum-browser;
verbosity = "mesg";
corner_radius = 0;
mouse_left_click = "do_action";
mouse_right_click = "close_current";
mouse_middle_click = "close_all";
};
urgency_low = {
timeout = 5;
};
urgency_normal = {
timeout = 10;
};
urgency_critical = {
timeout = 0;
};
};
};
}

View File

@@ -4,20 +4,7 @@
config, config,
... ...
}: }:
let
vim-kmein = (
pkgs.vim-kmein.override {
# stylixColors = config.lib.stylix.colors;
colorscheme = "base16-gruvbox-dark-medium";
}
);
in
{ {
environment.variables.EDITOR = lib.getExe vim-kmein;
environment.shellAliases.vi = "nvim";
environment.shellAliases.vim = "nvim";
environment.shellAliases.view = "nvim -R";
home-manager.users.me = { home-manager.users.me = {
editorconfig = { editorconfig = {
enable = true; enable = true;
@@ -45,13 +32,12 @@ in
environment.systemPackages = [ environment.systemPackages = [
pkgs.vim-typewriter pkgs.vim-typewriter
vim-kmein pkgs.dawn-editor
# language servers # language servers
pkgs.pyright pkgs.pyright
pkgs.haskellPackages.haskell-language-server pkgs.haskellPackages.haskell-language-server
pkgs.texlab pkgs.texlab
pkgs.nil
pkgs.gopls pkgs.gopls
pkgs.nixfmt-rfc-style pkgs.nixfmt-rfc-style
pkgs.rust-analyzer pkgs.rust-analyzer

View File

@@ -1,27 +0,0 @@
{ pkgs, ... }:
{
programs.fzf = {
fuzzyCompletion = true;
keybindings = true;
};
home-manager.users.me = {
programs.fzf =
let
defaultCommand = "${pkgs.fd}/bin/fd --type f --strip-cwd-prefix --follow --no-ignore-vcs --exclude .git";
in
{
enable = true;
defaultCommand = defaultCommand;
defaultOptions = [ "--height=40%" ];
changeDirWidgetCommand = "${pkgs.fd}/bin/fd --type d";
changeDirWidgetOptions = [
"--preview='${pkgs.tree}/bin/tree -L 1 {}'"
"--bind=space:toggle-preview"
"--preview-window=hidden"
];
fileWidgetCommand = defaultCommand;
fileWidgetOptions = [ "--preview='head -$LINES {}'" ];
};
};
}

View File

@@ -1,52 +0,0 @@
{
pkgs,
lib,
...
}:
{
environment.systemPackages = [
pkgs.mr
pkgs.gitFull
pkgs.git-crypt
pkgs.gitflow
pkgs.gh
pkgs.git-extras
# pkgs.git-trim
pkgs.git-absorb
pkgs.gitstats
pkgs.patch
pkgs.patchutils
];
environment.shellAliases = {
gf = "git-flow";
g = "git";
};
home-manager.users.me = {
programs.git = {
enable = true;
package = pkgs.gitFull;
settings.alias = {
br = "branch";
co = "checkout";
ci = "commit";
cm = "commit -m";
amend = "commit --amend";
st = "status -s";
unstage = "reset HEAD --";
diffs = "diff --staged";
last = "log -1 HEAD";
logs = "log --pretty=oneline";
graph = "log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all";
};
ignores = pkgs.lib.niveum.ignorePaths;
settings.user.name = pkgs.lib.niveum.kieran.name;
settings.user.email = pkgs.lib.niveum.kieran.email;
settings.pull.ff = "only";
settings.rebase.autoStash = true;
settings.merge.autoStash = true;
settings.push.autoSetupRemove = true;
};
};
}

View File

@@ -0,0 +1,44 @@
{
pkgs,
lib,
config,
...
}:
{
programs.hyprland = {
enable = true;
withUWSM = true;
xwayland.enable = true;
package = pkgs.hyprland;
portalPackage = pkgs.xdg-desktop-portal-hyprland;
};
programs.ydotool.enable = true;
xdg.portal = {
enable = true;
extraPortals = [
pkgs.xdg-desktop-portal-hyprland
pkgs.xdg-desktop-portal-gtk
];
config.common.default = "*";
};
services.dbus = {
implementation = "broker";
# needed for GNOME services outside of GNOME (?)
packages = [ pkgs.gcr ];
};
environment.systemPackages = [
pkgs.xdg-desktop-portal
pkgs.xdg-desktop-portal-hyprland
];
services.getty.autologinOnce = true;
services.getty.autologinUser = config.users.users.me.name;
home-manager.users.me = import ./home-manager.nix {
inherit lib pkgs config;
};
}

View File

@@ -0,0 +1,415 @@
{
lib,
pkgs,
config,
...
}:
let
klem = pkgs.klem.override {
options.dmenu = "${pkgs.dmenu}/bin/dmenu -i -p klem";
options.scripts = {
"p.r paste" = pkgs.writers.writeDash "p.r" ''
${pkgs.curl}/bin/curl -fSs http://p.r --data-binary @- \
| ${pkgs.coreutils}/bin/tail --lines=1 \
| ${pkgs.gnused}/bin/sed 's/\\<r\\>/krebsco.de/'
'';
"envs.sh paste" = pkgs.writers.writeDash "envs-host" ''
${pkgs.curl}/bin/curl -F "file=@-" https://envs.sh
'';
# this segfaults
# "envs.sh mirror" = pkgs.writers.writeDash "envs-mirror" ''
# ${pkgs.curl}/bin/curl -F "url=$(${pkgs.coreutils}/bin/cat)" https://envs.sh
# '';
"envs.sh shorten" = pkgs.writers.writeDash "envs-shorten" ''
${pkgs.curl}/bin/curl -F "shorten=$(${pkgs.coreutils}/bin/cat)" https://envs.sh
'';
"go.r shorten" = pkgs.writers.writeDash "go.r" ''
${pkgs.curl}/bin/curl -fSs http://go.r -F "uri=$(${pkgs.coreutils}/bin/cat)"
'';
"4d2.org paste" = pkgs.writers.writeDash "4d2-paste" ''
${pkgs.curl}/bin/curl -F "file=@-" https://depot.4d2.org/
'';
"0x0.st shorten" = pkgs.writers.writeDash "0x0.st" ''
${pkgs.curl}/bin/curl -fSs https://0x0.st -F "shorten=$(${pkgs.coreutils}/bin/cat)"
'';
"rot13" = pkgs.writers.writeDash "rot13" ''
${pkgs.coreutils}/bin/tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
'';
"ipa" = pkgs.writers.writeDash "ipa" ''
${pkgs.ipa}/bin/ipa
'';
"betacode" = pkgs.writers.writeDash "betacode" ''
${pkgs.betacode}/bin/betacode
'';
"curl" = pkgs.writers.writeDash "curl" ''
${pkgs.curl}/bin/curl -fSs "$(${pkgs.coreutils}/bin/cat)"
'';
ocr = pkgs.writers.writeDash "ocr" ''
${pkgs.tesseract4}/bin/tesseract -l eng+deu - stdout
'';
emojai = pkgs.writers.writeDash "emojai" ''
${pkgs.curl}/bin/curl https://www.emojai.app/api/generate -X POST -H 'Content-Type: application/json' --data-raw "$(${pkgs.jq}/bin/jq -sR '{emoji:.}')" | ${pkgs.jq}/bin/jq -r .result
'';
};
};
arabic.workspaces = [
"١"
"٢"
"٣"
"٤"
"٥"
"٦"
"٧"
"٨"
"٩"
"١٠"
];
arabic.music = "الموسيقى";
arabic.obsidian = "السبج";
hindi.workspaces = [
""
""
""
""
""
""
""
""
""
""
];
hindi.music = "";
hindi.obsidian = "ि";
hebrew.workspaces = [
"א"
"ב"
"ג"
"ד"
"ה"
"ו"
"ז"
"ח"
"ט"
"י"
];
hebrew.music = "מוסיקה";
hebrew.obsidian = "אובסידיאן";
latin.workspaces = [
""
""
""
""
""
""
""
""
""
""
];
latin.music = "MVSICA";
latin.obsidian = "NOSCENDA";
greek.workspaces = [
"Α"
"Β"
"Γ"
"Δ"
"Ε"
"Ϛ"
"Ζ"
"Η"
"Θ"
"Ι"
];
greek.music = "ΜΟΥΣΙΚΗ";
greek.obsidian = "ΥΠΟΜΝΗΜΑΤΑ";
language = greek;
in
{
services.mako = {
enable = true;
settings.default-timeout = 10 * 1000;
};
programs.ashell = {
enable = true;
settings = {
# position = "bottom";
modules = {
left = [
"Workspaces"
[
"WindowTitle"
]
];
center = [ "Clock" ];
right = [
"KeyboardLayout"
[
"Tray"
"SystemInfo"
"Settings"
]
];
};
workspaces = {
enable_workspace_filling = false;
disable_special_workspaces = true;
visibility_mode = "MonitorSpecific";
workspace_names = language.workspaces;
};
keyboard_layout.labels = {
"de" = "🇩🇪";
};
window_title = {
mode = "Title";
truncate_title_after_length = 75;
};
media_player = {
max_title_length = 40;
};
system_info.indicators = [
"Cpu"
"Memory"
{ Disk = "/"; }
];
clock.format = "%Y-%m-%d (%j %a %W) %H:%M";
settings.indicators = [
"IdleInhibitor"
"PowerProfile"
"Audio"
"Bluetooth"
"Network"
"Vpn"
"Battery"
];
appearance = {
font_name = config.stylix.fonts.sansSerif.name;
backdrop = 0.3;
scale_factor = 0.85;
# style = "Solid";
};
};
};
services.hypridle = {
enable = true;
settings = {
general = {
after_sleep_cmd = "hyprctl dispatch dpms on";
ignore_dbus_inhibit = false;
lock_cmd = "hyprlock";
};
listener = [
{
timeout = 900;
on-timeout = "hyprlock";
}
{
timeout = 1200;
on-timeout = "hyprctl dispatch dpms off";
on-resume = "hyprctl dispatch dpms on";
}
];
};
};
programs.hyprlock = {
enable = true;
settings = {
animations.enabled = false;
general = {
hide_cursor = true;
ignore_empty_input = true;
};
};
};
gtk = {
enable = true;
iconTheme = {
name = "Adwaita";
package = pkgs.adwaita-icon-theme;
};
};
wayland.windowManager.hyprland =
let
mod = "SUPER";
in
{
enable = true;
systemd.enable = false;
systemd.variables = [ "--all" ];
settings = {
env = [
"XCURSOR_SIZE,${toString config.stylix.cursor.size}" # TODO
"HYPRCURSOR_SIZE,${toString config.stylix.cursor.size}" # TODO
"HYPRCURSOR_THEME,${config.stylix.cursor.name}"
"QT_QPA_PLATFORM=wayland"
"GDK_BACKEND=wayland"
"NIXOS_OZONE_WL=1"
];
permission = [
"${pkgs.xdg-desktop-portal-hyprland}/libexec/.xdg-desktop-portal-hyprland-wrapped, screencopy, allow"
];
monitor = [
"eDP-1, 1920x1080, 0x0, 1" # fatteh's display
"desc:Samsung Electric Company C27F390 HTQH602129, 1920x1080, 0x-1080, 1" # home
"desc:Dell Inc. DELL P2419HC 8L0FL03, 1920x1080, 0x-1080, 1" # amo
", preferred, auto, 1"
];
exec-once = [
(lib.getExe pkgs.ashell)
"hyprctl dispatch exec \"[workspace special:${language.obsidian} silent] obsidian\""
(lib.getExe pkgs.niphas-clipboard-watcher)
(lib.getExe pkgs.niphas-redshift)
(lib.getExe pkgs.niphas-set-wallpaper)
];
device = [
{
name = "elan-touchscreen";
enabled = false;
}
];
general = {
gaps_in = 2;
gaps_out = 2;
border_size = 2;
resize_on_border = true;
allow_tearing = false;
layout = "dwindle";
};
decoration = {
rounding = 0;
rounding_power = 0;
active_opacity = 1.0;
inactive_opacity = 1.0;
shadow = {
enabled = false;
range = 4;
render_power = 3;
};
blur = {
enabled = false;
size = 3;
passes = 1;
vibrancy = 0.17;
};
};
animations = {
enabled = true;
animation = [
"global, 1, 2, default"
];
};
dwindle = {
preserve_split = true;
};
master.new_status = "master";
gesture = [
"3, horizontal, workspace"
];
input = {
kb_layout = "de";
kb_variant = "T3";
kb_options = "compose:caps,grp:ctrls_toggle";
follow_mouse = 1;
sensitivity = 0;
touchpad.natural_scroll = false;
};
bindm = [
"${mod}, mouse:272, movewindow"
"${mod}, mouse:273, resizewindow"
];
bindel = [
",XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"
",XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
",XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
",XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
",XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+"
",XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%-"
", Print, exec, ${lib.getExe pkgs.niphas-screenshot}"
];
bindl = [
", XF86AudioNext, exec, playerctl next"
", XF86AudioPause, exec, playerctl play-pause"
", XF86AudioPlay, exec, playerctl play-pause"
", XF86AudioPrev, exec, playerctl previous"
];
bind = [
"${mod}, Return, exec, ${lib.getExe pkgs.niphas-terminal}"
"${mod} SHIFT, Q, killactive,"
"${mod} SHIFT, R, exit,"
"${mod}, t, exec, ${lib.getExe pkgs.niphas-file-browser}"
"${mod}, Y, exec, ${lib.getExe pkgs.niphas-web-browser}"
"${mod}, Q, exec, ${lib.getExe pkgs.niphas-clipman}"
"${mod}, u, exec, ${lib.getExe pkgs.unicodmenu}"
"${mod}, p, exec, ${lib.getExe pkgs.rofi-pass-wayland}"
"${mod} SHIFT, Z, togglefloating,"
"${mod}, D, exec, ${lib.getExe pkgs.rofi} -show run"
"${mod}, E, togglesplit," # dwindle
"${mod}, F, fullscreen"
"${mod}, G, moveoutofgroup"
"${mod} SHIFT, G, togglegroup"
"${mod}, h, movefocus, l"
"${mod}, l, movefocus, r"
"${mod}, k, movefocus, u"
"${mod}, j, movefocus, d"
"${mod}, F12, exec, ${klem}/bin/klem"
"${mod} SHIFT, W, exec, hyprlock"
"${mod} SHIFT, H, movewindow, l"
"${mod} SHIFT, L, movewindow, r"
"${mod} SHIFT, K, movewindow, u"
"${mod} SHIFT, J, movewindow, d"
"${mod}, S, togglespecialworkspace, ${language.music}"
"${mod} SHIFT, S, movetoworkspace, special:${language.music}"
"${mod}, O, togglespecialworkspace, ${language.obsidian}"
"${mod} SHIFT, O, movetoworkspace, special:${language.obsidian}"
]
++ lib.concatMap (
i:
let
key = lib.mod i 10;
in
[
"${mod}, ${toString key}, workspace, ${toString i}"
"${mod} SHIFT, ${toString key}, movetoworkspace, ${toString i}"
]
) (lib.range 1 10);
windowrule = [
"suppressevent maximize, class:.*" # ignore maximize requests from apps
"nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0" # fix some dragging issues with wayyland
"float,title:^(Picture-in-Picture)$"
"pin,title:^(Picture-in-Picture)$"
"size 640 360,title:^(Picture-in-Picture)$"
"move 100%-640 100%-360,title:^(Picture-in-Picture)$"
];
};
extraConfig = ''
bind = ${mod}, R, submap, resize
submap = resize
binde = , l, resizeactive, 50 0
binde = , h, resizeactive, -50 0
binde = , k, resizeactive, 0 -50
binde = , j, resizeactive, 0 50
bind = , escape, submap, reset
submap = reset
'';
};
}

View File

@@ -4,7 +4,6 @@
}: }:
let let
ledgerDirectory = "/home/kfm/sync/src/ledger"; ledgerDirectory = "/home/kfm/sync/src/ledger";
hora = pkgs.callPackage ../packages/hora.nix { timeLedger = "${ledgerDirectory}/time.timeclock"; };
in in
{ {
environment.systemPackages = environment.systemPackages =
@@ -12,7 +11,6 @@ in
git = "${pkgs.git}/bin/git -C ${ledgerDirectory}"; git = "${pkgs.git}/bin/git -C ${ledgerDirectory}";
in in
[ [
hora
pkgs.hledger pkgs.hledger
(pkgs.writers.writeDashBin "hledger-git" '' (pkgs.writers.writeDashBin "hledger-git" ''
if [ "$1" = entry ]; then if [ "$1" = entry ]; then

View File

@@ -243,16 +243,16 @@ in
"${modifier}+w" = "layout tabbed"; "${modifier}+w" = "layout tabbed";
"${modifier}+q" = "exec ${config.services.clipmenu.package}/bin/clipmenu"; "${modifier}+q" = "exec ${config.services.clipmenu.package}/bin/clipmenu";
"${modifier}+Return" = "exec ${lib.getExe pkgs.niveum-terminal}"; "${modifier}+Return" = "exec ${lib.getExe pkgs.niphas-terminal}";
"${modifier}+t" = "exec ${lib.getExe pkgs.niveum-filemanager}"; "${modifier}+t" = "exec ${lib.getExe pkgs.niphas-file-browser}";
"${modifier}+y" = "exec ${lib.getExe pkgs.niveum-browser}"; "${modifier}+y" = "exec ${lib.getExe pkgs.niphas-web-browser}";
"${modifier}+d" = "${modifier}+d" =
"exec ${pkgs.writers.writeDash "run" ''exec rofi -modi run,ssh,window -show run''}"; "exec ${pkgs.writers.writeDash "run" ''exec rofi -modi run,ssh,window -show run''}";
"${modifier}+Shift+d" = "exec ${pkgs.notemenu}/bin/notemenu"; "${modifier}+Shift+d" = "exec ${lib.getExe pkgs.notemenu}";
"${modifier}+p" = "exec rofi-pass"; "${modifier}+p" = "exec rofi-pass";
"${modifier}+Shift+p" = "exec rofi-pass --insert"; "${modifier}+Shift+p" = "exec rofi-pass --insert";
"${modifier}+u" = "exec ${pkgs.unicodmenu}/bin/unicodmenu"; "${modifier}+u" = "exec ${lib.getExe pkgs.unicodmenu}";
"${modifier}+Shift+u" = "${modifier}+Shift+u" =
"exec ${pkgs.writers.writeDash "last-unicode" ''${pkgs.xdotool}/bin/xdotool type --delay 1000 "$(${pkgs.gawk}/bin/awk 'END{print $1}' ~/.cache/unicodmenu)"''}"; "exec ${pkgs.writers.writeDash "last-unicode" ''${pkgs.xdotool}/bin/xdotool type --delay 1000 "$(${pkgs.gawk}/bin/awk 'END{print $1}' ~/.cache/unicodmenu)"''}";
@@ -264,15 +264,15 @@ in
fi fi
''}"; ''}";
"${modifier}+F12" = "exec ${klem}/bin/klem"; "${modifier}+F12" = "exec ${klem}/bin/klem";
"XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5"; "XF86AudioLowerVolume" = "exec ${lib.getExe pkgs.pamixer} -d 5";
"XF86AudioMute" = "exec ${pkgs.pamixer}/bin/pamixer -t"; "XF86AudioMute" = "exec ${lib.getExe pkgs.pamixer} -t";
"XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5"; "XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5";
"XF86Calculator" = "exec ${pkgs.st}/bin/st -c floating -e ${pkgs.bc}/bin/bc"; "XF86Calculator" = "exec ${lib.getExe pkgs.st} -c floating -e ${pkgs.bc}/bin/bc";
"XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl play-pause"; "XF86AudioPause" = "exec ${lib.getExe pkgs.playerctl} play-pause";
"XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play-pause"; "XF86AudioPlay" = "exec ${lib.getExe pkgs.playerctl} play-pause";
"XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next"; "XF86AudioNext" = "exec ${lib.getExe pkgs.playerctl} next";
"XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous"; "XF86AudioPrev" = "exec ${lib.getExe pkgs.playerctl} previous";
"XF86AudioStop" = "exec ${pkgs.playerctl}/bin/playerctl stop"; "XF86AudioStop" = "exec ${lib.getExe pkgs.playerctl} stop";
# key names detected with xorg.xev: # key names detected with xorg.xev:
# XF86WakeUp (fn twice) # XF86WakeUp (fn twice)
@@ -297,12 +297,12 @@ in
extraConfig = '' extraConfig = ''
bindsym --release ${modifier}+Shift+w exec xsecurelock bindsym --release ${modifier}+Shift+w exec xsecurelock
exec "${pkgs.obsidian}/bin/obsidian" exec "${lib.getExe pkgs.obsidian}"
for_window [class="obsidian"] , move scratchpad for_window [class="obsidian"] , move scratchpad
assign [class="message"] ${messageWorkspace} assign [class="message"] ${messageWorkspace}
exec "${pkgs.writers.writeDash "irc" "exec ${pkgs.alacritty}/bin/alacritty --class message -e ssh weechat@makanek -t tmux attach-session -t IM"}" exec "${pkgs.writers.writeDash "irc" "exec ${lib.getExe pkgs.alacritty} --class message -e ssh weechat@makanek -t tmux attach-session -t IM"}"
exec "${pkgs.writers.writeDash "email" "exec ${pkgs.alacritty}/bin/alacritty --class message -e aerc"}" exec "${pkgs.writers.writeDash "email" "exec ${lib.getExe pkgs.alacritty} --class message -e aerc"}"
exec --no-startup-id ${pkgs.xss-lock}/bin/xss-lock -- xsecurelock exec --no-startup-id ${pkgs.xss-lock}/bin/xss-lock -- xsecurelock
''; '';
@@ -317,14 +317,12 @@ in
colors colors
; ;
keybindings = keybindings // { keybindings = keybindings // {
"${modifier}+F6" = "exec ${pkgs.xorg.xkill}/bin/xkill";
"${modifier}+F9" = "exec ${pkgs.redshift}/bin/redshift -O 4000 -b 0.85"; "${modifier}+F9" = "exec ${pkgs.redshift}/bin/redshift -O 4000 -b 0.85";
"${modifier}+F10" = "exec ${pkgs.redshift}/bin/redshift -x"; "${modifier}+F10" = "exec ${pkgs.redshift}/bin/redshift -x";
"${modifier}+F11" = "exec ${pkgs.xcalib}/bin/xcalib -invert -alter";
"Print" = "exec flameshot gui"; "Print" = "exec flameshot gui";
# "${modifier}+Shift+x" = "exec ${move-to-new-workspace}"; # "${modifier}+Shift+x" = "exec ${move-to-new-workspace}";
# "${modifier}+x" = "exec ${new-workspace}"; # "${modifier}+x" = "exec ${new-workspace}";
"XF86Display" = "exec ${pkgs.dmenu-randr}/bin/dmenu-randr"; "XF86Display" = "exec ${lib.getExe pkgs.dmenu-randr}";
}; };
}; };
}; };

View File

@@ -1,85 +0,0 @@
{
pkgs,
config,
...
}:
{
age.secrets = {
miniflux-api-token = {
file = ../secrets/miniflux-api-token.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "400";
};
};
home-manager.users.me = {
programs.i3status-rust = {
enable = true;
bars.bottom = {
icons = "awesome6";
settings = {
theme.overrides =
let
colours = config.lib.stylix.colors.withHashtag;
in
{
idle_bg = colours.base00;
idle_fg = colours.base05;
good_bg = colours.base00;
good_fg = colours.base0B;
warning_bg = colours.base00;
warning_fg = colours.base0A;
critical_bg = colours.base00;
critical_fg = colours.base09;
info_bg = colours.base00;
info_fg = colours.base04;
separator_bg = colours.base00;
separator = " ";
};
};
blocks = [
{
block = "music";
format = "{$icon $combo $play |}";
separator = " ";
}
{
block = "net";
format = " $icon HU";
missing_format = "";
device = "ppp0";
}
{
block = "net";
format = " $icon FU";
missing_format = "";
device = "tun0";
}
{
block = "battery";
format = "$icon $percentage $time";
device = "DisplayDevice";
driver = "upower";
}
{
block = "sound";
}
{
block = "disk_space";
format = "$icon $available";
}
{
block = "memory";
format = "$icon $mem_used.eng(prefix:G)";
}
{ block = "load"; }
{
block = "time";
format = "$icon $timestamp.datetime(f:'%Y-%m-%d (%W %a) %H:%M', l:de_DE)";
}
];
};
};
};
}

View File

@@ -111,14 +111,18 @@ in
variant = if settings ? "variant" then settings.variant else ""; variant = if settings ? "variant" then settings.variant else "";
in in
pkgs.writers.writeDashBin "kb-${language}" '' pkgs.writers.writeDashBin "kb-${language}" ''
if [ -z $SWAYSOCK ]; then if [ -n "$SWAYSOCK" ]; then
${pkgs.xorg.setxkbmap}/bin/setxkbmap ${defaultLanguage.code},${code} ${defaultLanguage.variant},${variant} ${
toString (map (option: "-option ${option}") xkbOptions)
}
else
swaymsg -s $SWAYSOCK 'input * xkb_layout "${defaultLanguage.code},${code}"' swaymsg -s $SWAYSOCK 'input * xkb_layout "${defaultLanguage.code},${code}"'
swaymsg -s $SWAYSOCK 'input * xkb_variant "${defaultLanguage.variant},${variant}"' swaymsg -s $SWAYSOCK 'input * xkb_variant "${defaultLanguage.variant},${variant}"'
swaymsg -s $SWAYSOCK 'input * xkb_options "${lib.concatStringsSep "," xkbOptions}"' swaymsg -s $SWAYSOCK 'input * xkb_options "${lib.concatStringsSep "," xkbOptions}"'
elif [ -n "$HYPRLAND_INSTANCE_SIGNATURE" ]; then
hyprctl keyword input:kb_variant "" # otherwise we end up with an invalid combination for a short while
hyprctl keyword input:kb_layout "${defaultLanguage.code},${code}"
hyprctl keyword input:kb_variant "${defaultLanguage.variant},${variant}"
elif [ -n "$DISPLAY" ]; then
${pkgs.xorg.setxkbmap}/bin/setxkbmap ${defaultLanguage.code},${code} ${defaultLanguage.variant},${variant} ${
toString (map (option: "-option ${option}") xkbOptions)
}
fi fi
'' ''
) (languages // config.services.xserver.xkb.extraLayouts); ) (languages // config.services.xserver.xkb.extraLayouts);

View File

@@ -20,12 +20,6 @@ in
group = config.users.users.me.group; group = config.users.users.me.group;
mode = "400"; mode = "400";
}; };
nextcloud-password-fysi = {
file = ../secrets/nextcloud-password-fysi.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "400";
};
}; };
environment.systemPackages = [ environment.systemPackages = [

11
configs/lix.nix Normal file
View File

@@ -0,0 +1,11 @@
{
pkgs,
lib,
...
}:
{
nix = {
package = lib.mkForce pkgs.lix;
settings.experimental-features = [ "nix-command" "flakes" ];
};
}

View File

@@ -1,20 +0,0 @@
{ pkgs, ... }:
{
systemd.services.imaginary-illuminations = {
enable = false;
wants = [ "network-online.target" ];
serviceConfig = {
User = "kfm";
Group = "users";
WorkingDirectory = "/home/kfm/cloud/Seafile/Documents/Media/imaginary-illuminations";
Restart = "on-failure";
RestartSec = "15s";
};
startAt = "7:00";
script = ''
${pkgs.deno}/bin/deno run -A post.ts
'';
};
systemd.timers.imaginary-illuminations.timerConfig.RandomizedDelaySec = "14h";
}

View File

@@ -1,49 +1,42 @@
{ {
pkgs, pkgs,
lib, lib,
self,
config, config,
... ...
}: }:
let let
swallow = command: "${pkgs.swallow}/bin/swallow ${command}"; swallow = command: "${pkgs.swallow}/bin/swallow ${command}";
myMpv =
pkgs:
self.inputs.wrappers.wrapperModules.mpv.apply {
inherit pkgs;
scripts = [
pkgs.mpvScripts.visualizer
];
"mpv.conf".content = "";
"mpv.input".content = ''
Alt+- add video-zoom -0.25
Alt+= add video-zoom 0.25
Alt+LEFT add video-rotate -90
Alt+RIGHT add video-rotate 90
Alt+h add video-pan-x 0.05
Alt+j add video-pan-y -0.05
Alt+k add video-pan-y 0.05
Alt+l add video-pan-x -0.05
'';
};
in in
{ {
environment.shellAliases.smpv = swallow "mpv"; environment.shellAliases.smpv = swallow "mpv";
nixpkgs.overlays = [ nixpkgs.overlays = [
(self: super: { (final: prev: {
mpv = config.home-manager.users.me.programs.mpv.finalPackage; mpv = (myMpv prev).wrapper;
}) })
]; ];
home-manager.users.me = { environment.systemPackages = [
programs.mpv = { ((myMpv pkgs).wrapper)
enable = true; ];
config = {
ytdl-format = "bestvideo[height<=?720][fps<=?30][vcodec!=?vp9]+bestaudio/best";
ytdl-raw-options = lib.concatStringsSep "," [
''sub-lang="de,en"''
"write-sub="
"write-auto-sub="
];
screenshot-template = "%F-%wH%wM%wS-%#04n";
script-opts = "ytdl_hook-ytdl_path=${pkgs.yt-dlp}/bin/yt-dlp";
ao = "pulse"; # no pipewire for me :(
};
bindings = {
"Alt+RIGHT" = "add video-rotate 90";
"Alt+LEFT" = "add video-rotate -90";
"Alt+-" = "add video-zoom -0.25";
"Alt+=" = "add video-zoom 0.25";
"Alt+l" = "add video-pan-x -0.05";
"Alt+h" = "add video-pan-x 0.05";
"Alt+k" = "add video-pan-y 0.05";
"Alt+j" = "add video-pan-y -0.05";
};
scripts = [
pkgs.mpvScripts.quality-menu
pkgs.mpvScripts.visualizer
];
};
};
} }

View File

@@ -1,18 +0,0 @@
{
pkgs,
config,
...
}:
{
environment.systemPackages = [
(pkgs.writers.writeDashBin "miniflux-watch-later" ''
miniflux_api_token=$(cat ${config.age.secrets.miniflux-api-token.path})
random_feed_item=$(
${pkgs.curl}/bin/curl -u "$miniflux_api_token" --basic -s 'https://feed.kmein.de/v1/entries?starred=true&limit=0' \
| ${pkgs.jq}/bin/jq -r '.entries[].id' \
| ${pkgs.coreutils}/bin/shuf -n1
)
${pkgs.xdg-utils}/bin/xdg-open "https://feed.kmein.de/starred/entry/$random_feed_item"
'')
];
}

View File

@@ -1,15 +0,0 @@
{
pkgs,
inputs,
...
}:
{
nixpkgs = {
config.allowUnfree = true;
};
nix = {
package = pkgs.nixVersions.stable;
extraOptions = "experimental-features = nix-command flakes";
nixPath = [ "nixpkgs=${inputs.nixpkgs}" ];
};
}

View File

@@ -1,8 +1,6 @@
{ {
config, config,
pkgs, pkgs,
lib,
inputs,
... ...
}: }:
let let
@@ -72,41 +70,28 @@ in
GPODDER_DOWNLOAD_DIR=${config.users.users.me.home}/mobile/audio/Text/podcasts exec ${pkgs.gpodder}/bin/gpodder "$@" GPODDER_DOWNLOAD_DIR=${config.users.users.me.home}/mobile/audio/Text/podcasts exec ${pkgs.gpodder}/bin/gpodder "$@"
'') '')
# INTERNET # INTERNET
aria2
telegram-desktop telegram-desktop
whois ferdium
dnsutils
# FILE MANAGERS # FILE MANAGERS
lf lf
pcmanfm
# MEDIA # MEDIA
ffmpeg ffmpeg
simplescreenrecorder simplescreenrecorder
imagemagick imagemagick
exiftool exiftool
nsxiv
graphviz graphviz
# SHELL # SHELL
bat # better cat
dos2unix
genpass # generate passwords genpass # generate passwords
(pkgs.writers.writeDashBin "genpassphrase" ''${pkgs.genpass}/bin/genpass --passphrase | ${pkgs.gnused}/bin/sed 's/ /-/g;s/\(^\|-\)\([a-z]\)/\1\U\2/g;s/$/-'$(${pkgs.coreutils}/bin/date +%Y)'/' '') (pkgs.writers.writeDashBin "genpassphrase" ''${pkgs.genpass}/bin/genpass "$@" --passphrase | ${pkgs.gnused}/bin/sed 's/ /-/g;s/\(^\|-\)\([a-z]\)/\1\U\2/g;s/$/-'$(${pkgs.coreutils}/bin/date +%Y)'/' '')
gcc gcc
python3Packages.jsonschema # json validation python3Packages.jsonschema # json validation
pup # html toolkit pup # html toolkit
xan # csv toolkit xan # csv toolkit
magic-wormhole-rs # file transfer magic-wormhole-rs # file transfer
man-pages
man-pages-posix
exfat # to mount windows drives exfat # to mount windows drives
# HARDWARE TOOLS # HARDWARE TOOLS
gnome-disk-utility gnome-disk-utility
arandr # xrandr for noobs arandr # xrandr for noobs
wdisplays
libnotify # for notify-send
xclip # clipboard CLI
dragon-drop # drag and drop
xorg.xkill # kill by clicking
portfolio # personal finance overview portfolio # personal finance overview
audacity audacity
calibre calibre
@@ -123,7 +108,7 @@ in
zoom-us # video conferencing zoom-us # video conferencing
(pkgs.writers.writeDashBin "im" '' (pkgs.writers.writeDashBin "im" ''
weechat_password=$(${pkgs.pass}/bin/pass weechat) weechat_password=$(${pkgs.pass}/bin/pass weechat)
exec ${weechat}/bin/weechat -t -r '/mouse enable; /remote add makanek http://${pkgs.lib.niveum.systems.makanek.externalIp}:8002 -password='"$weechat_password"'; /remote connect makanek' exec ${weechat}/bin/weechat -t -r '/mouse enable; /remote add makanek http://${pkgs.lib.niveum.machines.makanek.externalIp}:8002 -password='"$weechat_password"'; /remote connect makanek'
'') '')
alejandra # nix formatter alejandra # nix formatter
pdfgrep # search in pdf pdfgrep # search in pdf
@@ -135,6 +120,7 @@ in
pdfpc # presenter console for pdf slides pdfpc # presenter console for pdf slides
hc # print files as qr codes hc # print files as qr codes
yt-dlp yt-dlp
yt-dlp-master
espeak espeak
rink # unit converter rink # unit converter
auc auc
@@ -144,6 +130,7 @@ in
polyglot polyglot
qrpaste qrpaste
ttspaste ttspaste
pi # llm agent
new-mac # get a new mac address new-mac # get a new mac address
scanned scanned
default-gateway default-gateway
@@ -179,37 +166,36 @@ in
di-fm-key-file = config.age.secrets.di-fm-key.path; di-fm-key-file = config.age.secrets.di-fm-key.path;
}) })
# kmein.slide # kmein.slide
termdown termdown # countdown timer in terminal
image-convert-tolino image-convert-tolino
rfc rfc
tag tag
timer timer
nix-prefetch-git comma
nix-git
nixfmt-rfc-style
par par
qrencode qrencode
# inputs.menstruation-backend.defaultPackage.x86_64-linux pkgs.agenix
inputs.agenix.packages.x86_64-linux.default pkgs.wetter
inputs.recht.defaultPackage.x86_64-linux pkgs.alarm
(pkgs.writers.writeDashBin "worldradio" '' (pkgs.writers.writeDashBin "worldradio" ''
shuf ${worldradio} | ${pkgs.findutils}/bin/xargs ${pkgs.mpv}/bin/mpv --no-video shuf ${worldradio} | ${pkgs.findutils}/bin/xargs ${pkgs.mpv}/bin/mpv --no-video
'') '')
(pkgs.writers.writeDashBin "chats" '' (pkgs.writers.writeDashBin "chats" ''
${pkgs.openssh}/bin/ssh makanek "cd /var/lib/weechat/logs && grep --ignore-case --color=always --recursive $@" | ${pkgs.less}/bin/less --raw-control-chars ${pkgs.openssh}/bin/ssh -p ${toString pkgs.lib.niveum.machines.makanek.sshPort} ${pkgs.lib.niveum.machines.makanek.externalIp} "cd /var/lib/weechat/logs && grep --ignore-case --color=always --recursive $@" | ${pkgs.less}/bin/less --raw-control-chars
'') '')
inputs.scripts.packages.x86_64-linux.alarm niveum-ssh
spotify spotify
ncspot
playerctl playerctl
#krebs #krebs
pkgs.nur.repos.mic92.ircsink pkgs.nur.repos.mic92.ircsink
cyberlocker-tools
kpaste
(haskellPackages.ghcWithHoogle (hs: [ (haskellPackages.ghcWithHoogle (hs: [
hs.text hs.text
@@ -219,6 +205,7 @@ in
(python3.withPackages (py: [ (python3.withPackages (py: [
py.black py.black
py.ruff
# py.python-language-server # py.python-language-server
# py.pyls-mypy # py.pyls-mypy
# py.pyls-black # py.pyls-black
@@ -248,7 +235,7 @@ in
text2pdf text2pdf
lowdown lowdown
glow # markdown to term glow # markdown to term
libreoffice libreoffice-qt6-fresh
# gnumeric # gnumeric
dia dia
pandoc pandoc
@@ -258,10 +245,6 @@ in
# proselint # proselint
asciidoctor asciidoctor
wordnet wordnet
tokei # count lines of code
gnumake
binutils # for strip, ld, ...
# nightly.rust
shellcheck shellcheck
# photography # photography

View File

@@ -1,6 +1,6 @@
{ pkgs, lib, ... }: { pkgs, lib, ... }:
let let
hp-driver = pkgs.hplip; hp-driver = pkgs.hplipWithPlugin;
in in
{ {
services.printing = { services.printing = {
@@ -8,12 +8,25 @@ in
drivers = [ hp-driver ]; drivers = [ hp-driver ];
}; };
hardware.sane = {
enable = true;
extraBackends = [ hp-driver ];
};
environment.systemPackages = [ environment.systemPackages = [
pkgs.system-config-printer pkgs.system-config-printer
pkgs.simple-scan
hp-driver
]; ];
# allow connecting to .local printers # allow connecting to .local printers
services.avahi.nssmdns4 = true; services.avahi = {
nssmdns4 = true;
enable = true;
openFirewall = true;
};
# users.users.me.extraGroups is set in configs/default.nix which defines the "me" user
hardware.printers.ensurePrinters = [ hardware.printers.ensurePrinters = [
{ {

View File

@@ -60,6 +60,7 @@
user = "kfm"; user = "kfm";
port = pkgs.lib.niveum.sshPort; port = pkgs.lib.niveum.sshPort;
}; };
"*.onion".proxyCommand = "nc -xlocalhost:9050 %h %p";
}; };
}; };
} }

View File

@@ -8,7 +8,7 @@
services.openssh = { services.openssh = {
enable = true; enable = true;
ports = [ pkgs.lib.niveum.sshPort ]; ports = [ pkgs.lib.niveum.machines.${config.networking.hostName}.sshPort ];
settings = { settings = {
PasswordAuthentication = false; PasswordAuthentication = false;
X11Forwarding = true; X11Forwarding = true;

View File

@@ -1,7 +1,6 @@
{ {
pkgs, pkgs,
lib, lib,
inputs,
... ...
}: }:
let let
@@ -153,7 +152,6 @@ let
}; };
}; };
coptic = { coptic = {
dictionary = inputs.coptic-dictionary.packages.x86_64-linux.coptic-stardict;
Crum = pkgs.fetchzip { Crum = pkgs.fetchzip {
url = locker "stardict-Coptic-English_all_dialects-2.4.2.tar.bz2"; url = locker "stardict-Coptic-English_all_dialects-2.4.2.tar.bz2";
sha256 = "1fi281mb9yzv40wjsdapi8fzpa7x2yscz582lv2qnss9g8zzzzr9"; sha256 = "1fi281mb9yzv40wjsdapi8fzpa7x2yscz582lv2qnss9g8zzzzr9";

View File

@@ -2,23 +2,11 @@
pkgs, pkgs,
config, config,
lib, lib,
inputs,
... ...
}: }:
let
generatedWallpaper = pkgs.runCommand "wallpaper.png" { } ''
${inputs.wallpaper-generator.packages.x86_64-linux.wp-gen}/bin/wallpaper-generator lines \
--output $out \
${lib.concatMapStringsSep " " (
n: "--base0${lib.toHexString n}=${config.lib.stylix.colors.withHashtag."base0${lib.toHexString n}"}"
) (lib.range 0 15)}
'';
in
{ {
# https://danth.github.io/stylix/tricks.html # https://danth.github.io/stylix/tricks.html
# stylix.image = inputs.wallpapers.outPath + "/meteora/rodrigo-soares-250630.jpg";
stylix.enable = true; stylix.enable = true;
stylix.image = generatedWallpaper;
stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-medium.yaml"; stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-medium.yaml";
@@ -55,6 +43,7 @@ in
# dracula # https://draculatheme.com/ # dracula # https://draculatheme.com/
# }.yaml"; # }.yaml";
stylix.fonts = { stylix.fonts = {
serif = { serif = {
package = pkgs.noto-fonts; package = pkgs.noto-fonts;
@@ -77,7 +66,7 @@ in
}; };
sizes = { sizes = {
terminal = 6; terminal = 8;
applications = 10; applications = 10;
}; };
}; };

View File

@@ -18,7 +18,7 @@
]; ];
services.tlp = { services.tlp = {
enable = true; enable = false;
settings = { settings = {
START_CHARGE_THRESH_BAT0 = 80; START_CHARGE_THRESH_BAT0 = 80;
STOP_CHARGE_THRESH_BAT0 = 95; STOP_CHARGE_THRESH_BAT0 = 95;

View File

@@ -1,44 +0,0 @@
{ pkgs, ... }:
{
environment.systemPackages = [
pkgs.tmuxp
pkgs.reptyr # move programs over to a tmux session
];
programs.tmux = {
enable = true;
keyMode = "vi";
clock24 = true;
terminal = "screen-256color";
baseIndex = 1;
aggressiveResize = true;
escapeTime = 50;
historyLimit = 7000;
shortcut = "b";
extraConfig = ''
set -g mouse on
unbind *
bind * list-clients
# naVIgate
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
# Use C-h and C-l to cycle through panes
bind -r C-h select-window -t :-
bind -r C-l select-window -t :+
setw -g monitor-activity on
set -g visual-activity on
set -g status-interval 2
set -g status-left-length 32
set -g status-right-length 150
set -g status-position bottom
'';
};
}

View File

@@ -1,4 +1,12 @@
{ pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let
sshPort = pkgs.lib.niveum.machines.${config.networking.hostName}.sshPort;
in
{ {
services.tor.enable = true; services.tor.enable = true;
services.tor.client.enable = true; services.tor.client.enable = true;
@@ -6,4 +14,17 @@
pkgs.tor pkgs.tor
pkgs.torsocks pkgs.torsocks
]; ];
services.tor.relay.onionServices = {
"ssh" = {
version = 3;
map = [
{
port = sshPort;
target.port = sshPort;
target.addr = "127.0.0.1";
}
];
};
};
} }

View File

@@ -56,7 +56,6 @@ in
passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-meinhak99.path}"; passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-meinhak99.path}";
himalaya = { himalaya = {
enable = true; enable = true;
settings.backend = "imap";
}; };
} }
) )

View File

@@ -1,14 +1,4 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
users.users.me.extraGroups = [ "libvirtd" ]; virtualisation.waydroid.enable = true;
virtualisation.libvirtd.enable = true;
# Enable TPM support for VMs
virtualisation.libvirtd.qemu = {
# swtpm.enable = true;
};
environment.systemPackages = with pkgs; [
virt-manager
];
} }

View File

@@ -12,18 +12,26 @@ in
systemd.user.services.wallpaper = { systemd.user.services.wallpaper = {
wantedBy = [ "graphical-session.target" ]; wantedBy = [ "graphical-session.target" ];
after = [ "network.target" ]; after = [ "network.target" ];
path = [
pkgs.curl
pkgs.hyprland
];
script = '' script = ''
set -euf set -euf
mkdir -p ${stateDir} mkdir -p ${stateDir}
chmod o+rx ${stateDir} chmod o+rx ${stateDir}
cd ${stateDir} cd ${stateDir}
(${pkgs.curl}/bin/curl -s -o wallpaper.tmp -z wallpaper.tmp ${lib.escapeShellArg url} && cp wallpaper.tmp wallpaper) || : (${pkgs.curl}/bin/curl -s -o wallpaper.tmp -z wallpaper.tmp ${lib.escapeShellArg url} && cp wallpaper.tmp wallpaper.png) || :
${pkgs.feh}/bin/feh --no-fehbg --bg-scale wallpaper hyprctl hyprpaper preload ${stateDir}/wallpaper.png
hyprctl hyprpaper wallpaper ",${stateDir}/wallpaper.png"
sleep 5
hyprctl hyprpaper unload unused
true
''; '';
startAt = "*:00,10,20,30,40,50"; startAt = "*:00,10,20,30,40,50";
serviceConfig = { serviceConfig = {
Restart = "always"; Restart = "on-failure";
RestartSec = "15s"; RestartSec = "15s";
StartLimitBurst = 0; StartLimitBurst = 0;
}; };

View File

@@ -1,10 +0,0 @@
{
config,
pkgs,
...
}:
{
environment.systemPackages = [ pkgs.watson ];
environment.variables.WATSON_DIR = "${config.users.users.me.home}/cloud/Seafile/Documents/watson";
}

View File

@@ -1,98 +0,0 @@
{
config,
pkgs,
...
}:
let
promptColours.success = "cyan";
promptColours.failure = "red";
in
{
programs.zsh =
let
zsh-completions = pkgs.fetchFromGitHub {
owner = "zsh-users";
repo = "zsh-completions";
rev = "cf565254e26bb7ce03f51889e9a29953b955b1fb";
sha256 = "1yf4rz99acdsiy0y1v3bm65xvs2m0sl92ysz0rnnrlbd5amn283l";
};
in
{
enable = true;
enableCompletion = true;
autosuggestions.enable = true;
syntaxHighlighting.enable = true;
syntaxHighlighting.highlighters = [
"main"
"brackets"
"pattern"
"line"
];
interactiveShellInit = ''
setopt INTERACTIVE_COMMENTS CORRECT
setopt MULTIOS
setopt AUTO_NAME_DIRS
setopt AUTOCD CDABLE_VARS
setopt HIST_IGNORE_ALL_DUPS
setopt VI
setopt AUTO_MENU
setopt COMPLETE_IN_WORD
setopt ALWAYS_TO_END
unsetopt NOMATCH
unsetopt MENU_COMPLETE
zstyle ':completion:*:*:*:*:*' menu select
zstyle ':completion:*' matcher-list 'm:{a-zA-Z-_}={A-Za-z_-}' 'r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' special-dirs true
zstyle ':completion:*' list-colors \'\'
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#) ([0-9a-z-]#)*=01;34=0=01'
zstyle ':completion:*:*:*:*:processes' command "ps -u $USER -o pid,user,comm -w -w"
zstyle ':completion:*:cd:*' tag-order local-directories directory-stack path-directories
export KEYTIMEOUT=1
hash -d nixos=/etc/nixos niveum=${config.users.users.me.home}/sync/src/niveum
autoload -U zmv run-help edit-command-line
fpath=(${zsh-completions}/src $fpath)
'';
promptInit = ''
autoload -Uz vcs_info
zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:*' check-for-changes true
zstyle ':vcs_info:*' stagedstr '%F{green}+%f'
zstyle ':vcs_info:*' unstagedstr '%F{red}~%f'
zstyle ':vcs_info:*' use-prompt-escapes true
zstyle ':vcs_info:*' formats "%c%u%F{cyan}%b%f"
zstyle ':vcs_info:*' actionformats "(%a) %c%u%F{cyan}%b%f"
precmd () {
vcs_info
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] || [ -n "$SSH_CONNECTION" ]; then
RPROMPT="$(hostname)"
else
RPROMPT="$vcs_info_msg_0_"
fi
if [[ -n $IN_NIX_SHELL ]]; then
PROMPT='%B%~%b %(?.%F{${promptColours.success}}.%F{${promptColours.failure}})λ%f '
else
PROMPT='%B%~%b %(?.%F{${promptColours.success}}.%F{${promptColours.failure}})%#%f '
fi
print -Pn "\e]2;%n@%M:%~\a" # title bar prompt
}
zle-keymap-select zle-line-init () {
case $KEYMAP in
vicmd) print -n '\e]12;green\a';;
viins|main) print -n '\e]12;gray\a';;
esac
}
zle -N zle-line-init
zle -N zle-keymap-select
zle -N edit-command-line
bindkey -M vicmd v edit-command-line
'';
};
}

1468
flake.lock generated

File diff suppressed because it is too large Load Diff

584
flake.nix
View File

@@ -2,141 +2,195 @@
description = "niveum: packages, modules, systems"; description = "niveum: packages, modules, systems";
inputs = { inputs = {
self.submodules = true;
agenix.url = "github:ryantm/agenix"; agenix.url = "github:ryantm/agenix";
autorenkalender.url = "github:kmein/autorenkalender"; autorenkalender.url = "github:kmein/autorenkalender";
coptic-dictionary.url = "github:kmein/coptic-dictionary";
home-manager.url = "github:nix-community/home-manager/release-25.11"; home-manager.url = "github:nix-community/home-manager/release-25.11";
menstruation-backend.url = "github:kmein/menstruation.rs"; menstruation-backend.url = "github:kmein/menstruation.rs";
menstruation-telegram.url = "github:kmein/menstruation-telegram"; menstruation-telegram.url = "github:kmein/menstruation-telegram";
nix-index-database.url = "github:nix-community/nix-index-database"; nix-index-database.url = "github:nix-community/nix-index-database";
nixinate.url = "github:matthewcroughan/nixinate";
nixpkgs-old.url = "github:NixOS/nixpkgs/50fc86b75d2744e1ab3837ef74b53f103a9b55a0"; nixpkgs-old.url = "github:NixOS/nixpkgs/50fc86b75d2744e1ab3837ef74b53f103a9b55a0";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/master";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
niphas.url = "git+https://code.kmein.de/kfm/niphas";
panoptikon.url = "git+https://code.kmein.de/kfm/panoptikon";
nixos-hardware.url = "github:NixOS/nixos-hardware";
nur.url = "github:nix-community/NUR"; nur.url = "github:nix-community/NUR";
recht.url = "github:kmein/recht";
retiolum.url = "github:krebs/retiolum"; retiolum.url = "github:krebs/retiolum";
scripts.url = "github:kmein/scripts"; scripts.url = "github:kmein/scripts";
stockholm.url = "github:krebs/stockholm"; stockholm.url = "github:krebs/stockholm";
stylix.url = "github:danth/stylix/release-25.11"; stylix.url = "github:danth/stylix/release-25.11";
telebots.url = "github:kmein/telebots"; telebots.url = "github:kmein/telebots";
tinc-graph.url = "github:kmein/tinc-graph"; tinc-graph.url = "github:kmein/tinc-graph";
treefmt-nix.url = "github:numtide/treefmt-nix";
voidrice.url = "github:Lukesmithxyz/voidrice"; voidrice.url = "github:Lukesmithxyz/voidrice";
wallpaper-generator.url = "github:pinpox/wallpaper-generator/v1.1"; nix-topology.url = "github:oddlama/nix-topology";
wallpapers.url = "github:kmein/wallpapers"; wetter.url = "github:4z3/wetter";
wrappers.url = "github:lassulus/wrappers";
llm-agents.url = "github:numtide/llm-agents.nix";
opencrow.url = "github:pinpox/opencrow";
meteora.url = "git+ssh://git@github.com/kmein/meteora.git";
voidrice.flake = false;
naersk.url = "github:nix-community/naersk";
fenix.url = "github:nix-community/fenix";
naersk.inputs.fenix.follows = "fenix";
menstruation-backend.inputs.fenix.follows = "fenix";
tinc-graph.inputs.fenix.follows = "fenix";
scripts.inputs.fenix.follows = "fenix";
tinc-graph.inputs.naersk.follows = "naersk";
scripts.inputs.naersk.follows = "naersk";
menstruation-telegram.inputs.menstruation-backend.follows = "menstruation-backend";
menstruation-telegram.inputs.nixpkgs.follows = "nixpkgs-old";
telebots.inputs.nixpkgs.follows = "nixpkgs-old";
agenix.inputs.home-manager.follows = "home-manager"; agenix.inputs.home-manager.follows = "home-manager";
opencrow.inputs.treefmt-nix.follows = "treefmt-nix";
agenix.inputs.nixpkgs.follows = "nixpkgs"; agenix.inputs.nixpkgs.follows = "nixpkgs";
autorenkalender.inputs.nixpkgs.follows = "nixpkgs"; autorenkalender.inputs.nixpkgs.follows = "nixpkgs";
coptic-dictionary.inputs.nixpkgs.follows = "nixpkgs";
home-manager.inputs.nixpkgs.follows = "nixpkgs"; home-manager.inputs.nixpkgs.follows = "nixpkgs";
menstruation-telegram.inputs.menstruation-backend.follows = "menstruation-backend"; naersk.inputs.nixpkgs.follows = "nixpkgs";
menstruation-telegram.inputs.nixpkgs.follows = "nixpkgs-old"; fenix.inputs.nixpkgs.follows = "nixpkgs";
treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
nur.inputs.nixpkgs.follows = "nixpkgs";
nix-topology.inputs.nixpkgs.follows = "nixpkgs";
stockholm.inputs.nixpkgs.follows = "nixpkgs";
menstruation-backend.inputs.nixpkgs.follows = "nixpkgs";
nix-index-database.inputs.nixpkgs.follows = "nixpkgs"; nix-index-database.inputs.nixpkgs.follows = "nixpkgs";
recht.inputs.nixpkgs.follows = "nixpkgs";
scripts.inputs.nixpkgs.follows = "nixpkgs"; scripts.inputs.nixpkgs.follows = "nixpkgs";
stylix.inputs.nixpkgs.follows = "nixpkgs"; stylix.inputs.nixpkgs.follows = "nixpkgs";
tinc-graph.inputs.nixpkgs.follows = "nixpkgs"; tinc-graph.inputs.nixpkgs.follows = "nixpkgs";
voidrice.flake = false; wetter.inputs.nixpkgs.follows = "nixpkgs";
wallpapers.flake = false; niphas.inputs.nixpkgs.follows = "nixpkgs-unstable";
wrappers.inputs.nixpkgs.follows = "nixpkgs";
opencrow.inputs.nixpkgs.follows = "nixpkgs";
}; };
outputs = outputs =
{ {
self, self,
nixpkgs, nixpkgs,
nixpkgs-unstable,
nur, nur,
home-manager, home-manager,
agenix, agenix,
retiolum, retiolum,
nixinate,
coptic-dictionary,
menstruation-backend, menstruation-backend,
menstruation-telegram, menstruation-telegram,
scripts, scripts,
tinc-graph, tinc-graph,
recht, nix-topology,
llm-agents,
opencrow,
nixpkgs-unstable,
nixos-hardware,
niphas,
treefmt-nix,
autorenkalender, autorenkalender,
wallpaper-generator,
telebots, telebots,
stockholm, stockholm,
panoptikon,
nix-index-database, nix-index-database,
stylix, stylix,
voidrice, voidrice,
wetter,
wrappers,
meteora,
... ...
}: }:
let let
lib = nixpkgs.lib; lib = nixpkgs.lib;
eachSupportedSystem = lib.genAttrs lib.systems.flakeExposed; eachSupportedSystem = lib.genAttrs lib.systems.flakeExposed;
treefmtEval = eachSupportedSystem (
system:
treefmt-nix.lib.evalModule nixpkgs.legacyPackages.${system} (
{ pkgs, ... }:
{
projectRootFile = "flake.nix";
programs.nixfmt.enable = true;
programs.ormolu.enable = true;
programs.black.enable = true;
programs.prettier.enable = true;
programs.stylua.enable = true;
}
)
);
in in
{ {
apps = {
x86_64-linux = apps =
let let
pkgs = nixpkgs.legacyPackages.x86_64-linux; localSystem = "x86_64-linux";
lib = nixpkgs.lib; in
in {
lib.mergeAttrsList [ ${localSystem} =
(nixinate.nixinate.x86_64-linux self) let
{ pkgs = import nixpkgs {
mock-secrets = { system = localSystem;
type = "app"; overlays = [ self.overlays.default ];
program = toString (
pkgs.writers.writeDash "mock-secrets" ''
${pkgs.findutils}/bin/find secrets -not -path '*/.*' -type f | ${pkgs.coreutils}/bin/sort > secrets.txt
''
);
}; };
} lib = nixpkgs.lib;
# the following error prevents remote building of ful: https://github.com/NixOS/nixpkgs/issues/177873 in
(builtins.listToAttrs ( lib.mergeAttrsList [
map ( {
hostname: mock-secrets = {
let
targets = {
ful = "root@ful";
zaatar = "root@zaatar";
makanek = "root@makanek";
manakish = "root@manakish";
tahina = "root@tahina";
tabula = "root@tabula";
kabsa = "root@kabsa";
fatteh = "root@fatteh";
kibbeh = "root@kibbeh";
};
in
lib.attrsets.nameValuePair "deploy-${hostname}" {
type = "app"; type = "app";
program = toString ( program = toString (
pkgs.writers.writeDash "deploy-${hostname}" '' pkgs.writers.writeDash "mock-secrets" ''
exec ${pkgs.nixos-rebuild}/bin/nixos-rebuild switch \ ${pkgs.findutils}/bin/find secrets -not -path '*/.*' -type f | ${pkgs.coreutils}/bin/sort > secrets.txt
--max-jobs 2 \
--log-format internal-json \
--flake .#${hostname} \
--target-host ${targets.${hostname}} 2>&1 \
| ${pkgs.nix-output-monitor}/bin/nom --json
'' ''
); );
} };
) (builtins.attrNames self.nixosConfigurations) }
)) (builtins.listToAttrs (
{ map (
deploy-ful = { hostname:
type = "app"; let
program = toString ( machines = import lib/machines.nix;
pkgs.writers.writeDash "deploy-ful" '' deployScript = pkgs.writers.writeBash "deploy-${hostname}" ''
exec ${pkgs.nix}/bin/nix run .#nixinate.ful \ reachable=$(${pkgs.try-connect.${hostname}}/bin/try-connect)
--log-format internal-json 2>&1 \
| ${pkgs.nix-output-monitor}/bin/nom --json if [ -z "$reachable" ]; then
'' exit 1
); fi
};
} target="root@$reachable"
]; echo "Deploying to ${hostname} via $target"
};
# Set SSH options based on address type
if [[ "$reachable" == *.onion ]]; then
# why? ControlPath=none
# SSH is trying to create a control socket with a path that includes
# the full .onion hostname, and Unix domain sockets have a path length
# limit (typically 108 characters). The .onion address is too long.
export NIX_SSHOPTS="-p ${
toString machines.${hostname}.sshPort
} -o ProxyCommand='${pkgs.netcat}/bin/nc -x localhost:9050 %h %p' -o ControlPath=none"
else
export NIX_SSHOPTS="-p ${toString machines.${hostname}.sshPort}"
fi
${pkgs.nixos-rebuild-ng}/bin/nixos-rebuild-ng switch \
--max-jobs 2 \
--log-format internal-json \
--flake .?submodules=1#${hostname} \
--use-substitutes \
--target-host "$target" \
${lib.optionalString (localSystem != machines.${hostname}.system) "--build-host $target"} \
|& ${pkgs.nix-output-monitor}/bin/nom --json
'';
in
lib.attrsets.nameValuePair "deploy-${hostname}" {
type = "app";
program = toString deployScript;
}
) (builtins.attrNames self.nixosConfigurations)
))
];
};
# TODO overlay for packages # TODO overlay for packages
# TODO remove flake-utils dependency from my own repos # TODO remove flake-utils dependency from my own repos
@@ -144,20 +198,31 @@
nixosModules = { nixosModules = {
moodle-dl = import modules/moodle-dl.nix; moodle-dl = import modules/moodle-dl.nix;
passport = import modules/passport.nix; passport = import modules/passport.nix;
panoptikon = import modules/panoptikon.nix;
power-action = import modules/power-action.nix; power-action = import modules/power-action.nix;
system-dependent = import modules/system-dependent.nix; system-dependent = import modules/system-dependent.nix;
telegram-bot = import modules/telegram-bot.nix; telegram-bot = import modules/telegram-bot.nix;
go-webring = import modules/go-webring.nix; go-webring = import modules/go-webring.nix;
}; };
lib = {
};
overlays.default = final: prev: { overlays.default = final: prev: {
niveum-terminal = prev.alacritty;
niveum-browser = prev.firefox; # packaged from .bin/
niveum-filemanager = prev.pcmanfm; two56color = prev.callPackage packages/256color.nix { };
avesta = prev.callPackage packages/avesta.nix { };
bvg = prev.callPackage packages/bvg.nix { };
charinfo = prev.callPackage packages/charinfo.nix { };
chunk-pdf = prev.callPackage packages/chunk-pdf.nix { };
csv2json = prev.callPackage packages/csv2json.nix { };
fix-sd = prev.callPackage packages/fix-sd.nix { };
json2csv = prev.callPackage packages/json2csv.nix { };
mp3player-write = prev.callPackage packages/mp3player-write.nix { };
mushakkil = prev.callPackage packages/mushakkil.nix { };
nix-haddock-index = prev.callPackage packages/nix-haddock-index.nix { };
pdf-ocr = prev.callPackage packages/pdf-ocr.nix { };
prospekte = prev.callPackage packages/prospekte.nix { };
readme = prev.callPackage packages/readme.nix { };
ashell = nixpkgs-unstable.legacyPackages.${prev.system}.ashell;
# wrapped from upstream # wrapped from upstream
wrapScript = wrapScript =
@@ -193,6 +258,7 @@
auc = prev.callPackage packages/auc.nix { }; auc = prev.callPackage packages/auc.nix { };
cheat-sh = prev.callPackage packages/cheat-sh.nix { }; cheat-sh = prev.callPackage packages/cheat-sh.nix { };
brassica = prev.callPackage packages/brassica.nix { }; # TODO upstream brassica = prev.callPackage packages/brassica.nix { }; # TODO upstream
dawn-editor = prev.callPackage packages/dawn.nix { };
text2pdf = prev.callPackage packages/text2pdf.nix { }; # TODO upstream text2pdf = prev.callPackage packages/text2pdf.nix { }; # TODO upstream
wttr = prev.callPackage packages/wttr.nix { }; # TODO upstream wttr = prev.callPackage packages/wttr.nix { }; # TODO upstream
jsesh = prev.callPackage packages/jsesh.nix { }; # TODO upstream jsesh = prev.callPackage packages/jsesh.nix { }; # TODO upstream
@@ -200,14 +266,10 @@
trans = prev.callPackage packages/trans.nix { }; # TODO upstream trans = prev.callPackage packages/trans.nix { }; # TODO upstream
go-webring = prev.callPackage packages/go-webring.nix { }; # TODO upstream go-webring = prev.callPackage packages/go-webring.nix { }; # TODO upstream
stag = prev.callPackage packages/stag.nix { }; # TODO upstream stag = prev.callPackage packages/stag.nix { }; # TODO upstream
mpv = prev.mpv.override {
scripts = [
final.mpvScripts.visualizer
final.mpvScripts.mpris
];
};
morris = prev.callPackage packages/morris.nix { }; morris = prev.callPackage packages/morris.nix { };
cro = prev.callPackage packages/cro.nix { }; cro = prev.callPackage packages/cro.nix { };
exodus = prev.callPackage packages/exodus.nix { };
picoclaw = prev.callPackage packages/picoclaw.nix { };
dmenu = prev.writers.writeDashBin "dmenu" ''exec ${final.rofi}/bin/rofi -dmenu "$@"''; dmenu = prev.writers.writeDashBin "dmenu" ''exec ${final.rofi}/bin/rofi -dmenu "$@"'';
weechatScripts = prev.weechatScripts // { weechatScripts = prev.weechatScripts // {
hotlist2extern = prev.callPackage packages/weechatScripts/hotlist2extern.nix { }; # TODO upstream hotlist2extern = prev.callPackage packages/weechatScripts/hotlist2extern.nix { }; # TODO upstream
@@ -227,6 +289,24 @@
vim-reason-plus = prev.callPackage packages/vimPlugins/vim-reason-plus.nix { }; # TODO upstream vim-reason-plus = prev.callPackage packages/vimPlugins/vim-reason-plus.nix { }; # TODO upstream
}; };
# packaged from inputs
opencrow = opencrow.packages.${prev.stdenv.hostPlatform.system}.opencrow;
wetter = wetter.packages.${prev.stdenv.hostPlatform.system}.wetter;
agenix = agenix.packages.${prev.stdenv.hostPlatform.system}.default;
pun-sort-api = scripts.packages.${prev.stdenv.hostPlatform.system}.pun-sort-api;
alarm = scripts.packages.${prev.stdenv.hostPlatform.system}.alarm;
menstruation-telegram =
menstruation-telegram.packages.${prev.stdenv.hostPlatform.system}.menstruation-telegram;
menstruation-backend =
menstruation-backend.packages.${prev.stdenv.hostPlatform.system}.menstruation-backend;
telebots = telebots.packages.${prev.stdenv.hostPlatform.system}.telebots;
pi-llm = llm-agents.packages.${prev.stdenv.hostPlatform.system}.pi;
hesychius = scripts.packages.${prev.stdenv.hostPlatform.system}.hesychius;
autorenkalender = autorenkalender.packages.${prev.stdenv.hostPlatform.system}.default;
onomap = scripts.packages.${prev.stdenv.hostPlatform.system}.onomap;
tinc-graph = tinc-graph.packages.${prev.stdenv.hostPlatform.system}.tinc-graph;
meteora-website = meteora.packages.${prev.stdenv.hostPlatform.system}.website;
# krebs # krebs
brainmelter = prev.callPackage packages/brainmelter.nix { }; brainmelter = prev.callPackage packages/brainmelter.nix { };
cyberlocker-tools = prev.callPackage packages/cyberlocker-tools.nix { }; cyberlocker-tools = prev.callPackage packages/cyberlocker-tools.nix { };
@@ -235,9 +315,14 @@
radio-news = prev.callPackage packages/radio-news { }; radio-news = prev.callPackage packages/radio-news { };
untilport = prev.callPackage packages/untilport.nix { }; untilport = prev.callPackage packages/untilport.nix { };
weechat-declarative = prev.callPackage packages/weechat-declarative.nix { }; weechat-declarative = prev.callPackage packages/weechat-declarative.nix { };
pi = prev.callPackage packages/pi {
pkgs = final;
inherit wrappers;
};
# my packages # my packages
betacode = prev.callPackage packages/betacode.nix { }; betacode = prev.callPackage packages/betacode.nix { };
bring-out-the-gimp = prev.callPackage packages/gimp.nix { };
closest = prev.callPackage packages/closest { }; closest = prev.callPackage packages/closest { };
default-gateway = prev.callPackage packages/default-gateway.nix { }; default-gateway = prev.callPackage packages/default-gateway.nix { };
depp = prev.callPackage packages/depp.nix { }; depp = prev.callPackage packages/depp.nix { };
@@ -269,6 +354,7 @@
notemenu = prev.callPackage packages/notemenu.nix { }; notemenu = prev.callPackage packages/notemenu.nix { };
obsidian-vim = prev.callPackage packages/obsidian-vim.nix { }; obsidian-vim = prev.callPackage packages/obsidian-vim.nix { };
vim-typewriter = prev.callPackage packages/vim-typewriter.nix { }; vim-typewriter = prev.callPackage packages/vim-typewriter.nix { };
vim-email = prev.callPackage packages/vim-email.nix { };
polyglot = prev.callPackage packages/polyglot.nix { }; polyglot = prev.callPackage packages/polyglot.nix { };
q = prev.callPackage packages/q.nix { }; q = prev.callPackage packages/q.nix { };
qrpaste = prev.callPackage packages/qrpaste.nix { }; qrpaste = prev.callPackage packages/qrpaste.nix { };
@@ -278,181 +364,193 @@
swallow = prev.callPackage packages/swallow.nix { }; swallow = prev.callPackage packages/swallow.nix { };
tocharian-font = prev.callPackage packages/tocharian-font.nix { }; tocharian-font = prev.callPackage packages/tocharian-font.nix { };
ttspaste = prev.callPackage packages/ttspaste.nix { }; ttspaste = prev.callPackage packages/ttspaste.nix { };
niveum-ssh = prev.callPackage packages/niveum-ssh.nix { };
try-connect = prev.callPackage packages/try-connect.nix { };
unicodmenu = prev.callPackage packages/unicodmenu.nix { }; unicodmenu = prev.callPackage packages/unicodmenu.nix { };
vg = prev.callPackage packages/vg.nix { }; vg = prev.callPackage packages/vg.nix { };
vim-kmein = prev.callPackage packages/vim-kmein { }; vim-kmein = prev.callPackage packages/vim-kmein { };
vimv = prev.callPackage packages/vimv.nix { };
klem = prev.callPackage packages/klem.nix { }; klem = prev.callPackage packages/klem.nix { };
yt-dlp-master = prev.callPackage packages/yt-dlp-master.nix { };
lib = lib // { lib = lib // {
niveum = import lib/default.nix { niveum = import lib/default.nix {
inherit lib; inherit lib;
pkgs = final; pkgs = final;
}; };
panoptikon = import lib/panoptikon.nix {
inherit lib;
pkgs = final;
};
}; };
}; };
nixosConfigurations = nixosConfigurations =
let let
niveumSpecialArgs = system: { profiles.default = [
unstablePackages = import nixpkgs-unstable { { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; }
inherit system; {
overlays = [ ]; nixpkgs.overlays = [
config.allowUnfreePredicate = self.overlays.default
pkg: niphas.overlays.default
builtins.elem (nixpkgs-unstable.lib.getName pkg) [ panoptikon.overlays.default
"obsidian" (final: prev: {
"zoom" niphas-git =
(prev.niphas-git.passthru.configuration.apply {
settings = {
user.name = prev.lib.niveum.kieran.name;
user.email = prev.lib.niveum.kieran.email;
};
}).wrapper;
niphas-editor = prev.niphas-editor.override {
withCopilot = true;
colorscheme = "base16-gruvbox-dark-medium";
};
})
];
}
{
system.autoUpgrade = {
enable = true;
flake = self.outPath;
flags = [
"--print-build-logs"
]; ];
}; dates = "02:00";
inputs = { randomizedDelaySec = "45min";
inherit };
tinc-graph }
self agenix.nixosModules.default
telebots retiolum.nixosModules.retiolum
menstruation-telegram nix-topology.nixosModules.default
menstruation-backend niphas.nixosModules.nix
scripts niphas.nixosModules.shell
coptic-dictionary configs/mycelium.nix
agenix configs/tor.nix
recht configs/retiolum.nix
autorenkalender configs/spacetime.nix
nixpkgs configs/sshd.nix
wallpaper-generator ];
; profiles.desktop = [
}; niphas.nixosModules.editor
}; niphas.nixosModules.git
niphas.nixosModules.udiskie
niphas.nixosModules.desktop
home-manager.nixosModules.home-manager
nix-index-database.nixosModules.default
nur.modules.nixos.default
stylix.nixosModules.stylix
self.nixosModules.system-dependent
self.nixosModules.power-action
];
profiles.server = [
configs/save-space.nix
configs/monitoring.nix
self.nixosModules.passport
];
in in
{ {
ful = nixpkgs.lib.nixosSystem rec { ful = nixpkgs.lib.nixosSystem {
system = "aarch64-linux"; system = "aarch64-linux";
specialArgs = niveumSpecialArgs system; specialArgs = { inherit self; };
modules = [ modules =
{ nixpkgs.overlays = [ self.overlays.default ]; } profiles.default
systems/ful/configuration.nix ++ profiles.server
agenix.nixosModules.default ++ [
self.nixosModules.passport systems/ful/configuration.nix
self.nixosModules.panoptikon panoptikon.nixosModules.default
self.nixosModules.go-webring self.nixosModules.go-webring
stockholm.nixosModules.reaktor2 stockholm.nixosModules.reaktor2
retiolum.nixosModules.retiolum opencrow.nixosModules.default
nur.modules.nixos.default nur.modules.nixos.default
{ nixpkgs.overlays = [ stockholm.overlays.default ]; } {
{ nixpkgs.overlays = [
_module.args.nixinate = { stockholm.overlays.default
host = "ful"; llm-agents.overlays.default
sshUser = "root"; ];
buildOn = "remote"; }
substituteOnTarget = true; ];
hermetic = false;
};
}
];
}; };
zaatar = nixpkgs.lib.nixosSystem rec { zaatar = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = niveumSpecialArgs system; specialArgs = { inherit self; };
modules = [ modules =
{ nixpkgs.overlays = [ self.overlays.default ]; } profiles.default
systems/zaatar/configuration.nix ++ profiles.server
agenix.nixosModules.default ++ [
retiolum.nixosModules.retiolum systems/zaatar/configuration.nix
]; ];
}; };
kibbeh = nixpkgs.lib.nixosSystem rec { kibbeh = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = niveumSpecialArgs system; specialArgs = { inherit self; };
modules = [ modules =
{ nixpkgs.overlays = [ self.overlays.default ]; } profiles.default
systems/kibbeh/configuration.nix ++ profiles.desktop
agenix.nixosModules.default ++ [
retiolum.nixosModules.retiolum systems/kibbeh/configuration.nix
home-manager.nixosModules.home-manager ];
];
}; };
makanek = nixpkgs.lib.nixosSystem rec { makanek = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
# for using inputs in other config files specialArgs = { inherit self; };
specialArgs = niveumSpecialArgs system; modules =
modules = [ profiles.default
{ nixpkgs.overlays = [ self.overlays.default ]; } ++ profiles.server
systems/makanek/configuration.nix ++ [
self.nixosModules.telegram-bot systems/makanek/configuration.nix
self.nixosModules.passport self.nixosModules.telegram-bot
agenix.nixosModules.default nur.modules.nixos.default
retiolum.nixosModules.retiolum ];
nur.modules.nixos.default
];
}; };
tahina = nixpkgs.lib.nixosSystem rec { tahina = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = niveumSpecialArgs system; specialArgs = { inherit self; };
modules = [ modules = profiles.default ++ [
{ nixpkgs.overlays = [ self.overlays.default ]; }
systems/tahina/configuration.nix systems/tahina/configuration.nix
agenix.nixosModules.default
retiolum.nixosModules.retiolum
]; ];
}; };
tabula = nixpkgs.lib.nixosSystem rec { tabula = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = niveumSpecialArgs system; specialArgs = { inherit self; };
modules = [ modules = profiles.default ++ [
{ nixpkgs.overlays = [ self.overlays.default ]; }
systems/tabula/configuration.nix systems/tabula/configuration.nix
agenix.nixosModules.default
retiolum.nixosModules.retiolum
]; ];
}; };
manakish = nixpkgs.lib.nixosSystem rec { manakish = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = niveumSpecialArgs system; specialArgs = { inherit self; };
modules = [ modules =
{ nixpkgs.overlays = [ self.overlays.default ]; } profiles.default
systems/manakish/configuration.nix ++ profiles.desktop
agenix.nixosModules.default ++ [
retiolum.nixosModules.retiolum systems/manakish/configuration.nix
home-manager.nixosModules.home-manager nixos-hardware.nixosModules.lenovo-thinkpad-x220
nix-index-database.nixosModules.default ];
nur.modules.nixos.default
stylix.nixosModules.stylix
];
}; };
kabsa = nixpkgs.lib.nixosSystem rec { kabsa = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = niveumSpecialArgs system; specialArgs = { inherit self; };
modules = [ modules =
{ nixpkgs.overlays = [ self.overlays.default ]; } profiles.default
systems/kabsa/configuration.nix ++ profiles.desktop
agenix.nixosModules.default ++ [
retiolum.nixosModules.retiolum systems/kabsa/configuration.nix
home-manager.nixosModules.home-manager nixos-hardware.nixosModules.lenovo-thinkpad-x230
nur.modules.nixos.default ];
nix-index-database.nixosModules.default
stylix.nixosModules.stylix
];
}; };
fatteh = nixpkgs.lib.nixosSystem rec { fatteh = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = niveumSpecialArgs system; specialArgs = { inherit self; };
modules = [ modules =
{ nixpkgs.overlays = [ self.overlays.default ]; } profiles.default
systems/fatteh/configuration.nix ++ profiles.desktop
agenix.nixosModules.default ++ [
retiolum.nixosModules.retiolum systems/fatteh/configuration.nix
home-manager.nixosModules.home-manager nixos-hardware.nixosModules.lenovo-thinkpad-t480
nur.modules.nixos.default ];
nix-index-database.nixosModules.default
stylix.nixosModules.stylix
];
}; };
}; };
formatter = eachSupportedSystem (system: nixpkgs.legacyPackages.${system}.nixfmt-tree); formatter = eachSupportedSystem (system: treefmtEval.${system}.config.build.wrapper);
checks = eachSupportedSystem (system: {
formatting = treefmtEval.${system}.config.build.check self;
});
packages = eachSupportedSystem ( packages = eachSupportedSystem (
system: system:
@@ -463,30 +561,46 @@
overlays = [ overlays = [
nur.overlays.default nur.overlays.default
self.overlays.default self.overlays.default
nix-topology.overlays.default
]; ];
}; };
in in
{ {
topology = import nix-topology {
inherit pkgs;
modules = [
{ nixosConfigurations = self.nixosConfigurations; }
];
};
inherit (pkgs) inherit (pkgs)
two56color
avesta
auc auc
betacode betacode
booksplit booksplit
brainmelter brainmelter
brassica brassica
bvg
charinfo
cheat-sh cheat-sh
chunk-pdf
closest closest
cro cro
csv2json
cyberlocker-tools cyberlocker-tools
dawn-editor
default-gateway default-gateway
depp depp
devanagari devanagari
devour devour
dmenu-randr dmenu-randr
emailmenu emailmenu
exodus
fkill fkill
fix-sd
fzfmenu fzfmenu
gfs-fonts gfs-fonts
gimp bring-out-the-gimp
go-webring go-webring
hc hc
heuretes heuretes
@@ -494,6 +608,7 @@
image-convert-tolino image-convert-tolino
ipa ipa
jsesh jsesh
json2csv
kirciuoklis kirciuoklis
klem klem
kpaste kpaste
@@ -502,23 +617,31 @@
mansplain mansplain
manual-sort manual-sort
morris morris
mp3player-write
mpv-iptv mpv-iptv
mpv-radio mpv-radio
mpv-tuner mpv-tuner
mpv-tv mpv-tv
mushakkil
new-mac new-mac
niveum-ssh
nix-git nix-git
nix-haddock-index
noise-waves noise-waves
notemenu notemenu
obsidian-vim obsidian-vim
opustags opustags
pdf-ocr
pi
picoclaw
pls pls
polyglot polyglot
prospekte
q q
qrpaste qrpaste
radio-news radio-news
radioStreams
random-zeno random-zeno
readme
rfc rfc
scanned scanned
stag stag
@@ -528,17 +651,24 @@
timer timer
tocharian-font tocharian-font
trans trans
try-connect
ttspaste ttspaste
unicodmenu unicodmenu
untilport untilport
vg vg
vim-kmein vim-kmein
vim-typewriter vim-typewriter
vimv vim-email
weechat-declarative weechat-declarative
wttr wttr
yt-dlp-master
; ;
} }
); );
}; };
nixConfig = {
extra-substituters = [ "https://cache.numtide.com" ];
extra-trusted-public-keys = [ "niks3.numtide.com-1:DTx8wZduET09hRmMtKdQDxNNthLQETkc/yaX7M4qK0g=" ];
};
} }

View File

@@ -1,6 +1,6 @@
{ lib, pkgs }: { lib, pkgs }:
let let
systems = import ./systems.nix; machines = import ./machines.nix;
in in
{ {
tmpfilesConfig = tmpfilesConfig =
@@ -54,35 +54,23 @@ in
sshPort = 22022; sshPort = 22022;
theme = {
gtk = {
name = "Adwaita-dark";
package = pkgs.gnome-themes-extra;
};
icon = {
name = "Adwaita";
package = pkgs.adwaita-icon-theme;
};
cursor = {
name = "capitaine-cursors-white";
package = pkgs.capitaine-cursors;
};
};
retiolumAddresses = lib.mapAttrs (_: v: { inherit (v.retiolum) ipv4 ipv6; }) ( retiolumAddresses = lib.mapAttrs (_: v: { inherit (v.retiolum) ipv4 ipv6; }) (
lib.filterAttrs (_: v: v ? "retiolum") systems lib.filterAttrs (_: v: v ? "retiolum") machines
); );
externalNetwork = lib.mapAttrs (_: v: v.externalIp) ( externalNetwork = lib.mapAttrs (_: v: v.externalIp) (
lib.filterAttrs (_: v: v ? "externalIp") systems lib.filterAttrs (_: v: v ? "externalIp") machines
); );
localAddresses = lib.mapAttrs (_: v: v.internalIp) ( localAddresses = lib.mapAttrs (_: v: v.internalIp) (
lib.filterAttrs (_: v: v ? "internalIp") systems lib.filterAttrs (_: v: v ? "internalIp") machines
); );
myceliumAddresses = lib.mapAttrs (_: v: v.mycelium.ipv6) ( myceliumAddresses = lib.mapAttrs (_: v: v.mycelium.ipv6) (
lib.filterAttrs (_: v: v ? "mycelium") systems lib.filterAttrs (_: v: v ? "mycelium") machines
);
torAddresses = lib.mapAttrs (_: v: v.torAddress) (
lib.filterAttrs (_: v: v ? "torAddress") machines
); );
syncthingIds = lib.mapAttrs (_: v: { id = v.syncthingId; }) ( syncthingIds = lib.mapAttrs (_: v: { id = v.syncthingId; }) (
lib.filterAttrs (_: v: v ? "syncthingId") systems lib.filterAttrs (_: v: v ? "syncthingId") machines
); );
email = email =
@@ -102,7 +90,7 @@ in
}; };
}; };
systems = systems; machines = machines;
kieran = { kieran = {
github = "kmein"; github = "kmein";
@@ -120,9 +108,9 @@ in
"" ""
]; ];
sshKeys = [ sshKeys = [
systems.fatteh.sshKey machines.fatteh.sshKey
systems.manakish.sshKey machines.manakish.sshKey
systems.kabsa.sshKey machines.kabsa.sshKey
]; ];
}; };

View File

@@ -1,30 +1,45 @@
let
sshPort = 22022;
in
{ {
kabsa = { kabsa = {
sshKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDyTnGhFq0Q+vghNhrqNrAyY+CsN7nNz8bPfiwIwNpjk"; sshKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDyTnGhFq0Q+vghNhrqNrAyY+CsN7nNz8bPfiwIwNpjk";
internalIp = "192.168.0.209";
syncthingId = "R6DEBD7-G5RYDKN-VFA3HPO-WX4DNVI-373F7OQ-AW5MZTT-3L4BDVW-Y6ROEAF"; syncthingId = "R6DEBD7-G5RYDKN-VFA3HPO-WX4DNVI-373F7OQ-AW5MZTT-3L4BDVW-Y6ROEAF";
retiolum = { retiolum = {
ipv4 = "10.243.2.4"; ipv4 = "10.243.2.4";
ipv6 = "42:0:3c46:861f:a118:8e9a:82c9:3d"; ipv6 = "42:0:3c46:861f:a118:8e9a:82c9:3d";
}; };
mycelium.ipv6 = "432:e30:d5d8:9311:e34b:6587:96ee:3fcb"; mycelium.ipv6 = "432:e30:d5d8:9311:e34b:6587:96ee:3fcb";
torAddress = "uwhxlsrkumxfjygdpoa556xs33jafcyq7gcifbdgscsoimbo5wbbksyd.onion";
inherit sshPort;
system = "x86_64-linux";
}; };
manakish = { manakish = {
sshKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOiQEc8rTr7C7xVLYV7tQ99BDDBLrJsy5hslxtCEatkB"; sshKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOiQEc8rTr7C7xVLYV7tQ99BDDBLrJsy5hslxtCEatkB";
internalIp = "192.168.0.237";
syncthingId = "AJVBWR2-VFFAGZF-7ZF5JAX-T63GMOG-NZ446WK-MC5E6WK-6X6Q2HE-QQA2JQ3"; syncthingId = "AJVBWR2-VFFAGZF-7ZF5JAX-T63GMOG-NZ446WK-MC5E6WK-6X6Q2HE-QQA2JQ3";
retiolum = { retiolum = {
ipv4 = "10.243.2.85"; ipv4 = "10.243.2.85";
ipv6 = "42:0:3c46:ac99:ae36:cb8:c551:ba27"; ipv6 = "42:0:3c46:ac99:ae36:cb8:c551:ba27";
}; };
mycelium.ipv6 = "512:d3bd:3cd9:fcc8:ae34:81fa:385f:8c21"; mycelium.ipv6 = "512:d3bd:3cd9:fcc8:ae34:81fa:385f:8c21";
torAddress = "wyc6ci4obq5huqhtop2omdkqipbq2tf7bz3wqxmsnfkwwrxvaesdepad.onion";
inherit sshPort;
system = "x86_64-linux";
}; };
fatteh = { fatteh = {
sshKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIByreBjBEMJKjgpKLd5XZHIUUwIhNafVqN6OUOQpJa3y"; sshKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIByreBjBEMJKjgpKLd5XZHIUUwIhNafVqN6OUOQpJa3y";
internalIp = "192.168.0.59";
syncthingId = "GSOGYT3-2GBHZXT-MNCTDIY-3BJIR4V-OHVOOMJ-ICVLKXR-U4C7RFB-HJOK3AC"; syncthingId = "GSOGYT3-2GBHZXT-MNCTDIY-3BJIR4V-OHVOOMJ-ICVLKXR-U4C7RFB-HJOK3AC";
retiolum = { retiolum = {
ipv6 = "42:0:3c46:aa73:82b0:14d7:7bf8:bf2"; ipv6 = "42:0:3c46:aa73:82b0:14d7:7bf8:bf2";
ipv4 = "10.243.2.77"; ipv4 = "10.243.2.77";
}; };
torAddress = "uoe7poyeliuaudf4x5nrwvs3t55ldcdpfqfyeqsadbs77ttjx7upquyd.onion";
mycelium.ipv6 = "463:a0d4:daa3:aa8d:a9b1:744a:46a5:7a80"; mycelium.ipv6 = "463:a0d4:daa3:aa8d:a9b1:744a:46a5:7a80";
inherit sshPort;
system = "x86_64-linux";
}; };
kibbeh = { kibbeh = {
syncthingId = "HLQSG3D-WSKLA6S-MEYQ3EU-GDBGABE-PY53RQ6-SWQAP2I-Z5MVBVX-MYPJXAM"; syncthingId = "HLQSG3D-WSKLA6S-MEYQ3EU-GDBGABE-PY53RQ6-SWQAP2I-Z5MVBVX-MYPJXAM";
@@ -36,13 +51,20 @@
ipv6 = "42:0:3c46:2c8b:a564:1213:9fb4:1bc4"; ipv6 = "42:0:3c46:2c8b:a564:1213:9fb4:1bc4";
}; };
mycelium.ipv6 = "5bf:d60e:bebf:5163:f495:8787:880c:6d41"; mycelium.ipv6 = "5bf:d60e:bebf:5163:f495:8787:880c:6d41";
torAddress = "ll3k2akcpwuo562hlbr452yvzhi6kmpjzcnjgw6z4nege2yftspgjjad.onion";
inherit sshPort;
system = "aarch64-linux";
}; };
zaatar = { zaatar = {
internalIp = "192.168.0.47";
retiolum = { retiolum = {
ipv4 = "10.243.2.34"; ipv4 = "10.243.2.34";
ipv6 = "42:0:3c46:156e:10b6:3bd6:6e82:b2cd"; ipv6 = "42:0:3c46:156e:10b6:3bd6:6e82:b2cd";
}; };
mycelium.ipv6 = "5c5:49e0:7793:f017:59e1:1715:9e0e:3fc8"; mycelium.ipv6 = "5c5:49e0:7793:f017:59e1:1715:9e0e:3fc8";
torAddress = "hurgxlejplh7lj2hyaj4gk2fuearibst6axdxl2ekfohiivyiab3gkad.onion";
inherit sshPort;
system = "x86_64-linux";
}; };
makanek = { makanek = {
externalIp = "88.99.83.173"; externalIp = "88.99.83.173";
@@ -51,6 +73,9 @@
ipv6 = "42:0:3c46:f7a9:1f0a:1b2b:822a:6050"; ipv6 = "42:0:3c46:f7a9:1f0a:1b2b:822a:6050";
}; };
mycelium.ipv6 = "43f:ad4f:fa67:d9f7:8a56:713c:7418:164b"; mycelium.ipv6 = "43f:ad4f:fa67:d9f7:8a56:713c:7418:164b";
torAddress = "gnaoacvkhovpllpiwi4a4mbnx4awpdcufwtsj365tiweybdeec7thuyd.onion";
inherit sshPort;
system = "x86_64-linux";
}; };
officejet = { officejet = {
internalIp = "192.168.0.251"; internalIp = "192.168.0.251";
@@ -63,11 +88,15 @@
ipv4 = "10.243.2.78"; ipv4 = "10.243.2.78";
ipv6 = ""; ipv6 = "";
}; };
inherit sshPort;
system = "x86_64-linux";
}; };
tahina = { tahina = {
retiolum = { retiolum = {
ipv4 = "10.243.2.74"; ipv4 = "10.243.2.74";
ipv6 = "42:0:3c46:2923:1c90:872:edd6:306"; ipv6 = "42:0:3c46:2923:1c90:872:edd6:306";
}; };
inherit sshPort;
system = "x86_64-linux";
}; };
} }

View File

@@ -1,47 +0,0 @@
{
pkgs,
lib,
...
}:
{
# watcher scripts
url =
address:
pkgs.writers.writeDash "watch-url" ''
${pkgs.curl}/bin/curl -sSL ${lib.escapeShellArg address} \
| ${pkgs.python3Packages.html2text}/bin/html2text --decode-errors=ignore
'';
urlSelector =
selector: address:
pkgs.writers.writeDash "watch-url-selector" ''
${pkgs.curl}/bin/curl -sSL ${lib.escapeShellArg address} \
| ${pkgs.htmlq}/bin/htmlq ${lib.escapeShellArg selector} \
| ${pkgs.python3Packages.html2text}/bin/html2text
'';
urlJSON =
{
jqScript ? ".",
}:
address:
pkgs.writers.writeDash "watch-url-json" ''
${pkgs.curl}/bin/curl -sSL ${lib.escapeShellArg address} | ${pkgs.jq}/bin/jq -f ${pkgs.writeText "script.jq" jqScript}
'';
# reporter scripts
kpaste-irc =
{
target,
retiolumLink ? false,
server ? "irc.r",
messagePrefix ? "change detected: ",
nick ? ''"$PANOPTIKON_WATCHER"-watcher'',
}:
pkgs.writers.writeDash "kpaste-irc-reporter" ''
KPASTE_CONTENT_TYPE=text/plain ${pkgs.kpaste}/bin/kpaste \
| ${pkgs.gnused}/bin/sed -n "${if retiolumLink then "2" else "3"}s/^/${messagePrefix}/p" \
| ${pkgs.nur.repos.mic92.ircsink}/bin/ircsink \
--nick ${nick} \
--server ${server} \
--target ${target}
'';
}

View File

@@ -1,123 +0,0 @@
{
config,
lib,
pkgs,
...
}:
{
options.services.panoptikon = {
enable = lib.mkEnableOption "Generic command output / website watcher";
watchers = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (watcher: {
options = {
script = lib.mkOption {
type = lib.types.path;
description = ''
A script whose stdout is to be watched.
'';
example = ''
pkgs.writers.writeDash "github-meta" '''
''${pkgs.curl}/bin/curl -sSL https://api.github.com/meta | ''${pkgs.jq}/bin/jq
'''
'';
};
frequency = lib.mkOption {
type = lib.types.str;
description = ''
How often to run the script. See systemd.time(7) for more information about the format.
'';
example = "*:0/3";
default = "daily";
};
loadCredential = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = ''
This can be used to pass secrets to the systemd service without adding them to the nix store.
'';
default = [ ];
};
reporters = lib.mkOption {
type = lib.types.listOf lib.types.path;
description = ''
A list of scripts that take the diff (if any) via stdin and report it (e.g. to IRC, Telegram or Prometheus). The name of the watcher will be in the $PANOPTIKON_WATCHER environment variable.
'';
example = ''
[
(pkgs.writers.writeDash "telegram-reporter" '''
''${pkgs.curl}/bin/curl -X POST https://api.telegram.org/bot''${TOKEN}/sendMessage \
-d chat_id=123456 \
-d text="$(cat)"
''')
(pkgs.writers.writeDash "notify" '''
''${pkgs.libnotify}/bin/notify-send "$PANOPTIKON_WATCHER has changed."
''')
]
'';
};
};
config = { };
})
);
};
};
config =
let
cfg = config.services.panoptikon;
in
lib.mkIf cfg.enable {
users.extraUsers.panoptikon = {
isSystemUser = true;
createHome = true;
home = "/var/lib/panoptikon";
group = "panoptikon";
};
users.extraGroups.panoptikon = { };
systemd.timers = lib.attrsets.mapAttrs' (
watcherName: _:
lib.nameValuePair "panoptikon-${watcherName}" {
timerConfig.RandomizedDelaySec = toString (60 * 60);
}
) cfg.watchers;
systemd.services = lib.attrsets.mapAttrs' (
watcherName: watcherOptions:
lib.nameValuePair "panoptikon-${watcherName}" {
enable = true;
startAt = watcherOptions.frequency;
serviceConfig = {
Type = "oneshot";
User = "panoptikon";
Group = "panoptikon";
WorkingDirectory = "/var/lib/panoptikon";
RestartSec = toString (60 * 60);
Restart = "on-failure";
LoadCredential = watcherOptions.loadCredential;
};
unitConfig = {
StartLimitIntervalSec = "300";
StartLimitBurst = "5";
};
environment.PANOPTIKON_WATCHER = watcherName;
wants = [ "network-online.target" ];
script = ''
set -fux
${watcherOptions.script} > ${lib.escapeShellArg watcherName}
diff_output=$(${pkgs.diffutils}/bin/diff --new-file ${
lib.escapeShellArg (watcherName + ".old")
} ${lib.escapeShellArg watcherName} || :)
if [ -n "$diff_output" ]
then
${lib.strings.concatMapStringsSep "\n" (
reporter: ''echo "$diff_output" | ${reporter} || :''
) watcherOptions.reporters}
fi
mv ${lib.escapeShellArg watcherName} ${lib.escapeShellArg (watcherName + ".old")}
'';
}
) cfg.watchers;
};
}

View File

@@ -1,73 +0,0 @@
{
config,
pkgs,
lib,
...
}:
with lib;
let
netname = "retiolum";
cfg = config.networking.retiolum;
in
{
options = {
networking.retiolum.ipv4 = mkOption {
type = types.str;
description = ''
own ipv4 address
'';
};
networking.retiolum.ipv6 = mkOption {
type = types.str;
description = ''
own ipv6 address
'';
};
networking.retiolum.nodename = mkOption {
type = types.str;
default = config.networking.hostName;
description = ''
tinc network name
'';
};
};
config = {
services.tinc.networks.${netname} = {
name = cfg.nodename;
hosts = builtins.mapAttrs (name: _: builtins.readFile "${<retiolum/hosts>}/${name}") (
builtins.readDir <retiolum/hosts>
);
rsaPrivateKeyFile = toString <system-secrets/retiolum.key>;
ed25519PrivateKeyFile = toString <system-secrets/retiolum.ed25519>;
extraConfig = ''
LocalDiscovery = yes
AutoConnect = yes
'';
};
networking.extraHosts = builtins.readFile (toString <retiolum/etc.hosts>);
environment.systemPackages = [ config.services.tinc.networks.${netname}.package ];
networking.firewall = {
allowedTCPPorts = [ 655 ];
allowedUDPPorts = [ 655 ];
};
#services.netdata.portcheck.checks.tinc.port = 655;
systemd.network = {
enable = true;
networks = {
"${netname}".extraConfig = ''
[Match]
Name = tinc.${netname}
[Network]
Address=${cfg.ipv4}/12
Address=${cfg.ipv6}/16
'';
};
};
};
}

37
packages/256color.nix Normal file
View File

@@ -0,0 +1,37 @@
{
writers,
}:
writers.writeDashBin "256color" ''
pl() {
for i in $(seq $1 $(expr $2 - 1)); do
printf '\e[38;5;%sm%03i\e[m ' $i $i
done
printf '\e[38;5;%sm%03i\e[m\n' $2 $2
}
p() {
printf '\e[38;5;%sm%03i\e[m ' $1 $1
}
p6x6() {
for i in $(seq 0 5); do
for j in $(seq 0 5); do
p $(expr $1 + $i + $j \* 6)
done
echo
done
}
pl 0 7
pl 8 15
p6x6 16
p6x6 52
p6x6 88
p6x6 124
p6x6 160
p6x6 196
pl 232 243
pl 244 255
''

View File

@@ -0,0 +1,38 @@
{
runCommand,
fetchurl,
imagemagick,
colors,
}:
let
backgroundColor = colors.withHashtag.base06;
foregroundColor = colors.withHashtag.base01;
width = 1920;
height = 1080;
svgUrl = "https://applicative.systems/_astro/logo-full.D8zRvqBZ.svg";
logoSvg = fetchurl {
url = svgUrl;
hash = "sha256-qXDIEZsAPn4eUJ3kb5U6L3PMUCtWGYqhqyIaBt7FntE=";
};
in
runCommand "applicative-wallpaper.png"
{
nativeBuildInputs = [ imagemagick ];
}
''
# 1. We use -background to set the canvas color
# 2. We use -fuzz and -opaque to replace the logo's internal colors
# 3. We use -gravity and -extent to center it on a wallpaper-sized canvas
convert \
-background none \
-density 300 \
"${logoSvg}" \
-fuzz 100% -fill "${foregroundColor}" -opaque black \
-resize 800x800 \
-gravity center \
-background "${backgroundColor}" \
-extent ${toString width}x${toString height} \
$out
''

66
packages/avesta.nix Normal file
View File

@@ -0,0 +1,66 @@
# Transliterate Latin-script Avestan to Avestan Unicode script
{
lib,
writers,
gnused,
}:
let
sedScript = builtins.toFile "avesta.sed" ''
s/ā̊/𐬃/g
s/t̰/𐬝/g
s/̌/𐬴/g
s/š́/𐬳/g
s/ą̄/𐬅/g
s/ŋ/𐬤/g
s/ə̄/𐬇/g
s/ŋ́/𐬣/g
s/x́/𐬒/g
s/x/𐬓/g
s/a/𐬀/g
s/ā/𐬁/g
s/å/𐬂/g
s/ą/𐬄/g
s/ə/𐬆/g
s/e/𐬈/g
s/ē/𐬉/g
s/o/𐬊/g
s/ō/𐬋/g
s/i/𐬌/g
s/ī/𐬍/g
s/u/𐬎/g
s/ū/𐬏/g
s/k/𐬐/g
s/x/𐬑/g
s/g/𐬔/g
s/ġ/𐬕/g
s/γ/𐬖/g
s/c/𐬗/g
s/j/𐬘/g
s/t/𐬙/g
s/θ/𐬚/g
s/d/𐬛/g
s/δ/𐬜/g
s/p/𐬞/g
s/f/𐬟/g
s/b/𐬠/g
s/β/𐬡/g
s/ŋ/𐬢/g
s/n/𐬥/g
s/ń/𐬦/g
s//𐬧/g
s/m/𐬨/g
s/m̨/𐬩/g
s//𐬫/g
s/y/𐬪/g
s/v/𐬬/g
s/r/𐬭/g
s/s/𐬯/g
s/z/𐬰/g
s/š/𐬱/g
s/ž/𐬲/g
s/h/𐬵/g
'';
in
writers.writeDashBin "avesta" ''
exec ${lib.getExe gnused} -f ${sedScript} "$@"
''

52
packages/bvg.nix Normal file
View File

@@ -0,0 +1,52 @@
# Berlin BVG transit disruption checker
{
lib,
writers,
curl,
jq,
}:
writers.writeDashBin "bvg" ''
${lib.getExe curl} -sSL 'https://www.bvg.de/disruption-reports/q' \
--data-raw '{"variables":{},"query":"{
allDisruptions {
disruptions {
meldungsId
linie
verkehrsmittel
__typename
... on Traffic {
datum
gueltigVonDatum
gueltigVonZeit
gueltigBisDatum
gueltigBisZeit
richtungName
richtungHafasId
beginnAbschnittName
beginnAbschnittHafasId
endeAbschnittName
endeAbschnittHafasId
textIntUrsache
sev
textIntAuswirkung
umfahrung
textWAPSMSUrsache
textWAPSMSAuswirkung
prioritaet
__typename
}
}
__typename
}
}"}' \
| ${lib.getExe jq} --arg interesting "$interesting" '
.data.allDisruptions.disruptions
| map(select(
(.linie as $linie
| $interesting
| split(" ")
| index($linie))
and (.["__typename"] == "Traffic")
))
'
''

17
packages/charinfo.nix Normal file
View File

@@ -0,0 +1,17 @@
# Print Unicode character info for each character on stdin
{
writers,
python3,
}:
writers.writePython3Bin "charinfo" {
flakeIgnore = [ "E501" "E722" ];
} ''
import sys
import unicodedata
for index, character in enumerate(sys.stdin.read().strip()):
try:
print(index, character, hex(ord(character)), unicodedata.category(character), unicodedata.name(character))
except Exception:
print(index, character, hex(ord(character)))
''

31
packages/chunk-pdf.nix Normal file
View File

@@ -0,0 +1,31 @@
# Split a PDF into chunks of N pages
{
lib,
writers,
pdftk,
gnugrep,
coreutils,
}:
writers.writeDashBin "chunk-pdf" ''
set -efu
INPUT_FILE="''${2:?Pass the PDF path as second argument.}"
PAGES_PER_REPORT="''${1:?Pass the chunk size as first argument.}"
if [ ! -f "$INPUT_FILE" ]; then
echo >&2 "File $INPUT_FILE does not exist."
exit 1
fi
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 $(${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"
${lib.getExe pdftk} "$INPUT_FILE" cat "$start_page-$end_page" output "$output_file"
done
''

View File

@@ -4,7 +4,7 @@
haskellPackages, haskellPackages,
}: }:
writers.writeDashBin "closest" '' writers.writeDashBin "closest" ''
${ exec ${
writers.writeHaskellBin "closest" { writers.writeHaskellBin "closest" {
libraries = with haskellPackages; [ libraries = with haskellPackages; [
parallel parallel
@@ -15,7 +15,7 @@ writers.writeDashBin "closest" ''
"-O3" "-O3"
"-threaded" "-threaded"
]; ];
} (builtins.readFile ./distance.hs) } ./distance.hs
}/bin/closest +RTS -N4 -RTS --dictionary ${ }/bin/closest +RTS -N4 -RTS --dictionary ${
fetchurl { fetchurl {
url = "https://gist.github.com/MarvinJWendt/2f4f4154b8ae218600eb091a5706b5f4/raw/36b70dd6be330aa61cd4d4cdfda6234dcb0b8784/wordlist-german.txt"; url = "https://gist.github.com/MarvinJWendt/2f4f4154b8ae218600eb091a5706b5f4/raw/36b70dd6be330aa61cd4d4cdfda6234dcb0b8784/wordlist-german.txt";

View File

@@ -1,17 +1,18 @@
{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecordWildCards #-}
import Control.Arrow ((&&&)) import Control.Arrow ((&&&))
import Control.Monad (forM_) import Control.Monad (forM_)
import Control.Parallel.Strategies (using, parList, rdeepseq) import Control.Parallel.Strategies (parList, rdeepseq, using)
import Data.Char (toLower) import Data.Char (toLower)
import Data.List (sortOn) import Data.List (sortOn)
import Options.Applicative import Options.Applicative
import Text.EditDistance (levenshteinDistance, defaultEditCosts) import Text.EditDistance (defaultEditCosts, levenshteinDistance)
data Options = Options data Options = Options
{ limit :: Int { limit :: Int,
, word :: String word :: String,
, dictionary :: FilePath dictionary :: FilePath
} }
optionsParser :: Parser Options optionsParser :: Parser Options

Some files were not shown because too many files have changed in this diff Show More