zaphyra's git: nixfiles

zaphyra's nixfiles

commit adeb3088d66507366401b5d33a6ae59b1c696c9d
parent 56181a264d465d1a96c25bc1635ddd5ccd18dd45
Author: Izzie van de Haaien <izzie@transgirl.cafe>
Date: Wed, 12 Nov 2025 18:02:45 +0100

Merge pull request 'wip/void/main' (#12) from wip/void/main into main

Reviewed-on: https://git.transgirl.cafe/zaphoid/config/pulls/12
Reviewed-by: Katja Kwast <zaphyra@no-reply.transgirl.cafe>
256 files changed, 10891 insertions(+), 3673 deletions(-)
M
.gitignore
|
2
+-
M
.sops.yaml
|
21
++++++++++++++++++---
M
config/home/common/home.nix
|
11
+++++++++--
A
config/home/common/programs/app2unit.nix
|
14
++++++++++++++
M
config/home/common/programs/gpg.nix
|
16
+++++++++-------
M
config/home/common/programs/ssh.nix
|
2
++
M
config/home/common/programs/starship.nix
|
155
+------------------------------------------------------------------------------
M
config/home/void/home.nix
|
15
++++++++++++++-
A
config/home/void/impermanence.nix
|
28
++++++++++++++++++++++++++++
M
config/home/void/programs/eza.nix
|
2
++
M
config/home/void/programs/fish.nix
|
4
+++-
A
config/home/void/programs/fuzzel.nix
|
33
+++++++++++++++++++++++++++++++++
M
config/home/void/programs/git.nix
|
6
+++++-
M
config/home/void/programs/gpg.nix
|
2
++
M
config/home/void/programs/kitty.nix
|
3
++-
M
config/home/void/programs/ssh.nix
|
10
+++++++---
M
config/home/void/programs/sway.nix
|
195
+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
M
config/home/void/programs/swaylock.nix
|
6
+++---
A
config/home/void/programs/swayr.nix
|
30
++++++++++++++++++++++++++++++
M
config/home/void/programs/waybar.nix
|
356
+++++++++++++++----------------------------------------------------------------
M
config/home/void/services/gpg-agent.nix
|
9
+++++++++
M
config/home/void/services/kanshi.nix
|
2
++
M
config/home/void/services/swayidle.nix
|
33
++++++++++++++++++++++++++-------
A
config/home/void/services/syncthing.nix
|
12
++++++++++++
A
config/home/zaphyra/configure/fonts.nix
|
94
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/home/zaphyra/configure/gnome.nix
|
87
+++++++++++++++++++++++++++++++++++++++++++------------------------------------
A
config/home/zaphyra/configure/niri.nix
|
109
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/home/zaphyra/configure/xdg.nix
|
37
++++++++++++++++++++++++++++---------
M
config/home/zaphyra/gnomeExtensions/bluetoothBatteryMeter.nix
|
5
++++-
M
config/home/zaphyra/gnomeExtensions/dash-to-dock.nix
|
5
++++-
M
config/home/zaphyra/gnomeExtensions/emoji-copy.nix
|
5
++++-
M
config/home/zaphyra/gnomeExtensions/just-perfection.nix
|
5
++++-
M
config/home/zaphyra/gnomeExtensions/pip-on-top.nix
|
5
++++-
M
config/home/zaphyra/gnomeExtensions/search-light.nix
|
5
++++-
M
config/home/zaphyra/gnomeExtensions/space-bar.nix
|
5
++++-
M
config/home/zaphyra/home.nix
|
29
+++++++++++++++++++++++++++--
M
config/home/zaphyra/impermanence.nix
|
2
+-
A
config/home/zaphyra/programs/airpodsctl.nix
|
18
++++++++++++++++++
M
config/home/zaphyra/programs/alacritty.nix
|
12
+++++-------
D
config/home/zaphyra/programs/ansible.nix
|
20
--------------------
M
config/home/zaphyra/programs/apostrophe.nix
|
5
++++-
M
config/home/zaphyra/programs/bat.nix
|
2
+-
M
config/home/zaphyra/programs/bitwarden-cli.nix
|
5
++++-
M
config/home/zaphyra/programs/celluloid.nix
|
13
++++++++++++-
A
config/home/zaphyra/programs/chaosctl.nix
|
20
++++++++++++++++++++
A
config/home/zaphyra/programs/chawan.nix
|
17
+++++++++++++++++
A
config/home/zaphyra/programs/cozy.nix
|
10
++++++++++
M
config/home/zaphyra/programs/deploymentUtilities.nix
|
5
++++-
A
config/home/zaphyra/programs/dino.nix
|
15
+++++++++++++++
M
config/home/zaphyra/programs/errands.nix
|
14
+++++++++-----
M
config/home/zaphyra/programs/eza.nix
|
7
+------
M
config/home/zaphyra/programs/firefox.nix
|
342
++++++++++++++++++++++++++++++++++++++++---------------------------------------
M
config/home/zaphyra/programs/fish.nix
|
9
+++++++--
M
config/home/zaphyra/programs/fractal.nix
|
18
++++++++++--------
A
config/home/zaphyra/programs/fuzzel.nix
|
33
+++++++++++++++++++++++++++++++++
A
config/home/zaphyra/programs/gajim.nix
|
16
++++++++++++++++
M
config/home/zaphyra/programs/ghostty.nix
|
4
+++-
M
config/home/zaphyra/programs/git.nix
|
16
++++++++++++++--
A
config/home/zaphyra/programs/gnome-calendar.nix
|
48
++++++++++++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/programs/gnome-obfuscate.nix
|
10
++++++++++
A
config/home/zaphyra/programs/gnome-text-editor.nix
|
22
++++++++++++++++++++++
M
config/home/zaphyra/programs/gpg.nix
|
35
++---------------------------------
A
config/home/zaphyra/programs/gtklock.nix
|
20
++++++++++++++++++++
M
config/home/zaphyra/programs/helix.nix
|
16
++++++++++------
M
config/home/zaphyra/programs/htop.nix
|
12
+++++-------
M
config/home/zaphyra/programs/imv.nix
|
12
++++--------
D
config/home/zaphyra/programs/javascript.nix
|
14
--------------
A
config/home/zaphyra/programs/languages/golang.nix
|
17
+++++++++++++++++
A
config/home/zaphyra/programs/languages/javascript.nix
|
19
+++++++++++++++++++
A
config/home/zaphyra/programs/languages/nimlang.nix
|
20
++++++++++++++++++++
A
config/home/zaphyra/programs/languages/nix.nix
|
25
+++++++++++++++++++++++++
M
config/home/zaphyra/programs/libreoffice.nix
|
19
+++++--------------
A
config/home/zaphyra/programs/loupe.nix
|
39
+++++++++++++++++++++++++++++++++++++++
M
config/home/zaphyra/programs/mcfly.nix
|
7
+++++--
M
config/home/zaphyra/programs/micro.nix
|
232
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
M
config/home/zaphyra/programs/mpv.nix
|
7
-------
M
config/home/zaphyra/programs/nautilus.nix
|
38
+++++++++++++++++++++++++++++++-------
A
config/home/zaphyra/programs/networkManagerDmenu.nix
|
46
++++++++++++++++++++++++++++++++++++++++++++++
D
config/home/zaphyra/programs/nim.nix
|
14
--------------
A
config/home/zaphyra/programs/niri.nix
|
250
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
config/home/zaphyra/programs/nix-cleanup.nix
|
22
----------------------
A
config/home/zaphyra/programs/nmgui.nix
|
21
+++++++++++++++++++++
M
config/home/zaphyra/programs/ocrmypdf.nix
|
5
++++-
A
config/home/zaphyra/programs/overskride.nix
|
10
++++++++++
D
config/home/zaphyra/programs/paper-plane.nix
|
7
-------
M
config/home/zaphyra/programs/papers.nix
|
5
++++-
M
config/home/zaphyra/programs/password-store.nix
|
12
+++++-------
M
config/home/zaphyra/programs/pdfarranger.nix
|
5
++++-
D
config/home/zaphyra/programs/phockup.nix
|
7
-------
A
config/home/zaphyra/programs/pipewire.nix
|
61
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/programs/plattenalbum.nix
|
10
++++++++++
A
config/home/zaphyra/programs/profanity.nix
|
16
++++++++++++++++
M
config/home/zaphyra/programs/shellUtilities.nix
|
82
++++++++++++++++++++++++++++++++++++++++++-------------------------------------
A
config/home/zaphyra/programs/sherlock-launcher.nix
|
89
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/home/zaphyra/programs/ssh.nix
|
8
++++++--
A
config/home/zaphyra/programs/swaylock.nix
|
44
++++++++++++++++++++++++++++++++++++++++++++
D
config/home/zaphyra/programs/texlive.nix
|
7
-------
M
config/home/zaphyra/programs/thunderbird.nix
|
32
+++++++++++++++++++-------------
M
config/home/zaphyra/programs/tmux.nix
|
2
+-
M
config/home/zaphyra/programs/tuba.nix
|
12
++++++++----
M
config/home/zaphyra/programs/typst.nix
|
11
++++++++++-
A
config/home/zaphyra/programs/wleave.nix
|
50
++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/programs/yazi.nix
|
37
+++++++++++++++++++++++++++++++++++++
M
config/home/zaphyra/programs/yt-dlp.nix
|
2
--
M
config/home/zaphyra/programs/zathura.nix
|
5
++++-
M
config/home/zaphyra/programs/zoxide.nix
|
9
++++++++-
A
config/home/zaphyra/services/batsignal.nix
|
23
+++++++++++++++++++++++
A
config/home/zaphyra/services/dssd.nix
|
17
+++++++++++++++++
D
config/home/zaphyra/services/easyeffects.nix
|
28
----------------------------
A
config/home/zaphyra/services/gnome-keyring.nix
|
20
++++++++++++++++++++
A
config/home/zaphyra/services/gomuks-web.nix
|
27
+++++++++++++++++++++++++++
M
config/home/zaphyra/services/mako.nix
|
15
++++++---------
A
config/home/zaphyra/services/owntone.nix
|
67
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/services/playerctl.nix
|
21
+++++++++++++++++++++
A
config/home/zaphyra/services/shaderbg.nix
|
20
++++++++++++++++++++
A
config/home/zaphyra/services/swayidle.nix
|
28
++++++++++++++++++++++++++++
A
config/home/zaphyra/services/swaync.nix
|
256
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/services/swayosd.nix
|
63
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/services/syncthing.nix
|
14
++++++++++++++
M
config/home/zaphyra/services/waybar.nix
|
319
+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
M
config/home/zaphyra/services/wlsunset.nix
|
2
+-
A
config/home/zaphyra/services/wob.nix
|
39
+++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/services/wpaperd.nix
|
49
+++++++++++++++++++++++++++++++++++++++++++++++++
M
config/nixos/dns.nix
|
24
+++++++++++-------------
M
config/nixos/modules/boot/plymouth.nix
|
2
+-
M
config/nixos/modules/filesystem/impermanence.nix
|
73
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
A
config/nixos/modules/filesystem/root.nix.bak
|
138
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/nixos/modules/filesystem/rootDisk.nix
|
100
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
M
config/nixos/modules/font.nix
|
11
-----------
M
config/nixos/modules/gnomeMinimal.nix
|
172
+++++++++++++++++++++++++++++++++++++++++--------------------------------------
A
config/nixos/modules/hardware/bluetooth.nix
|
31
+++++++++++++++++++++++++++++++
M
config/nixos/modules/hardware/fprint.nix
|
11
++++++++++-
M
config/nixos/modules/hardware/quirks.nix
|
1
-
M
config/nixos/modules/hardware/smartcard.nix
|
1
-
A
config/nixos/modules/hardware/thunderbolt.nix
|
24
++++++++++++++++++++++++
D
config/nixos/modules/hardware/video/enable.nix
|
23
-----------------------
M
config/nixos/modules/hardware/video/intel.nix
|
28
+++++++++++++++-------------
M
config/nixos/modules/hardware/video/nvidia.nix
|
19
++++++++++---------
M
config/nixos/modules/homeManager.nix
|
6
+++---
A
config/nixos/modules/networking/NetworkManager.nix
|
28
++++++++++++++++++++++++++++
M
config/nixos/modules/networking/dn42.nix
|
352
+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
M
config/nixos/modules/nix/disableChannels.nix
|
1
-
M
config/nixos/modules/nix/enable.nix
|
3
++-
M
config/nixos/modules/presets/base.nix
|
57
+++++++++++++++++++++++++++++++--------------------------
M
config/nixos/modules/presets/graphical/enable.nix
|
8
++++++++
M
config/nixos/modules/presets/graphical/type.nix
|
5
++---
M
config/nixos/modules/presets/graphical/typeGnomeMinimal.nix
|
25
++++++++++++-------------
A
config/nixos/modules/presets/graphical/typeNiri.nix
|
44
++++++++++++++++++++++++++++++++++++++++++++
A
config/nixos/modules/presets/graphical/typeSway.nix
|
43
+++++++++++++++++++++++++++++++++++++++++++
A
config/nixos/modules/presets/minimal.nix
|
60
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/nixos/modules/presets/netcup.nix
|
1
-
M
config/nixos/modules/presets/networkManagerProfiles/cccdaWifi.nix
|
1
-
A
config/nixos/modules/presets/networkManagerProfiles/grogHomeWifi.nix
|
57
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/nixos/modules/presets/networkManagerProfiles/voidHomeWifi.nix
|
2
--
M
config/nixos/modules/presets/networkManagerProfiles/voidPhoneWifi.nix
|
2
--
M
config/nixos/modules/presets/networkManagerProfiles/zaphyraHomeWifi.nix
|
2
--
M
config/nixos/modules/presets/networkManagerProfiles/zaphyraPhoneWifi.nix
|
2
--
M
config/nixos/modules/presets/void/enable.nix
|
7
+++++--
A
config/nixos/modules/presets/void/stylix.nix
|
49
+++++++++++++++++++++++++++++++++++++++++++++++++
M
config/nixos/modules/presets/zaphyra/dn42.nix
|
70
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
M
config/nixos/modules/presets/zaphyra/dnsServer.nix
|
32
+++++++++++++-------------------
M
config/nixos/modules/presets/zaphyra/enable.nix
|
52
++++++++++++++--------------------------------------
M
config/nixos/modules/presets/zaphyra/mailServer.nix
|
19
+++++++++++++------
M
config/nixos/modules/presets/zaphyra/mautrixBridges/signal.nix
|
24
+++++++++++-------------
M
config/nixos/modules/presets/zaphyra/mautrixBridges/telegram.nix
|
26
++++++++++++--------------
M
config/nixos/modules/presets/zaphyra/mautrixBridges/whatsapp.nix
|
32
++++++++++++++++----------------
M
config/nixos/modules/presets/zaphyra/networkManagerProfiles/dn42.nix
|
4
+---
M
config/nixos/modules/presets/zaphyra/router/enable.nix
|
74
+++++++++++++++++++++++++++++++++++++++-----------------------------------
M
config/nixos/modules/presets/zaphyra/router/pppd.nix
|
3
---
M
config/nixos/modules/presets/zaphyra/router/systemd-networkd.nix
|
1
-
M
config/nixos/modules/presets/zaphyra/smarthome/enable.nix
|
3
---
M
config/nixos/modules/presets/zaphyra/smarthome/mosqitto.nix
|
2
--
M
config/nixos/modules/presets/zaphyra/smarthome/mqttWebUI.nix
|
2
+-
M
config/nixos/modules/presets/zaphyra/smarthome/telegraf.nix
|
2
--
M
config/nixos/modules/presets/zaphyra/smarthome/zigbee2mqtt.nix
|
2
+-
M
config/nixos/modules/presets/zaphyra/syncthing.nix
|
50
+++++++++++++++++++++++++-------------------------
A
config/nixos/modules/programs/nixUtilities.nix
|
31
+++++++++++++++++++++++++++++++
M
config/nixos/modules/programs/shellUtilities.nix
|
40
+++++++++++++++++++++++-----------------
M
config/nixos/modules/programs/steam.nix
|
5
+++--
M
config/nixos/modules/programs/yubikey.nix
|
2
--
M
config/nixos/modules/services/earlyoom.nix
|
23
+++++++++++------------
M
config/nixos/modules/services/gitolite.nix
|
62
++++++++++++++++++++++++++++++--------------------------------
D
config/nixos/modules/services/gotosocial.nix
|
198
-------------------------------------------------------------------------------
A
config/nixos/modules/services/greetd.nix
|
169
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/nixos/modules/services/gtklock.nix
|
46
++++++++++++++++++++++++++++++++++++++++++++++
A
config/nixos/modules/services/gvfs.nix
|
62
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/nixos/modules/services/keyd.nix
|
28
+++++++++++++++++++++-------
M
config/nixos/modules/services/knot.nix
|
58
++++++++++++++++++++++++++++++++--------------------------
M
config/nixos/modules/services/knotACME.nix
|
76
+++++++++++++++++++++++++++++++++++-----------------------------------------
D
config/nixos/modules/services/mautrixBridge.nix
|
156
-------------------------------------------------------------------------------
M
config/nixos/modules/services/openssh.nix
|
4
++++
A
config/nixos/modules/services/power-profiles-daemon.nix
|
27
+++++++++++++++++++++++++++
A
config/nixos/modules/services/prosody.nix
|
156
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/nixos/modules/services/rcloneResticServer.nix
|
15
+++++++--------
M
config/nixos/modules/services/resticBackup.nix
|
166
+++++++++++++++++++++++++++++++++++++------------------------------------------
A
config/nixos/modules/services/swaylock.nix
|
47
+++++++++++++++++++++++++++++++++++++++++++++++
A
config/nixos/modules/services/udisks2.nix
|
23
+++++++++++++++++++++++
A
config/nixos/modules/services/upower.nix
|
27
+++++++++++++++++++++++++++
M
config/nixos/modules/services/vnstat.nix
|
1
-
M
config/nixos/modules/sops.nix
|
1
-
M
config/nixos/modules/users/void.nix
|
23
+++++++++++++----------
M
config/nixos/modules/users/zaphyra.nix
|
43
+++++++++++++++++++++++++++++++++----------
M
config/nixos/modules/websites/bikemap.zaphyra.eu.nix
|
7
+++----
M
config/nixos/modules/websites/dav.zaphyra.eu.nix
|
15
++++++++++-----
M
config/nixos/modules/websites/fedi.ctu.cx.nix
|
245
++++++++++++++++++++++++++++++++++++++++---------------------------------------
M
config/nixos/modules/websites/fedi.home.ctu.cx.nix
|
241
+++++++++++++++++++++++++++++++++++++++----------------------------------------
M
config/nixos/modules/websites/flauschehorn.zaphyra.eu.nix
|
1
-
M
config/nixos/modules/websites/git.zaphyra.eu.nix
|
4
++--
A
config/nixos/modules/websites/gomuks.zaphyra.eu.nix
|
104
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
config/nixos/modules/websites/grafana.infra.zaphyra.eu.nix
|
2
--
M
config/nixos/modules/websites/grapevine.zaphyra.eu.nix
|
6
+++---
M
config/nixos/modules/websites/gts.zaphyra.eu.nix
|
280
+++++++++++++++++++++++++++++++++++++++++--------------------------------------
M
config/nixos/modules/websites/ip.zaphyra.eu.nix
|
124
++++++++++++++++++++++++++++++++++++++++---------------------------------------
M
config/nixos/modules/websites/katja.wtf.nix
|
1
-
M
config/nixos/modules/websites/oeffi.zaphyra.eu.nix
|
85
++++++++++++++++++++++++++++++++++++++++---------------------------------------
M
config/nixos/modules/websites/prometheus.infra.zaphyra.eu.nix
|
22
++++++++--------------
M
config/nixos/modules/websites/restic.novus.infra.zaphyra.eu.nix
|
2
--
M
config/nixos/modules/websites/things.zaphyra.eu.nix
|
7
+++++--
M
config/nixos/modules/websites/vault.zaphyra.eu.nix
|
6
+++++-
M
config/nixos/modules/websites/zaphyra.dn42.nix
|
2
--
M
config/nixosModules.nix
|
22
++++++++++------------
M
flake.lock
|
1207
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
M
flake.nix
|
215
+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
M
hosts/empty/default.nix
|
24
+++++++++++++++---------
A
hosts/eximius/configuration.nix
|
89
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
hosts/eximius/default.nix
|
180
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
hosts/eximius/hardware-configuration.nix
|
96
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
hosts/huntii/default.nix
|
34
++++++++++++++++++++++++----------
M
hosts/morio/default.nix
|
18
++++++++++++------
M
hosts/morio/dn42.nix
|
13
-------------
M
hosts/novus/default.nix
|
4
----
M
hosts/novus/dn42.nix
|
78
++++++++++++++++++++++++++++++++++++++++--------------------------------------
M
hosts/polaris/default.nix
|
6
------
A
hosts/pratorum/default.nix
|
149
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
hosts/pratorum/dn42.nix
|
49
+++++++++++++++++++++++++++++++++++++++++++++++++
D
packages/adwaita-colors-icon-theme.nix
|
41
-----------------------------------------
D
packages/chaosctl/chaosctl.fish
|
65
-----------------------------------------------------------------
D
packages/chaosctl/default.nix
|
5
-----
D
packages/gotosocial/default.nix
|
99
-------------------------------------------------------------------------------
D
packages/mautrix-telegramgo.nix
|
48
------------------------------------------------
D
packages/phanpy.nix
|
46
----------------------------------------------
M
renovate.json
|
3
+--
A
resources/patchedNixpkgsModules/fprintd.nix
|
82
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
resources/patchedNixpkgsModules/pam.nix
|
2406
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
resources/patches/gomuks-web-css.patch
|
117
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
resources/pgp/2C754046341AB6A0C3F0EF6F23100DF8D68F4FA6.asc
|
22
++++++++++++----------
M
resources/pgp/BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022.asc
|
35
+++++++++++++++++++----------------
A
resources/shaders/background1.frag
|
79
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
resources/void/programs/waybar/style.css
|
205
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
secrets/common.yaml
|
95
+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
A
secrets/eximius.yaml
|
28
++++++++++++++++++++++++++++
M
secrets/morio.yaml
|
8
++++----
M
secrets/novus.yaml
|
7
++-----
A
secrets/pratorum.yaml
|
34
++++++++++++++++++++++++++++++++++
M
secrets/zaphyra/sieve.yaml
|
33
+++++++++++----------------------
A
statix.toml
|
6
++++++
diff --git a/.gitignore b/.gitignore
@@ -2,7 +2,7 @@
 *.qcow2
 
 # Nix output
-result
+result*
 
 # nixos-anywhere extra-files
 tmp 
\ No newline at end of file
diff --git a/.sops.yaml b/.sops.yaml
@@ -1,22 +1,32 @@
 keys:
-    - &zaphyra BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022
     - &void AB27F5D1136B20D3149FBCC00389451731A3ADDD
+    - &zaphyra BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022
+    - &eximius age1lkdpl26w3wyaes75hg6wwc2p3puqv24d4xyuf5xc9q9u9we0jq6q8lvz8f
     - &huntii age1laajqafnm4ft2m73wq7yqug4ts04ddn59wlqs4t30upeqa35dpdqu8fu3n
     - &morio age1wpffcr5p88a2x9dzx5v3sq4jqurvygu94fx773n229fqk4p95qzs840cmn
     - &novus age1tud4lvpmpx5nqceyp09ls9ej8l80zlh29d8cpjxcajfnnyy85fvqs63snm
     - &polaris age1qyqy5we7zua06ppj654rgd6t7kyw3gem6hnexna98j60klyus4zq68cjlz
+    - &pratorum age13f7t27x326hamq39qps2ygrftq3ylyn2nx8xga2kqaxgra2p748sphmetv
 
 creation_rules:
     - path_regex: secrets/common\.yaml$
       key_groups:
           - age:
+                - *eximius
                 - *huntii
                 - *morio
                 - *novus
                 - *polaris
+                - *pratorum
             pgp:
-                - *zaphyra
                 - *void
+                - *zaphyra
+    - path_regex: secrets/eximius\.yaml$
+      key_groups:
+         - age:
+               - *eximius
+           pgp:
+               - *void
     - path_regex: secrets/huntii\.yaml$
       key_groups:
           - age:

@@ -35,6 +45,12 @@ creation_rules:
                 - *novus
             pgp:
                 - *zaphyra
+    - path_regex: secrets/pratorum\.yaml$
+      key_groups:
+          - age:
+                - *pratorum
+            pgp:
+                - *zaphyra
     - path_regex: secrets/polaris\.yaml$
       key_groups:
           - age:

@@ -47,4 +63,3 @@ creation_rules:
                 - *morio
             pgp:
                 - *zaphyra
-                - *void
diff --git a/config/home/common/home.nix b/config/home/common/home.nix
@@ -1,10 +1,17 @@
 {
-  lib,
+  inputs,
   ...
 }:
 
 {
 
-  home.stateVersion = lib.mkDefault "25.05";
+  imports = [
+    inputs.impermanence.homeManagerModules.impermanence
+    #inputs.stylix.homeModules.stylix
+    inputs.niriFlake.homeModules.config
+    inputs.sopsNix.homeManagerModules.sops
+    inputs.airpodsctl.homeManagerModules.kairpodsd
+    inputs.tgcNUR.homeManagerModules.default
+  ];
 
 }
diff --git a/config/home/common/programs/app2unit.nix b/config/home/common/programs/app2unit.nix
@@ -0,0 +1,14 @@
+{
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = with pkgs; [
+    unstable.app2unit
+    xdg-launch
+    xdg-terminal-exec-mkhl
+  ];
+
+}
diff --git a/config/home/common/programs/gpg.nix b/config/home/common/programs/gpg.nix
@@ -1,4 +1,5 @@
 {
+  config,
   inputs,
   pkgs,
   ...

@@ -7,6 +8,7 @@
 {
   config = {
     programs.gpg = {
+      homedir = "${config.xdg.dataHome}/gnupg";
       scdaemonSettings = {
         disable-ccid = true;
       };

@@ -17,11 +19,12 @@
         {
           # emilyyy@jagudev.net
           source = inputs.self.resources.pgp."A9D363EA211BA9CB03D1B773AA59E255A3896073";
+          trust = 4;
         }
         {
           # hannah@totient.eu
           source = inputs.self.resources.pgp."AB27F5D1136B20D3149FBCC00389451731A3ADDD";
-          trust = 4;
+          #trust = 4;
         }
         {
           #izzie@haaien.xyz

@@ -45,17 +48,16 @@
         }
         {
           # kontakt@governikus.com
-          source = (
-            pkgs.fetchurl {
-              url = "https://www.governikus.de/wp-content/uploads/2023/06/governikusPubKey.asc";
-              sha256 = "sha256-eU7g+c2CAYGLxHCRb0qsnL3CvKgK3lWcKcgrS1WFwz0=";
-            }
-          );
+          source = pkgs.fetchurl {
+            url = "https://www.governikus.de/wp-content/uploads/2023/06/governikusPubKey.asc";
+            sha256 = "sha256-eU7g+c2CAYGLxHCRb0qsnL3CvKgK3lWcKcgrS1WFwz0=";
+          };
           trust = 3;
         }
         {
           # lmv@lmv.me
           source = inputs.self.resources.pgp."2C754046341AB6A0C3F0EF6F23100DF8D68F4FA6";
+          trust = 4;
         }
       ];
     };
diff --git a/config/home/common/programs/ssh.nix b/config/home/common/programs/ssh.nix
@@ -1,3 +1,5 @@
+_:
+
 {
 
   config = {
diff --git a/config/home/common/programs/starship.nix b/config/home/common/programs/starship.nix
@@ -1,163 +1,10 @@
-{
-  lib,
-  ...
-}:
+_:
 
 {
 
   config = {
     programs.starship = {
       enable = true;
-
-      settings =
-        let
-          lang = symbol: style: format: { inherit symbol style format; };
-
-        in
-        {
-          format = lib.concatStrings [
-            "[](color_orange)"
-            "$os"
-            "$username"
-            "[](bg:color_yellow fg:color_orange)"
-            "$directory"
-            "[](fg:color_yellow bg:color_aqua)"
-            "$git_branch"
-            "$git_status"
-            "[](fg:color_aqua bg:color_blue)"
-            "$c"
-            "$rust"
-            "$golang"
-            "$nodejs"
-            "$php"
-            "$java"
-            "$kotlin"
-            "$haskell"
-            "$python"
-            "[](fg:color_blue bg:color_bg3)"
-            "$docker_context"
-            "$conda"
-            "[](fg:color_bg3 bg:color_bg1)"
-            "$time"
-            "[ ](fg:color_bg1)"
-            "$line_break$character"
-          ];
-
-          add_newline = false;
-
-          palette = "gruvbox_dark";
-
-          palettes.gruvbox_dark = {
-            color_fg0 = "#fbf1c7";
-            color_bg1 = "#3c3836";
-            color_bg3 = "#665c54";
-            color_blue = "#458588";
-            color_aqua = "#689d6a";
-            color_green = "#98971a";
-            color_orange = "#d65d0e";
-            color_purple = "#b16286";
-            color_red = "#cc241d";
-            color_yellow = "#d79921";
-          };
-
-          os = {
-            disabled = false;
-            style = "bg:color_orange fg:color_fg0";
-
-            symbols = {
-              Windows = "󰍲";
-              Ubuntu = "󰕈";
-              SUSE = "";
-              Raspbian = "󰐿";
-              Mint = "󰣭";
-              Macos = "󰀵";
-              Manjaro = "";
-              Linux = "󰌽";
-              Gentoo = "󰣨";
-              Fedora = "󰣛";
-              Alpine = "";
-              Amazon = "";
-              Android = "";
-              Arch = "󰣇";
-              Artix = "󰣇";
-              CentOS = "";
-              Debian = "󰣚";
-              Redhat = "󱄛";
-              RedHatEnterprise = "󱄛";
-            };
-          };
-
-          username = {
-            show_always = true;
-            style_user = "bg:color_orange fg:color_fg0";
-            style_root = "bg:color_orange fg:color_fg0";
-            format = "[ $user ]($style)";
-          };
-
-          directory = {
-            style = "fg:color_fg0 bg:color_yellow";
-            format = "[ $path ]($style)";
-            truncation_length = 3;
-            truncation_symbol = "…/";
-
-            substitutions = {
-              "Documents" = "󰈙 ";
-              "Downloads" = " ";
-              "Music" = "󰝚 ";
-              "Pictures" = " ";
-              "Developer" = "󰲋 ";
-            };
-          };
-
-          line_break.disabled = false;
-          status.disabled = false;
-
-          git_branch = {
-            symbol = "";
-            style = "bg:color_aqua";
-            format = "[[ $symbol $branch ](fg:color_fg0 bg:color_aqua)]($style)";
-          };
-
-          git_status = {
-            style = "bg:color_aqua";
-            format = "[[($all_status$ahead_behind )](fg:color_fg0 bg:color_aqua)]($style)";
-          };
-
-          conda = {
-            style = "bg:color_bg3";
-            format = "[[ $symbol( $environment) ](fg:#83a598 bg:color_bg3)]($style)";
-          };
-
-          time = {
-            disabled = false;
-            time_format = "%R";
-            style = "bg:color_bg1";
-            format = "[[  $time ](fg:color_fg0 bg:color_bg1)]($style)";
-          };
-
-          character = {
-            disabled = false;
-            success_symbol = "[](bold fg:color_green)";
-            error_symbol = "[](bold fg:color_red)";
-            vimcmd_symbol = "[](bold fg:color_green)";
-            vimcmd_replace_one_symbol = "[](bold fg:color_purple)";
-            vimcmd_replace_symbol = "[](bold fg:color_purple)";
-            vimcmd_visual_symbol = "[](bold fg:color_yellow)";
-          };
-
-          nodejs = lang "" "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          c = lang " " "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          rust = lang "" "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          golang = lang "" "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          php = lang "" "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          java = lang " " "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          kotlin = lang "" "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          haskell = lang "" "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          python = lang "" "bg:color_blue" "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)";
-          docker_context =
-            lang "" "bg:color_bg3"
-              "[[ $symbol( $context) ](fg:#83a598 bg:color_bg3)]($style)";
-        };
     };
   };
 
diff --git a/config/home/void/home.nix b/config/home/void/home.nix
@@ -1,6 +1,8 @@
 {
-  lib,
   homeManagerModules,
+
+  lib,
+  pkgs,
   ...
 }:
 

@@ -15,4 +17,15 @@
       (lib.attrValues void.services)
     ];
 
+  home = {
+    packages = with pkgs; [
+      thunderbird
+    ];
+    shellAliases = {
+      ",," = "comma -s";
+    };
+  };
+  programs.nh.enable = true;
+  programs.librewolf.enable = true;
+
 }
diff --git a/config/home/void/impermanence.nix b/config/home/void/impermanence.nix
@@ -0,0 +1,28 @@
+_:
+
+{
+
+  home.persistence."/nix/persist/home/void" = {
+    enable = false;
+    allowOther = true;
+    removePrefixDirectory = true;
+    directories =
+      let
+        symlink = path: {
+          method = "symlink";
+          directory = path;
+        };
+      in
+      [
+        (symlink "syncthing/Documents")
+        (symlink "syncthing/Bahn-Richtlinien")
+        (symlink "syncthing/Videos")
+        (symlink "syncthing/Pictures")
+        (symlink "syncthing/Music")
+        (symlink "syncthing/Audiobooks")
+        (symlink "data/Downloads")
+        (symlink "data/proj")
+      ];
+  };
+
+}
diff --git a/config/home/void/programs/eza.nix b/config/home/void/programs/eza.nix
@@ -1,3 +1,5 @@
+_:
+
 {
 
   config = {
diff --git a/config/home/void/programs/fish.nix b/config/home/void/programs/fish.nix
@@ -1,7 +1,9 @@
+_:
+
 {
 
   config = {
-    home.persistence."/nix/persist/home/zaphyra".directories = [
+    home.persistence."/nix/persist/home/void".directories = [
       "fish/.local/share/fish"
     ];
 
diff --git a/config/home/void/programs/fuzzel.nix b/config/home/void/programs/fuzzel.nix
@@ -0,0 +1,33 @@
+_:
+
+{
+
+  programs.fuzzel = {
+    enable = true;
+    settings = {
+      main = {
+        launch-prefix = "app2unit --fuzzel-compat --";
+        dpi-aware = false;
+        horizontal-pad = 15;
+        vertical-pad = 15;
+        inner-pad = 5;
+      };
+      border = {
+        width = 2;
+        radius = 6;
+      };
+      #colors = {
+      #  background = "#000000f0"; # Background color
+      #  text = "#d8daddff"; # Text (foreground) color of unselected entries
+      #  prompt = "#d8daddff"; # Text (foreground) color of prompt character(s)
+      #  input = "#d8daddff"; # Text (foreground) color of input string
+      #  match = "#d8daddff"; # Text (foreground) color of the matched substring
+      #  selection = "#b2a4d4ff"; # Background color of the selected entry
+      #  selection-text = "#000000ff"; # Text (foreground) color of the selected entry
+      #  selection-match = "#b7d4edf2"; # Text (foreground) color of the matched substring of the selected entry
+      #  border = "#b2a4d4ff"; # The color of the match count stats printed at the right-hand side of the input prompt
+      #};
+    };
+  };
+
+}
diff --git a/config/home/void/programs/git.nix b/config/home/void/programs/git.nix
@@ -1,4 +1,8 @@
-{ lib, pkgs, ... }:
+{
+  lib,
+  pkgs,
+  ...
+}:
 let
   inherit (lib) mkIf mkMerge;
 in
diff --git a/config/home/void/programs/gpg.nix b/config/home/void/programs/gpg.nix
@@ -1,3 +1,5 @@
+_:
+
 {
 
   config = {
diff --git a/config/home/void/programs/kitty.nix b/config/home/void/programs/kitty.nix
@@ -1,10 +1,11 @@
+_:
+
 {
   config = {
     programs.kitty = {
       enable = true;
       settings = {
         term = "xterm-256color";
-        background_opacity = "0.75";
         enableGitIntegration = true;
       };
     };
diff --git a/config/home/void/programs/ssh.nix b/config/home/void/programs/ssh.nix
@@ -1,15 +1,19 @@
+_:
+
 {
 
   config = {
     programs.ssh = {
       enable = true;
-      controlMaster = "auto";
-      controlPersist = "10m";
-      serverAliveInterval = 30;
       extraConfig = ''
         VisualHostKey yes
       '';
       matchBlocks = {
+        "*" = {
+          controlMaster = "auto";
+          controlPersist = "10m";
+          serverAliveInterval = 30;
+        };
         hortorum = {
           hostname = "37.120.168.131";
           port = 18810;
diff --git a/config/home/void/programs/sway.nix b/config/home/void/programs/sway.nix
@@ -12,9 +12,9 @@ let
   DOCK_R = "Lenovo Group Limited T23d-10 V90B7ALM";
   DOCK_L = "Lenovo Group Limited T23d-10 V90B7AL8";
 
-  ws_2 = "'2: code'";
-  ws_3 = "'3: librewolf'";
-  ws_4 = "'4: matrix'";
+  ws_2 = "'2 dev'";
+  ws_3 = "'3 web'";
+  ws_4 = "'4 com'";
 
   inherit (wayland.windowManager.sway.config) modifier;
 

@@ -22,10 +22,31 @@ in
 {
 
   config = {
+    #gtk = {
+    #enable = true;
+    #cursorTheme = {
+    #  name = "adwaita";
+    #  size = 20;
+    #};
+    #iconTheme = {
+    #  name = "Papirus-Dark";
+    #  package = pkgs.papirus-icon-theme;
+    #};
+    #theme = {
+    #  name = "adwaita";
+    #  package = pkgs.gnome-themes-extra;
+    #};
+    #};
+
+    #qt = {
+    #  enable = true;
+    #  platformTheme.name = "adwaita";
+    #  style.name = "adwaita";
+    #};
+
     home = {
       packages = with pkgs; [
         grim
-        pulseaudio # for pactl
         slurp
         wl-clipboard
       ];

@@ -38,84 +59,110 @@ in
       feh.enable = true;
     };
 
-    wayland.windowManager.sway = {
-      enable = true;
-      extraConfig = ''
-        exec element-desktop
-      '';
-      extraOptions = [ "--unsupported-gpu" ];
-      config = {
-        assigns = {
-          "${ws_2}" = [ { "app_id" = "code"; } ];
-          "${ws_3}" = [ { "app_id" = "librewolf"; } ];
-          "${ws_4}" = [ { "app_id" = "Element"; } ];
-        };
-        bars = [
-          {
-            command = "waybar";
-            mode = "hide";
-          }
-        ];
-        gaps = {
-          inner = 8;
-          outer = 3;
-        };
-        input."*" = {
-          xkb_layout = "de";
-        };
-        keybindings = mkOptionDefault {
-          "${modifier}+2" = "workspace ${ws_2}";
-          "${modifier}+3" = "workspace ${ws_3}";
-          "${modifier}+4" = "workspace ${ws_4}";
+    wayland = {
+      systemd.target = "sway-session.target";
+      windowManager.sway = {
+        enable = true;
+        extraConfig = ''
+          exec element-desktop
+        '';
+        #extraOptions = [ "--unsupported-gpu" ];
+        config = {
+          assigns = {
+            "${ws_2}" = [ { "app_id" = "code"; } ];
+            "${ws_3}" = [ { "app_id" = "librewolf"; } ];
+            "${ws_4}" = [ { "app_id" = "Element"; } ];
+          };
+          bars = [
+            {
+              command = "waybar";
+              mode = "hide";
+            }
+          ];
+          #colors = {
+          #  focused = {
+          #    background = "#B2A4D4";
+          #    border = "#B2A4D4";
+          #    indicator = "#ffffff";
+          #    childBorder = "#B2A4D4";
+          #    text = "#000000";
+          #  };
+          #};
+          gaps = {
+            inner = 2;
+            #outer = 2;
+          };
+          input = {
+            "12951:6505:ZSA_Technology_Labs_Moonlander_Mark_I".xkb_variant = "''";
+            "type:keyboard" = {
+              xkb_layout = "gb";
+              xkb_variant = "colemak_dh";
+            };
+            "type:touchpad" = {
+              tap = "enabled";
+              natural_scroll = "enabled";
+            };
+          };
+          keybindings = mkOptionDefault {
+            "${modifier}+2" = "workspace ${ws_2}";
+            "${modifier}+3" = "workspace ${ws_3}";
+            "${modifier}+4" = "workspace ${ws_4}";
 
-          "${modifier}+Shift+2" = "move container to workspace ${ws_2}";
-          "${modifier}+Shift+3" = "move container to workspace ${ws_3}";
-          "${modifier}+Shift+4" = "move container to workspace ${ws_4}";
+            "${modifier}+Shift+2" = "move container to workspace ${ws_2}";
+            "${modifier}+Shift+3" = "move container to workspace ${ws_3}";
+            "${modifier}+Shift+4" = "move container to workspace ${ws_4}";
 
-          "${modifier}+Shift+Delete" = "exec 'swaymsg exit'";
-          "${modifier}+L" = "exec 'swaylock -f --grace 0'";
-          "XF86MonBrightnessDown" = "exec brightnessctl 10%-";
-          "XF86MonBrightnessUp" = "exec brightnessctl +10%";
-          "XF86AudioRaiseVolume" = "exec 'pactl set-sink-volume @DEFAULT_SINK@ +1%'";
-          "XF86AudioLowerVolume" = "exec 'pactl set-sink-volume @DEFAULT_SINK@ -1%'";
-          "XF86AudioMute" = "exec 'pactl set-sink-mute @DEFAULT_SINK@ toggle'";
-        };
-        modifier = "Mod4";
-        output."*" = {
-          bg = "${inputs.self.resources.void.background} fill";
-        };
-        terminal = "kitty";
-        window.titlebar = false;
-        workspaceOutputAssign = (
-          (map
-            (n: {
-              output = DOCK_L;
-              workspace = n;
-            })
-            [
-              "6"
-              "7"
-              "8"
-              "9"
-              "10"
-            ]
-          )
-          ++
-            map
+            "${modifier}+Shift+Delete" = "exec 'swaymsg exit'";
+            "${modifier}+Delete" = "exec 'swaylock -f --grace 0'";
+            "--locked XF86MonBrightnessDown" =
+              "exec '${pkgs.brightnessctl}/bin/brightnessctl set --min-value=19200 10%-'";
+            "--locked XF86MonBrightnessUp" = "exec '${pkgs.brightnessctl}/bin/brightnessctl set 10%+'";
+            "--locked XF86AudioRaiseVolume" =
+              "exec '${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 5%+'";
+            "--locked XF86AudioLowerVolume" =
+              "exec '${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 5%-'";
+            "--locked XF86AudioMute" = "exec '${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_SINK@ toggle'";
+            "Print" = "exec '${pkgs.slurp}/bin/slurp | ${pkgs.grim}/bin/grim'";
+            "${modifier}+Tab" = "exec ${pkgs.swayr}/bin/swayr switch-window";
+          };
+          menu = "${pkgs.fuzzel}/bin/fuzzel";
+          modifier = "Mod4";
+          output."*" = {
+            bg = "${inputs.self.resources.void.background} fill";
+          };
+          terminal = "kitty";
+          window.titlebar = false;
+          workspaceOutputAssign =
+            (map
               (n: {
-                output = DOCK_R;
+                output = DOCK_L;
                 workspace = n;
               })
               [
-                "1"
-                ws_2
-                ws_3
-                ws_4
-                "5"
+                "6"
+                "7"
+                "8"
+                "9"
+                "10"
               ]
-        );
+            )
+            ++
+              map
+                (n: {
+                  output = DOCK_R;
+                  workspace = n;
+                })
+                [
+                  "1"
+                  ws_2
+                  ws_3
+                  ws_4
+                  "5"
+                ];
+        };
+        wrapperFeatures.gtk = true;
+        #xwayland = false;
       };
-      wrapperFeatures.gtk = true;
     };
   };
 
diff --git a/config/home/void/programs/swaylock.nix b/config/home/void/programs/swaylock.nix
@@ -1,8 +1,8 @@
 {
-  inputs,
   pkgs,
   ...
 }:
+
 {
 
   config = {

@@ -13,10 +13,10 @@
         clock = true;
         fade-in = 5;
         grace = 5;
-        image = inputs.self.resources.void.background;
+        #image = inputs.self.resources.void.background;
         indicator = true;
         indicator-radius = 100;
-        ring-color = "00497A";
+        #ring-color = "00497A";
         show-failed-attempts = true;
       };
     };
diff --git a/config/home/void/programs/swayr.nix b/config/home/void/programs/swayr.nix
@@ -0,0 +1,30 @@
+{
+  config,
+  ...
+}:
+
+{
+
+  config = {
+
+    programs.swayr = {
+      enable = true;
+      extraConfig = ''
+        [format]
+        window_format = "{app_name} - {title} - Workspace: {workspace_name}\u0000icon\u001f{app_icon}"
+      ''; # We do this here because `settings` does weird string escapism shenanigans that break backslashes; '\\' -> '\\\\'
+      settings = {
+        menu = {
+          executable = "${config.programs.fuzzel.package}/bin/fuzzel";
+          args = [
+            "--dmenu"
+            "--lines=30"
+            "--prompt=Select Window: "
+            "--width=150"
+          ];
+        };
+      };
+      systemd.enable = true;
+    };
+  };
+}
diff --git a/config/home/void/programs/waybar.nix b/config/home/void/programs/waybar.nix
@@ -3,6 +3,7 @@
   pkgs,
   ...
 }:
+
 {
 
   config = {

@@ -38,13 +39,14 @@
             "clock"
           ];
           modules-right = [
-            "pulseaudio"
+            "wireplumber"
             "cpu"
             "memory"
             "temperature"
             "backlight"
             "battery"
             "tray"
+            "power-profiles-daemon"
             "custom/power"
           ];
           "sway/workspaces" = {

@@ -53,24 +55,30 @@
           idle_inhibitor = {
             format = "{icon}";
             format-icons = {
-              activated = "";
-              deactivated = "";
+              activated = "󰛐";
+              deactivated = "󰈉";
             };
           };
           keyboard-state = {
             capslock = true;
             format = "{name} {icon} ";
             format-icons = {
-              locked = " ";
-              unlocked = "";
+              locked = "󰍁";
+              unlocked = "󰌿";
             };
           };
           network = {
             interval = 5;
-            format-wifi = " {essid} ({signalStrength}%)";
-            format-ethernet = " {ifname}";
-            format-disconnected = "No connection";
-            format-alt = " {ipaddr}/{cidr}";
+            format-wifi = "{icon} {essid} ({signalStrength}%)";
+            format-ethernet = "󰈀 {ifname}";
+            format-disconnected = "󰌙 No connection";
+            format-alt = "󰩟 {ipaddr}/{cidr}";
+            format-icons = [
+              "󰤟"
+              "󰤢"
+              "󰤥"
+              "󰤨"
+            ];
             tooltip = false;
           };
           "sway/mode" = {

@@ -80,39 +88,39 @@
             tooltip-format = "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
             format = "{:%a, %d %b, %H:%M}";
           };
-          pulseaudio = {
+          wireplumber = {
             reverse-scrolling = 1;
             format = "{volume}% {icon} {format_source}";
             format-bluetooth = "{volume}% {icon}  {format_source}";
-            format-bluetooth-muted = " {icon}  {format_source}";
-            format-muted = "婢 {format_source}";
+            format-bluetooth-muted = "󰝟 {icon}  {format_source}";
+            format-muted = "󰝟 {format_source}";
             format-source = "{volume}% ";
             format-source-muted = "";
             format-icons = {
-              headphone = "";
-              hands-free = "";
-              headset = "";
-              phone = "";
-              portable = "";
-              car = "";
+              headphone = "󰋋";
+              hands-free = ""; # FIXME: Find proper Icon for this
+              headset = "󰋎";
+              phone = "󰏲";
+              portable = "󰏲";
+              car = "󰄋";
               default = [
-                "奄"
-                "奔"
-                "墳"
+                "󰕿"
+                "󰖀"
+                "󰕾"
               ];
             };
-            on-click = "${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle";
-            on-click-right = "${pkgs.pavucontrol}/bin/pavucontrol";
+            on-click = "${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_SINK@ toggle";
+            on-click-right = "${pkgs.pwvucontrol}/bin/pwvucontrol";
             min-length = 13;
           };
           "cpu" = {
-            format = "{usage}% ";
-            format-alt = "{load} ";
+            format = "{usage}% 󰘚";
+            format-alt = "{load} 󰘚";
             interval = 3;
             tooltip = false;
           };
           "memory" = {
-            format = "{}% ";
+            format = "{}% 󰍛";
             interval = 3;
             tooltip = false;
           };

@@ -133,66 +141,54 @@
             device = "intel_backlight";
             format = "{percent}% {icon}";
             format-icons = [
-              ""
-              ""
-              ""
-              ""
-              ""
-              ""
-              ""
+              "󰃚"
+              "󰃛"
+              "󰃜"
+              "󰃝"
+              "󰃞"
+              "󰃟"
+              "󰃠"
             ];
             min-length = 7;
           };
           battery = {
             states = {
               warning = 30;
-              critical = 15;
+              critical = 20;
             };
             format = "{capacity}% {icon}";
-            format-charging = "{capacity}% ";
+            format-charging = "{capacity}% 󰂄";
             format-plugged = "{capacity}% ";
             format-alt = "{time} {icon}";
             format-icons = [
-              ""
-              ""
-              ""
-              ""
-              ""
-              ""
-              ""
-              ""
-              ""
-              ""
+              "󰂃"
+              "󰁻"
+              "󰁼"
+              "󰁽"
+              "󰁾"
+              "󰁿"
+              "󰂀"
+              "󰂁"
+              "󰂂"
+              "󰁹"
             ];
-            on-update = pkgs.writeShellScript "check-battery" ''
-              #!/usr/bin/env sh
-
-              PATH=$PATH:${pkgs.coreutils-full}/bin:${pkgs.libnotify}/bin
-
-              bat=/sys/class/power_supply/BAT0
-              CRIT=''${1:-15}
-
-              FILE=~/.config/waybar/scripts/notified
-
-              stat=$(cat $bat/status)
-              perc=$(cat $bat/capacity)
-
-              if [[ $perc -le $CRIT ]] && [[ $stat == "Discharging" ]]; then
-                if [[ ! -f "$FILE" ]]; then
-                  notify-send --urgency=critical --icon=dialog-warning "Battery Low" "Current charge: $perc%"
-                  touch $FILE
-                fi
-              elif [[ -f "$FILE" ]]; then
-                rm $FILE
-              fi
-            '';
+            full-at = 80;
           };
           tray = {
             icon-size = 16;
             spacing = 0;
           };
+          power-profiles-daemon = {
+            format = "{icon}";
+            format-icons = {
+              default = "D";
+              performance = "󱐋";
+              balanced = "󰗑";
+              power-saver = "󱈏";
+            };
+          };
           "custom/power" = {
-            format = "⏻";
+            format = "󱅀";
             tooltip = false;
             menu = "on-click";
             menu-file = "$HOME/.config/waybar/power_menu.xml";

@@ -205,229 +201,7 @@
           };
         }
       ];
-      style = ''
-        * {
-            border: none;
-            border-radius: 0;
-            font-family: MesloLGS NF;
-            min-height: 20px;
-            padding: 5px;
-        }
-
-        window#waybar {
-            background: transparent;
-        }
-
-        window#waybar.hidden {
-            opacity: 0.2;
-        }
-
-        #workspaces {
-            margin-right: 8px;
-            border-radius: 10px;
-            transition: none;
-            background: #383c4a;
-        }
-
-        #workspaces button {
-            transition: none;
-            color: #7c818c;
-            background: transparent;
-            padding: 0px;
-            font-size: 18px;
-        }
-
-        #workspaces button.persistent {
-            color: #7c818c;
-            font-size: 12px;
-        }
-
-        /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
-        #workspaces button:hover {
-            transition: none;
-            box-shadow: inherit;
-            text-shadow: inherit;
-            border-radius: inherit;
-            color: #383c4a;
-            background: #7c818c;
-        }
-
-        #workspaces button.focused {
-            color: white;
-        }
-
-        #idle_inhibitor {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #idle_inhibitor.activated {
-            color: #383c4a;
-            background: #ffffff;
-        }
-
-        #keyboard-state {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 8px;
-            border-radius: 10px 10px 10px 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #mode {
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #network {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #clock {
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px 10px 10px 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #pulseaudio {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #pulseaudio.muted {
-            background-color: #90b1b1;
-            color: #2a5c45;
-        }
-
-        #cpu {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #memory {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #temperature {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #temperature.critical {
-            background-color: #eb4d4b;
-        }
-
-        #backlight {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #battery {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #battery.charging {
-            color: #ffffff;
-            background-color: #26A65B;
-        }
-
-        #battery.warning:not(.charging) {
-            background-color: #ffbe61;
-            color: black;
-        }
-
-        #battery.critical:not(.charging) {
-            background-color: #f53c3c;
-            color: #ffffff;
-            animation-name: blink;
-            animation-duration: 0.5s;
-            animation-timing-function: linear;
-            animation-iteration-count: infinite;
-            animation-direction: alternate;
-        }
-
-        #tray {
-            margin-right: 8px;
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        #custom-power {
-            padding-left: 16px;
-            padding-right: 16px;
-            border-radius: 10px;
-            transition: none;
-            color: #ffffff;
-            background: #383c4a;
-        }
-
-        @keyframes blink {
-            to {
-                background-color: #ffffff;
-                color: #000000;
-            }
-        }
-      '';
-      systemd = {
-        enable = true;
-        target = "sway-session.target";
-      };
+      style = builtins.readFile inputs.self.resources.void.programs.waybar.style;
     };
   };
 
diff --git a/config/home/void/services/gpg-agent.nix b/config/home/void/services/gpg-agent.nix
@@ -1,4 +1,9 @@
 {
+  pkgs,
+  ...
+}:
+
+{
 
   config = {
     services.gpg-agent = {

@@ -8,6 +13,10 @@
         "333BB4DAF37CAE63207F463D32EBD69BE5C74E75"
         "E6EE9F928448B4CBFE3BC4D7ED86FD11FD70C867"
       ];
+      pinentry = {
+        package = pkgs.pinentry-all;
+        program = "pinentry-gnome3";
+      };
     };
   };
 
diff --git a/config/home/void/services/kanshi.nix b/config/home/void/services/kanshi.nix
@@ -1,3 +1,5 @@
+_:
+
 {
 
   config = {
diff --git a/config/home/void/services/swayidle.nix b/config/home/void/services/swayidle.nix
@@ -1,29 +1,48 @@
 {
   config,
+  lib,
+  pkgs,
   ...
 }:
+
+let
+  inherit (lib) getExe getExe';
+in
+
 {
 
   config = {
     services.swayidle = {
       enable = true;
-      systemdTarget = "sway-session.target";
       timeouts = [
         {
+          timeout = 30;
+          command = "${getExe pkgs.brightnessctl} set -s $[ $(${getExe pkgs.brightnessctl} get) / 10 ]";
+          resumeCommand = "${getExe pkgs.brightnessctl} -r";
+        }
+        {
           timeout = 90;
-          command = "${config.programs.swaylock.package}/bin/swaylock -f";
+          command = "${getExe' config.wayland.windowManager.sway.package "swaymsg"} 'output * power off'";
+          resumeCommand = "${getExe' config.wayland.windowManager.sway.package "swaymsg"} 'output * power on'";
         }
         {
-          timeout = 95;
-          command = "${config.wayland.windowManager.sway.package}/bin/swaymsg 'output * power off'";
-          resumeCommand = "${config.wayland.windowManager.sway.package}/bin/swaymsg 'output * power on'";
+          timeout = 120;
+          command = "${getExe' pkgs.systemd "loginctl"} lock-session";
         }
       ];
       events = [
         {
           event = "before-sleep";
-          # Invoke swaylock instantaneously and without animations that inhibit sleep.
-          command = "${config.programs.swaylock.package}/bin/swaylock -f --grace 0 --fade-in 0";
+          # Invoke swaylock instantaneously and without animations that delay sleep.
+          command = "${getExe config.programs.swaylock.package} -f --grace 0 --fade-in 0";
+        }
+        {
+          event = "lock";
+          command = "${getExe config.programs.swaylock.package} -f --grace 0";
+        }
+        {
+          event = "unlock";
+          command = "${getExe' pkgs.procps "pkill"} -10 swaylock";
         }
       ];
     };
diff --git a/config/home/void/services/syncthing.nix b/config/home/void/services/syncthing.nix
@@ -0,0 +1,12 @@
+_:
+
+{
+
+  services.syncthing = {
+    enable = true;
+    overrideDevices = false;
+    overrideFolders = false;
+    tray.enable = true;
+  };
+
+}
diff --git a/config/home/zaphyra/configure/fonts.nix b/config/home/zaphyra/configure/fonts.nix
@@ -0,0 +1,94 @@
+{
+  lib,
+  pkgs,
+  ...
+}:
+
+let
+  adwaita-fonts-nerd = pkgs.stdenvNoCC.mkDerivation {
+    pname = "adwaita-fonts-nerd";
+    version = "1.8.0-${pkgs.nerd-font-patcher.version}";
+
+    src = pkgs.adwaita-fonts;
+
+    nativeBuildInputs = [
+      pkgs.nerd-font-patcher
+    ]
+    ++ (with pkgs.python3Packages; [
+      python
+      fontforge
+    ]);
+
+    buildPhase = ''
+      runHook preBuild
+
+      mkdir -p build/
+
+      for f in share/fonts/Adwaita/*; do
+        nerd-font-patcher $f --complete --no-progressbars --outputdir build
+        # note: this will *not* return an error exit code on failure, but instead
+        # write out a corrupt file, so an additional check phase is required
+      done
+
+      runHook postBuild
+    '';
+
+    doCheck = true;
+    checkPhase = ''
+      runHook preCheck
+
+      # Try to open each font. If a corrupt font was written out, this should fail
+      for f in build/*; do
+          fontforge - <<EOF
+      try:
+        fontforge.open(''\'''${f}')
+      except:
+        exit(1)
+      EOF
+      done
+
+      runHook postCheck
+    '';
+
+    installPhase = ''
+      runHook preInstall
+
+      mkdir -p $out/share/fonts/opentype/
+      install -Dm 444 build/* $out/share/fonts/opentype/
+
+      runHook postInstall
+    '';
+
+    meta = with lib; {
+      homepage = "https://github.com/ryanoasis/nerd-fonts";
+      description = "Adwaita Fonts patched with Nerd Fonts icons";
+      license = licenses.ofl;
+      platforms = platforms.all;
+    };
+  };
+
+in
+{
+
+  fonts.fontconfig = {
+    enable = true;
+    defaultFonts = {
+      serif = [ "Adwaita Sans" ];
+      sansSerif = [ "Adwaita Sans" ];
+      monospace = [ "Adwaita Mono" ];
+      emoji = [ "Noto Color Emoji" ];
+    };
+  };
+
+  home.packages = with pkgs; [
+    adwaita-fonts-nerd
+    liberation_ttf
+    ttf_bitstream_vera
+    noto-fonts
+    noto-fonts-emoji
+    nerd-fonts.symbols-only
+    fira-code
+    fira-mono
+  ];
+
+}
diff --git a/config/home/zaphyra/configure/gnome.nix b/config/home/zaphyra/configure/gnome.nix
@@ -1,4 +1,6 @@
 {
+  homeManagerModules,
+  config,
   inputs,
   lib,
   pkgs,

@@ -13,46 +15,52 @@ in
 
   manual.html.enable = true;
 
-  home.sessionVariables = {
-    QT_QPA_PLATFORMTHEME = "gnome";
-  };
+  imports = with homeManagerModules.zaphyra; [
+    configure.fonts
 
-  home.persistence."/nix/persist/home/zaphyra".directories = [
-    "dconf/.config/dconf"
-    "keyring/.local/share/keyrings"
-    "evolution-data-server/.local/share/evolution"
-    "gnome-online-accounts/.config/goa-1.0"
-    "gnome/.local/share/gnome-shell"
+    services.gnome-keyring
   ];
 
-  home.packages =
-    with pkgs;
-    [
-      gnome-calendar
-      gnome-text-editor
-      gnome-podcasts
-      gnome-obfuscate
-      gnome-power-manager
-      loupe
-      cozy
-
-      refine
-      xdg-utils
-      qgnomeplatform
-      wl-clipboard-x11
-      # look and feel from libadwaita ported to GTK-3
-      adw-gtk3
-    ]
-    ++ (with pkgs.gnomeExtensions; [
-      battery-time-percentage-compact
-      caffeine
-    ]);
+  home = {
+    persistence."/nix/persist/home/${config.home.username}".directories = [
+      "dconf/.config/dconf"
+      "gnome/.local/share/gnome-shell"
+    ];
+
+    sessionVariables = {
+      QT_QPA_PLATFORMTHEME = "gnome";
+    };
+
+    packages =
+      with pkgs;
+      [
+        gnome-power-manager
+        refine
+
+        xdg-utils
+        qgnomeplatform
+        wl-clipboard-x11
+        # look and feel from libadwaita ported to GTK-3
+        adw-gtk3
+      ]
+      ++ (with pkgs.gnomeExtensions; [
+        battery-time-percentage-compact
+        caffeine
+      ]);
+  };
 
   gtk = {
     enable = true;
 
-    iconTheme.package = pkgs.adwaita-colors-icon-theme;
-    iconTheme.name = "Adwaita-green";
+    iconTheme = {
+      name = "Adwaita-green";
+      package = pkgs.tgc.adwaita-colors-icon-theme;
+    };
+
+    cursorTheme = {
+      name = "Adwaita";
+      package = pkgs.adwaita-icon-theme;
+    };
 
     gtk3.extraConfig = {
       gtk-application-prefer-dark-theme = 1;

@@ -65,13 +73,12 @@ in
     with inputs.homeManager.lib.hm.gvariant;
     let
       numWorkspaces = 7;
-      workspaces = (
-        numWorkspaces
-        |> nixStd.list.unfold (
+      workspaces = lib.pipe numWorkspaces [
+        (nixStd.list.unfold (
           n: if n == 0 then nixStd.optional.nothing else nixStd.optional.just (nixStd.tuple.tuple2 n (n - 1))
-        )
-        |> lib.lists.reverseList
-      );
+        ))
+        lib.lists.reverseList
+      ];
     in
     {
       "org/gnome/mutter" = {

@@ -152,7 +159,7 @@ in
         command = "${pkgs.writeShellScript "cccda-buzzer" ''
           export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
 
-          ${pkgs.libnotify}/bin/notify-send -e "CCCDA-Door" "$(${pkgs.chaosctl}/bin/chaosctl door buzzer)"
+          ${lib.getExe' pkgs.libnotify "notify-send"} -e "CCCDA-Door" "$(${lib.getExe pkgs.tgc.chaosctl} door buzzer)"
         ''}";
         binding = "<Super><Shift>d";
       };
diff --git a/config/home/zaphyra/configure/niri.nix b/config/home/zaphyra/configure/niri.nix
@@ -0,0 +1,109 @@
+{
+  systemConfig,
+  config,
+  lib,
+  pkgs,
+  homeManagerModules,
+  ...
+}:
+
+{
+
+  imports =
+    with homeManagerModules.zaphyra;
+    [
+      configure.fonts
+
+      services.dssd
+      services.batsignal
+      services.wpaperd
+      services.shaderbg
+      services.waybar
+      services.wob
+      services.swaync
+      services.swayidle
+      services.wlsunset
+      services.playerctl
+      services.gomuks-web
+
+      programs.niri
+      programs.swaylock
+      programs.ghostty
+      programs.app2unit
+      programs.sherlock-launcher
+      programs.fuzzel
+    ]
+    ++ (lib.optionals systemConfig.modules.hardware.bluetooth.enable [
+      programs.overskride
+      programs.airpodsctl
+    ]);
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "dconf/.config/dconf"
+  ];
+
+  tgc.programs.nirius.enable = true;
+
+  xdg.portal = {
+    config.common.default = [
+      "gtk"
+      "gnome"
+    ];
+    extraPortals = with pkgs; [
+      xdg-desktop-portal-gtk
+      xdg-desktop-portal-gnome
+    ];
+  };
+
+  gtk = {
+    enable = true;
+
+    gtk3.extraConfig = {
+      gtk-theme = "adw-gtk3-dark";
+      gtk-application-prefer-dark-theme = 1;
+    };
+
+    font = {
+      name = "Adwaita Sans";
+      size = 11;
+      package = pkgs.adwaita-fonts;
+    };
+
+    iconTheme = {
+      name = "Adwaita-green";
+      package = pkgs.tgc.adwaita-colors-icon-theme;
+    };
+
+    cursorTheme = {
+      name = "Adwaita";
+      package = pkgs.adwaita-icon-theme;
+    };
+  };
+
+  qt = {
+    enable = true;
+    platformTheme.name = "Adwaita-dark";
+    style = {
+      name = "Adwaita-dark";
+      package = pkgs.adwaita-qt6;
+    };
+  };
+
+  home.packages = with pkgs; [
+    xdg-utils
+    wl-clipboard-rs
+    adw-gtk3
+  ];
+
+  # Use `dconf watch /` to track stateful changes you are doing and store them here.
+  dconf.settings = {
+    "org/gnome/desktop/interface" = {
+      color-scheme = "prefer-dark";
+      accent-color = "green";
+    };
+    "org/gnome/desktop/wm/preferences" = {
+      button-layout = "";
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/configure/xdg.nix b/config/home/zaphyra/configure/xdg.nix
@@ -1,22 +1,41 @@
-{ ... }:
+{
+  config,
+  ...
+}:
 
 {
 
+  home.preferXdgDirectories = true;
+
+  gtk.gtk2.configLocation = "${config.xdg.configHome}/gtk-2.0/gtkrc";
+
   xdg = {
     enable = true;
     mime.enable = true;
 
     userDirs = {
       enable = true;
-      desktop = "\$HOME/Desktop";
-      documents = "\$HOME/Documents";
-      download = "\$HOME/Downloads";
-      videos = "\$HOME/Videos";
-      music = "\$HOME/Music";
-      pictures = "\$HOME/Pictures";
-      publicShare = "\$HOME/Public";
-      templates = "\$HOME/Templates";
+
+      desktop = config.home.homeDirectory;
+      publicShare = config.home.homeDirectory;
+      templates = config.home.homeDirectory;
+
+      documents = "${config.home.homeDirectory}/Documents";
+      download = "${config.home.homeDirectory}/Downloads";
+      videos = "${config.home.homeDirectory}/Videos";
+      music = "${config.home.homeDirectory}/Music";
+      pictures = "${config.home.homeDirectory}/Pictures";
     };
   };
 
+  xdg.configFile."gtk-3.0/bookmarks".force = true;
+  gtk.gtk3.bookmarks = [
+    "file://${config.home.homeDirectory}/Downloads"
+    "file://${config.home.homeDirectory}/Documents"
+    "file://${config.home.homeDirectory}/proj Projects"
+    "file://${config.home.homeDirectory}/Audiobooks"
+    "file://${config.home.homeDirectory}/Music"
+    "file://${config.home.homeDirectory}/Pictures"
+  ];
+
 }
diff --git a/config/home/zaphyra/gnomeExtensions/bluetoothBatteryMeter.nix b/config/home/zaphyra/gnomeExtensions/bluetoothBatteryMeter.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/gnomeExtensions/dash-to-dock.nix b/config/home/zaphyra/gnomeExtensions/dash-to-dock.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/gnomeExtensions/emoji-copy.nix b/config/home/zaphyra/gnomeExtensions/emoji-copy.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/gnomeExtensions/just-perfection.nix b/config/home/zaphyra/gnomeExtensions/just-perfection.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/gnomeExtensions/pip-on-top.nix b/config/home/zaphyra/gnomeExtensions/pip-on-top.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/gnomeExtensions/search-light.nix b/config/home/zaphyra/gnomeExtensions/search-light.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/gnomeExtensions/space-bar.nix b/config/home/zaphyra/gnomeExtensions/space-bar.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/home.nix b/config/home/zaphyra/home.nix
@@ -1,18 +1,45 @@
 {
   homeManagerModules,
+  pkgs,
   ...
 }:
 
 {
 
+  i18n.glibcLocales = pkgs.glibcLocales.override {
+    allLocales = false;
+    locales = [
+      "en_GB.UTF-8/UTF-8"
+      "de_DE.UTF-8/UTF-8"
+    ];
+  };
+
+  home.language = {
+    base = "en_GB.UTF-8";
+    messages = "en_GB.UTF-8";
+    ctype = "en_GB.UTF-8";
+    address = "de_DE.UTF-8";
+    collate = "de_DE.UTF-8";
+    measurement = "de_DE.UTF-8";
+    monetary = "de_DE.UTF-8";
+    name = "de_DE.UTF-8";
+    numeric = "en_GB.UTF-8";
+    paper = "de_DE.UTF-8";
+    telephone = "de_DE.UTF-8";
+    time = "en_GB.UTF-8";
+  };
+
   imports = with homeManagerModules.zaphyra; [
     homeManagerModules.common.programs.starship
+    homeManagerModules.common.programs.app2unit
     programs.fish
     programs.mcfly
     programs.zoxide
     programs.eza
     programs.bat
 
+    programs.chawan
+    programs.yazi
     programs.micro
     programs.helix
     programs.tmux

@@ -20,8 +47,6 @@
 
     programs.deploymentUtilities
     programs.shellUtilities
-
-    programs.nix-cleanup
   ];
 
 }
diff --git a/config/home/zaphyra/impermanence.nix b/config/home/zaphyra/impermanence.nix
@@ -1,4 +1,4 @@
-{ ... }:
+_:
 
 {
 
diff --git a/config/home/zaphyra/programs/airpodsctl.nix b/config/home/zaphyra/programs/airpodsctl.nix
@@ -0,0 +1,18 @@
+{
+  config,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "kairpodsd/.config/kairpodsd/"
+    "kairpodsd/.local/share/kairpodsd/"
+  ];
+
+  services.kairpodsd.enable = true;
+
+  home.packages = [ pkgs.airpodsctl ];
+
+}
diff --git a/config/home/zaphyra/programs/alacritty.nix b/config/home/zaphyra/programs/alacritty.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 

@@ -49,11 +52,6 @@
     };
   };
 
-  wayland.windowManager.sway = {
-    config.terminal = "${pkgs.alacritty}/bin/alacritty";
-    extraConfig = ''
-      exec swaymsg 'workspace 3: Term; exec ${pkgs.alacritty}/bin/alacritty; exec ${pkgs.alacritty}/bin/alacritty; workspace 1: Web;'
-    '';
-  };
+  wayland.windowManager.sway.config.terminal = "${pkgs.alacritty}/bin/alacritty";
 
 }
diff --git a/config/home/zaphyra/programs/ansible.nix b/config/home/zaphyra/programs/ansible.nix
@@ -1,20 +0,0 @@
-{ pkgs, ... }:
-
-let
-  ansible = pkgs.python3Packages.toPythonApplication (
-    pkgs.python3Packages.ansible-core.overridePythonAttrs (old: rec {
-      propagatedBuildInputs = old.propagatedBuildInputs ++ [
-        pkgs.python3Packages.jmespath
-      ];
-    })
-  );
-
-in
-{
-
-  home.packages = [
-    ansible
-    pkgs.ansible-lint
-  ];
-
-}
diff --git a/config/home/zaphyra/programs/apostrophe.nix b/config/home/zaphyra/programs/apostrophe.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/programs/bat.nix b/config/home/zaphyra/programs/bat.nix
@@ -1,4 +1,4 @@
-{ ... }:
+_:
 
 {
 
diff --git a/config/home/zaphyra/programs/bitwarden-cli.nix b/config/home/zaphyra/programs/bitwarden-cli.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/programs/celluloid.nix b/config/home/zaphyra/programs/celluloid.nix
@@ -1,7 +1,18 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
   home.packages = [ pkgs.celluloid ];
 
+  dconf.settings = {
+    "io/github/celluloid-player/celluloid" = {
+      always-append-to-playlist = true;
+      draggable-video-area-enable = true;
+      always-autohide-cursor = true;
+    };
+  };
+
 }
diff --git a/config/home/zaphyra/programs/chaosctl.nix b/config/home/zaphyra/programs/chaosctl.nix
@@ -0,0 +1,20 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.tgc.chaosctl ];
+
+  programs.niri.settings.binds = with config.lib.niri.actions; {
+    "Mod+Shift+D".action = spawn "${pkgs.writeShellScript "cccda-buzzer" ''
+      export GNUPGHOME=${config.programs.gpg.homedir}
+      export SSH_AUTH_SOCK=$(${lib.getExe' pkgs.gnupg "gpgconf"} --list-dirs agent-ssh-socket)
+      ${lib.getExe' pkgs.libnotify "notify-send"} -e "CCCDA-Door" "$(${lib.getExe pkgs.tgc.chaosctl} door buzzer)"
+    ''}";
+  };
+
+}
diff --git a/config/home/zaphyra/programs/chawan.nix b/config/home/zaphyra/programs/chawan.nix
@@ -0,0 +1,17 @@
+_:
+
+{
+
+  programs.chawan = {
+    enable = true;
+    settings = {
+      buffer = {
+        images = true;
+        scripting = "app";
+        autofocus = true;
+        cookie = "save";
+      };
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/programs/cozy.nix b/config/home/zaphyra/programs/cozy.nix
@@ -0,0 +1,10 @@
+{
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.cozy ];
+
+}
diff --git a/config/home/zaphyra/programs/deploymentUtilities.nix b/config/home/zaphyra/programs/deploymentUtilities.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/programs/dino.nix b/config/home/zaphyra/programs/dino.nix
@@ -0,0 +1,15 @@
+{
+  config,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "dino/.local/share/dino"
+  ];
+
+  home.packages = [ pkgs.dino ];
+
+}
diff --git a/config/home/zaphyra/programs/errands.nix b/config/home/zaphyra/programs/errands.nix
@@ -1,11 +1,15 @@
-{ lib, pkgs, ... }:
-
 {
+  config,
+  pkgs,
+  ...
+}:
 
-  home.packages = [ pkgs.errands ];
+{
 
-  home.persistence."/nix/persist/home/zaphyra".directories = [
-    "tuba/.local/share/errands"
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "errands/.local/share/errands"
   ];
 
+  home.packages = [ pkgs.errands ];
+
 }
diff --git a/config/home/zaphyra/programs/eza.nix b/config/home/zaphyra/programs/eza.nix
@@ -1,9 +1,4 @@
-{
-  config,
-  pkgs,
-  lib,
-  ...
-}:
+_:
 
 {
 
diff --git a/config/home/zaphyra/programs/firefox.nix b/config/home/zaphyra/programs/firefox.nix
@@ -1,5 +1,6 @@
 {
   inputs,
+  config,
   pkgs,
   lib,
   ...

@@ -7,26 +8,28 @@
 
 {
 
-  home.sessionVariables = {
-    BROWSER = "firefox";
-  };
+  home = {
+    persistence."/nix/persist/home/${config.home.username}".directories = [
+      "firefox/.mozilla/firefox/"
+      "firefox/.cache/mozilla/firefox"
+    ];
 
-  home.file."firefox-gnome-theme" = {
-    source = inputs.firefoxGnomeTheme;
-    target = ".mozilla/firefox/zaphyra/chrome/firefox-gnome-theme";
-  };
+    sessionVariables = {
+      BROWSER = "firefox";
+    };
 
-  home.persistence."/nix/persist/home/zaphyra".directories = [
-    "firefox/.mozilla/firefox/"
-    "firefox/.cache/mozilla/firefox"
-  ];
+    file."firefox-gnome-theme" = {
+      source = inputs.firefoxGnomeTheme;
+      target = ".mozilla/firefox/${config.home.username}/chrome/firefox-gnome-theme";
+    };
+  };
 
   programs.firefox = {
     enable = true;
     package = pkgs.firefox;
     nativeMessagingHosts = [ pkgs.ff2mpv-rust ];
 
-    profiles.zaphyra = {
+    profiles."${config.home.username}" = {
       id = 0;
       isDefault = true;
 

@@ -98,18 +101,23 @@
       DNSOverHTTPS.Locked = true;
 
       # enable tracking protection
-      EnableTrackingProtection.Cryptomining = true;
-      EnableTrackingProtection.Fingerprinting = true;
-      EnableTrackingProtection.Value = true;
-      EnableTrackingProtection.Locked = true;
-
-      UserMessaging.ExtensionRecommendations = false;
-      UserMessaging.FeatureRecommendations = false;
-      UserMessaging.UrlbarInterventions = false;
-      UserMessaging.SkipOnboarding = true;
-      UserMessaging.MoreFromMozilla = false;
-      UserMessaging.FirefoxLabs = false;
-      UserMessaging.Locked = true;
+      EnableTrackingProtection = {
+
+        Cryptomining = true;
+        Fingerprinting = true;
+        Value = true;
+        Locked = true;
+      };
+
+      UserMessaging = {
+        ExtensionRecommendations = false;
+        FeatureRecommendations = false;
+        UrlbarInterventions = false;
+        SkipOnboarding = true;
+        MoreFromMozilla = false;
+        FirefoxLabs = false;
+        Locked = true;
+      };
 
       Handlers.schemes =
         let

@@ -141,157 +149,155 @@
           bahnbonus = handler;
         };
 
-      Preferences =
-        {
-          "browser.uiCustomization.state".Status = "default";
-          "browser.uiCustomization.state".Value = builtins.toJSON {
-            currentVersion = 21;
-            newElementCount = 7;
-            seen = [ ];
-            dirtyAreaCache = [ ];
-            placements = {
-              widget-overflow-fixed-list = [ ];
-              toolbar-menubar = [ "menubar-items" ];
-              vertical-tabs = [ ];
-              PersonalToolbar = [ ];
-              unified-extensions-area = [ ];
-              nav-bar = [
-                "back-button"
-                "forward-button"
-                "vertical-spacer"
-                "stop-reload-button"
-                "urlbar-container"
-                "downloads-button"
-                "_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action"
-                "ublock0_raymondhill_net-browser-action"
-                "unified-extensions-button"
-              ];
-              TabsToolbar = [
-                "tabbrowser-tabs"
-                "new-tab-button"
-              ];
-            };
+      Preferences = {
+        "browser.uiCustomization.state".Status = "default";
+        "browser.uiCustomization.state".Value = builtins.toJSON {
+          currentVersion = 21;
+          newElementCount = 7;
+          seen = [ ];
+          dirtyAreaCache = [ ];
+          placements = {
+            widget-overflow-fixed-list = [ ];
+            toolbar-menubar = [ "menubar-items" ];
+            vertical-tabs = [ ];
+            PersonalToolbar = [ ];
+            unified-extensions-area = [ ];
+            nav-bar = [
+              "back-button"
+              "forward-button"
+              "vertical-spacer"
+              "stop-reload-button"
+              "urlbar-container"
+              "downloads-button"
+              "_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action"
+              "ublock0_raymondhill_net-browser-action"
+              "unified-extensions-button"
+            ];
+            TabsToolbar = [
+              "tabbrowser-tabs"
+              "new-tab-button"
+            ];
           };
+        };
+      }
+      // (lib.mapAttrs
+        (_name: value: {
+          Status = "locked";
+          Value = value;
+        })
+        {
+          # disable some password-manager/autofill features
+          "signon.generation.enabled" = false;
+          "signon.autofillForms" = false;
+          "signon.firefoxRelay.feature" = "disabled";
+          "signon.management.page.breach-alerts.enabled" = false;
+
+          # ask websites to not share or sell data
+          "privacy.globalprivacycontrol.enabled" = true;
+
+          # disable warning on `abou:config`
+          "browser.aboutConfig.showWarning" = false;
+
+          # disable telemetry stuff
+          "browser.ping-centre.telemetry" = false;
+          "browser.topsites.contile.enabled" = false;
+          "browser.crashReports.unsubmittedCheck.autoSubmit2" = false;
+
+          # just open previous session
+          "browser.startup.page" = 3;
+
+          # disable trending search suggestions
+          "browser.urlbar.suggest.trending" = false;
+
+          # disable 'fancy' newtab page bullshit with tons of tracking and ads
+          "browser.startup.homepage" = "chrome://browser/content/blanktab.html";
+          "browser.newtabpage.enabled" = false;
+          "browser.newtabpage.activity-stream.telemetry" = false;
+          "browser.newtabpage.activity-stream.showSearch" = false;
+          "browser.newtabpage.activity-stream.showSponsored" = false;
+          "browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
+          "browser.newtabpage.activity-stream.feeds.telemetry" = false;
+          "browser.newtabpage.activity-stream.feeds.topsites" = false;
+          "browser.newtabpage.activity-stream.feeds.snippets" = false;
+          "browser.newtabpage.activity-stream.feeds.system.topsites" = false;
+          "browser.newtabpage.activity-stream.feeds.section.highlights" = false;
+          "browser.newtabpage.activity-stream.section.highlights.includePocket" = false;
+          "browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = false;
+          "browser.newtabpage.activity-stream.section.highlights.includeDownloads" = false;
+          "browser.newtabpage.activity-stream.section.highlights.includeVisited" = false;
         }
-        // (
-          {
-            # disable some password-manager/autofill features
-            "signon.generation.enabled" = false;
-            "signon.autofillForms" = false;
-            "signon.firefoxRelay.feature" = "disabled";
-            "signon.management.page.breach-alerts.enabled" = false;
-
-            # ask websites to not share or sell data
-            "privacy.globalprivacycontrol.enabled" = true;
-
-            # disable warning on `abou:config`
-            "browser.aboutConfig.showWarning" = false;
-
-            # disable telemetry stuff
-            "browser.ping-centre.telemetry" = false;
-            "browser.topsites.contile.enabled" = false;
-            "browser.crashReports.unsubmittedCheck.autoSubmit2" = false;
-
-            # disable trending search suggestions
-            "browser.urlbar.suggest.trending" = false;
-
-            # disable 'fancy' newtab page bullshit with tons of tracking and ads
-            "browser.startup.homepage" = "chrome://browser/content/blanktab.html";
-            "browser.newtabpage.enabled" = false;
-            "browser.newtabpage.activity-stream.telemetry" = false;
-            "browser.newtabpage.activity-stream.showSearch" = false;
-            "browser.newtabpage.activity-stream.showSponsored" = false;
-            "browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
-            "browser.newtabpage.activity-stream.feeds.telemetry" = false;
-            "browser.newtabpage.activity-stream.feeds.topsites" = false;
-            "browser.newtabpage.activity-stream.feeds.snippets" = false;
-            "browser.newtabpage.activity-stream.feeds.system.topsites" = false;
-            "browser.newtabpage.activity-stream.feeds.section.highlights" = false;
-            "browser.newtabpage.activity-stream.section.highlights.includePocket" = false;
-            "browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = false;
-            "browser.newtabpage.activity-stream.section.highlights.includeDownloads" = false;
-            "browser.newtabpage.activity-stream.section.highlights.includeVisited" = false;
-          }
-          |> lib.mapAttrs (
-            name: value: {
-              Status = "locked";
-              Value = value;
-            }
-          )
-        );
-
-      ExtensionSettings = (
-        [
-          [
-            "navbar"
-            "{446900e4-71c2-419f-a6a7-df9c091e268b}"
-          ] # Bitwarden Password Manager
-          [
-            "navbar"
-            "uBlock0@raymondhill.net"
-          ] # uBlock Origin
-          [
-            "menupanel"
-            "@ublacklist"
-          ] # uBlacklist
-          [
-            "menupanel"
-            "@contain-facebook"
-          ] # Facebook Container
-          [
-            "menupanel"
-            "@contain-google"
-          ] # Google Container
-          [
-            "menupanel"
-            "containerise@kinte.sh"
-          ] # Containerise
-          [
-            "menupanel"
-            "{12cf650b-1822-40aa-bff0-996df6948878}"
-          ] # cookies.txt
-          [
-            "menupanel"
-            "@testpilot-containers"
-          ] # Firefox Multi-Account Containers
-          [
-            "menupanel"
-            "{252ee273-8c8d-4609-b54d-62ae345be0a1}"
-          ] # IndicateTLS
-          [
-            "menupanel"
-            "ipvfoo@pmarks.net"
-          ] # IPvFoo
-          [
-            "menupanel"
-            "{e9090647-32ff-48e4-9c3c-1361e8fd270e}"
-          ] # Modern for Wikipedia
+      );
+
+      ExtensionSettings =
+        lib.pipe
           [
-            "menupanel"
-            "sponsorBlocker@ajay.app"
-          ] # SponsorBlock for YouTube - Skip Sponsorships
+            [
+              "navbar"
+              "{446900e4-71c2-419f-a6a7-df9c091e268b}"
+            ] # Bitwarden Password Manager
+            [
+              "navbar"
+              "uBlock0@raymondhill.net"
+            ] # uBlock Origin
+            [
+              "menupanel"
+              "@ublacklist"
+            ] # uBlacklist
+            [
+              "menupanel"
+              "@contain-facebook"
+            ] # Facebook Container
+            [
+              "menupanel"
+              "@contain-google"
+            ] # Google Container
+            [
+              "menupanel"
+              "containerise@kinte.sh"
+            ] # Containerise
+            [
+              "menupanel"
+              "{12cf650b-1822-40aa-bff0-996df6948878}"
+            ] # cookies.txt
+            [
+              "menupanel"
+              "@testpilot-containers"
+            ] # Firefox Multi-Account Containers
+            [
+              "menupanel"
+              "{252ee273-8c8d-4609-b54d-62ae345be0a1}"
+            ] # IndicateTLS
+            [
+              "menupanel"
+              "ipvfoo@pmarks.net"
+            ] # IPvFoo
+            [
+              "menupanel"
+              "{e9090647-32ff-48e4-9c3c-1361e8fd270e}"
+            ] # Modern for Wikipedia
+            [
+              "menupanel"
+              "sponsorBlocker@ajay.app"
+            ] # SponsorBlock for YouTube - Skip Sponsorships
+            [
+              "menupanel"
+              "de-DE@dictionaries.addons.mozilla.org"
+            ] # German Dictionary
+          ]
           [
-            "menupanel"
-            "de-DE@dictionaries.addons.mozilla.org"
-          ] # German Dictionary
-        ]
-        |> lib.map (config: {
-          name = (lib.elemAt config 1);
-          value = {
-            installation_mode = "normal_installed";
-            default_area = (lib.elemAt config 0);
-            install_url = "https://addons.mozilla.org/firefox/downloads/latest/${lib.elemAt config 1}/latest.xpi";
-          };
-        })
-        |> lib.listToAttrs
-      );
+            (lib.map (config: {
+              name = lib.elemAt config 1;
+              value = {
+                installation_mode = "normal_installed";
+                default_area = lib.elemAt config 0;
+                install_url = "https://addons.mozilla.org/firefox/downloads/latest/${lib.elemAt config 1}/latest.xpi";
+              };
+            }))
+            lib.listToAttrs
+          ];
     };
   };
 
-  wayland.windowManager.sway.config.startup = [
-    { command = "firefox"; }
-  ];
-
   xdg = {
     enable = true;
     mime.enable = true;
diff --git a/config/home/zaphyra/programs/fish.nix b/config/home/zaphyra/programs/fish.nix
@@ -1,8 +1,11 @@
-{ pkgs, lib, ... }:
+{
+  config,
+  ...
+}:
 
 {
 
-  home.persistence."/nix/persist/home/zaphyra".directories = [
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
     "fish/.local/share/fish"
   ];
 

@@ -11,4 +14,6 @@
     generateCompletions = true;
   };
 
+  programs.sherlock.settings.ignore = "fish";
+
 }
diff --git a/config/home/zaphyra/programs/fractal.nix b/config/home/zaphyra/programs/fractal.nix
@@ -1,14 +1,16 @@
-{ pkgs, ... }:
+{
+  config,
+  pkgs,
+  ...
+}:
 
 {
 
-  home = {
-    packages = [ pkgs.fractal ];
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "fractal/.local/share/fractal/"
+    "fractal/.cache/fractal/"
+  ];
 
-    persistence."/nix/persist/home/zaphyra".directories = [
-      "fractal/.local/share/fractal/"
-      "fractal/.cache/fractal/"
-    ];
-  };
+  home.packages = [ pkgs.fractal ];
 
 }
diff --git a/config/home/zaphyra/programs/fuzzel.nix b/config/home/zaphyra/programs/fuzzel.nix
@@ -0,0 +1,33 @@
+_:
+
+{
+
+  programs.fuzzel = {
+    enable = true;
+    settings = {
+      main = {
+        launch-prefix = "app2unit --fuzzel-compat --";
+        dpi-aware = false;
+        horizontal-pad = 15;
+        vertical-pad = 15;
+        inner-pad = 5;
+      };
+      border = {
+        width = 2;
+        radius = 6;
+      };
+      colors = {
+        background = "#00000080"; # Background color
+        text = "#d8daddff"; # Text (foreground) color of unselected entries
+        prompt = "#d8daddff"; # Text (foreground) color of prompt character(s)
+        input = "#d8daddff"; # Text (foreground) color of input string
+        match = "#d8daddff"; # Text (foreground) color of the matched substring
+        selection = "#ffffff1a"; # Background color of the selected entry
+        selection-text = "#d8daddff"; # Text (foreground) color of the selected entry
+        selection-match = "#b7d4edf2"; # Text (foreground) color of the matched substring of the selected entry
+        border = "#4aa96cff"; # The color of the match count stats printed at the right-hand side of the input prompt
+      };
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/programs/gajim.nix b/config/home/zaphyra/programs/gajim.nix
@@ -0,0 +1,16 @@
+{
+  config,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "gajim/.local/share/gajim"
+    "gajim/.config/gajim"
+  ];
+
+  home.packages = [ pkgs.gajim ];
+
+}
diff --git a/config/home/zaphyra/programs/ghostty.nix b/config/home/zaphyra/programs/ghostty.nix
@@ -1,7 +1,9 @@
-{ ... }:
+_:
 
 {
 
+  home.sessionVariables.TERMINAL = "ghostty";
+
   programs.ghostty = {
     enable = true;
     enableFishIntegration = true;
diff --git a/config/home/zaphyra/programs/git.nix b/config/home/zaphyra/programs/git.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 

@@ -7,7 +10,16 @@
     reinitgit = "rm -rf .git && git init && git add -A && git commit -m 'init'";
   };
 
-  programs.lazygit.enable = true;
+  programs.lazygit = {
+    enable = true;
+    settings = {
+      disableStartupPopups = true;
+      gui.nerdFontsVersion = "3";
+      git.overrideGpg = true;
+      os.editPreset = "micro";
+    };
+  };
+
   programs.git = {
     enable = true;
 
diff --git a/config/home/zaphyra/programs/gnome-calendar.nix b/config/home/zaphyra/programs/gnome-calendar.nix
@@ -0,0 +1,48 @@
+{
+  config,
+  pkgs,
+  ...
+}:
+
+let
+  gnome-online-accounts = pkgs.gnome-online-accounts.overrideAttrs (prevAttrs: {
+    mesonFlags = prevAttrs.mesonFlags ++ [
+      "-Dexchange=false"
+      "-Dgoogle=false"
+      "-Dkerberos=false"
+      "-Downcloud=false"
+      "-Dwindows_live=false"
+      "-Dms_graph=false"
+    ];
+  });
+
+in
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "evolution-data-server/.local/share/evolution"
+    "gnome-online-accounts/.config/goa-1.0"
+  ];
+
+  home.packages = with pkgs; [
+    gnome-online-accounts-gtk
+    (evolution-data-server-gtk4.override {
+      withGtk4 = true;
+      enableOAuth2 = false;
+    })
+    gnome-calendar
+  ];
+
+  dbus.packages = [ gnome-online-accounts ];
+
+  systemd.user.services.gnome-online-accounts = {
+    Unit.Description = "Gnome Online Accounts";
+
+    Service = {
+      Type = "dbus";
+      ExecStart = "${gnome-online-accounts}/libexec/goa-daemon";
+      BusName = "org.gnome.OnlineAccounts";
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/programs/gnome-obfuscate.nix b/config/home/zaphyra/programs/gnome-obfuscate.nix
@@ -0,0 +1,10 @@
+{
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.gnome-obfuscate ];
+
+}
diff --git a/config/home/zaphyra/programs/gnome-text-editor.nix b/config/home/zaphyra/programs/gnome-text-editor.nix
@@ -0,0 +1,22 @@
+{
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.gnome-text-editor ];
+
+  dconf.settings = {
+    "org/gnome/TextEditor" = {
+      highlight-current-line = true;
+      wrap-text = true;
+      show-line-numbers = true;
+      show-map = true;
+      show-right-margin = true;
+      indent-style = "space";
+      indent-width = 4;
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/programs/gpg.nix b/config/home/zaphyra/programs/gpg.nix
@@ -1,50 +1,19 @@
 {
-  inputs,
-  lib,
   pkgs,
   ...
 }:
 
 {
 
-  xdg = {
-    desktopEntries = {
-      gscriptor = {
-        name = "gscriptor";
-        settings = {
-          NoDisplay = "true";
-        };
-      };
-    };
-  };
-
   home = {
     packages = [ pkgs.pcsctools ];
 
-    sessionVariables = {
-      GNUPGHOME = lib.mkForce "$HOME/.gnupg";
-    };
-
     shellAliases = {
       gpg-card-relearn = "gpg-connect-agent 'scd serialno' 'learn --force' /bye";
     };
   };
 
-  wayland.windowManager.sway.extraConfig = ''
-    exec_always 'gpgconf --kill gpg-agent'
-  '';
-
   programs = {
-    zsh.initExtra = ''
-      export GPG_TTY=$(tty)
-      export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
-      gpgconf --launch gpg-agent
-    '';
-    fish.interactiveShellInit = ''
-      gpgconf --launch gpg-agent
-      set -gx SSH_AUTH_SOCK (gpgconf --list-dirs agent-ssh-socket)
-    '';
-
     gpg = {
       enable = true;
       mutableTrust = true;

@@ -58,6 +27,8 @@
       signByDefault = true;
       key = "95F0FE7CD7E6A022";
     };
+
+    sherlock.settings.ignore = "Gscriptor";
   };
 
   services = {

@@ -72,8 +43,6 @@
       defaultCacheTtlSsh = 600;
 
       sshKeys = [
-        # katja@ctu.cx
-        "0FA22A1EADBBE75767686D2C3778D14F1A267146"
         # katja@zaphyra.eu
         "595A90924C65444EF00F0890BA85DE2A57DD79B2"
       ];
diff --git a/config/home/zaphyra/programs/gtklock.nix b/config/home/zaphyra/programs/gtklock.nix
@@ -0,0 +1,20 @@
+{
+  pkgs,
+  ...
+}:
+
+{
+
+  tgc.programs.gtklock = {
+    enable = false;
+    systemd.enable = true;
+    settings.main = {
+      idle-hide = true;
+      idle-timeout = 10;
+    };
+    modules = [
+      pkgs.gtklock-playerctl-module
+    ];
+  };
+
+}
diff --git a/config/home/zaphyra/programs/helix.nix b/config/home/zaphyra/programs/helix.nix
@@ -1,10 +1,13 @@
-{ lib, pkgs, ... }:
+{
+  lib,
+  pkgs,
+  ...
+}:
 
 {
 
   home = {
-    sessionVariables.EDITOR = lib.mkForce "hx";
-    #    shellAliases.nano = lib.mkForce "hx";
+    # sessionVariables.EDITOR = lib.mkForce "hx";
   };
 
   programs.helix = {

@@ -30,10 +33,11 @@
         }
       ];
     };
-    extraPackages = with pkgs; [
-      nil
-      markdown-oxide
+    extraPackages = [
+      pkgs.markdown-oxide
     ];
   };
 
+  programs.sherlock.settings.ignore = "Helix";
+
 }
diff --git a/config/home/zaphyra/programs/htop.nix b/config/home/zaphyra/programs/htop.nix
@@ -1,4 +1,7 @@
-{ pkgs, lib, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 

@@ -17,11 +20,6 @@
     };
   };
 
-  xdg = lib.mkIf pkgs.stdenv.isLinux {
-    desktopEntries.htop = {
-      name = "Htop";
-      settings.NoDisplay = "true";
-    };
-  };
+  programs.sherlock.settings.ignore = "Htop";
 
 }
diff --git a/config/home/zaphyra/programs/imv.nix b/config/home/zaphyra/programs/imv.nix
@@ -1,14 +1,10 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
   home.packages = [ pkgs.imv ];
 
-  xdg.desktopEntries = {
-    imv-folder = {
-      name = "imv (Folder)";
-      settings.NoDisplay = "true";
-    };
-  };
-
 }
diff --git a/config/home/zaphyra/programs/javascript.nix b/config/home/zaphyra/programs/javascript.nix
@@ -1,14 +0,0 @@
-{ pkgs, ... }:
-
-{
-
-  home.packages = with pkgs; [
-    nodejs
-    pnpm
-  ];
-
-  programs.helix.extraPackages = [
-    pkgs.typescript-language-server
-  ];
-
-}
diff --git a/config/home/zaphyra/programs/languages/golang.nix b/config/home/zaphyra/programs/languages/golang.nix
@@ -0,0 +1,17 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  home = {
+    packages = [ pkgs.go ];
+    sessionVariables.GOPATH = "${config.xdg.dataHome}/go";
+
+  };
+  programs.micro.lsp-servers.go.command = lib.getExe pkgs.gopls;
+
+}
diff --git a/config/home/zaphyra/programs/languages/javascript.nix b/config/home/zaphyra/programs/languages/javascript.nix
@@ -0,0 +1,19 @@
+{
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = with pkgs; [
+    nodejs
+    pnpm
+  ];
+
+  programs.micro.lsp-servers.js.command = lib.getExe pkgs.typescript-language-server;
+  programs.helix.extraPackages = [
+    pkgs.typescript-language-server
+  ];
+
+}
diff --git a/config/home/zaphyra/programs/languages/nimlang.nix b/config/home/zaphyra/programs/languages/nimlang.nix
@@ -0,0 +1,20 @@
+{
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = with pkgs; [
+    nim
+    nimble
+  ];
+
+  programs.micro.lsp-servers.nim.command = lib.getExe pkgs.nimlangserver;
+
+  programs.helix.extraPackages = [
+    pkgs.nimlangserver
+  ];
+
+}
diff --git a/config/home/zaphyra/programs/languages/nix.nix b/config/home/zaphyra/programs/languages/nix.nix
@@ -0,0 +1,25 @@
+{
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.nixfmt-rfc-style ];
+
+  programs.helix.extraPackages = [
+    pkgs.nixd
+    pkgs.nil
+  ];
+
+  programs.micro.lsp-servers.nix = {
+    command = lib.getExe pkgs.nixd;
+    options = {
+      config = builtins.toJSON {
+        formatting.command = [ (lib.getExe pkgs.nixfmt-rfc-style) ];
+      };
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/programs/libreoffice.nix b/config/home/zaphyra/programs/libreoffice.nix
@@ -1,21 +1,12 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
   home.packages = [ pkgs.libreoffice-fresh ];
 
-  xdg.desktopEntries = {
-    impress.name = "LibreOffice Impress";
-    impress.settings.NoDisplay = "true";
-
-    math.name = "LibreOffice Math";
-    math.settings.NoDisplay = "true";
-
-    base.name = "LibreOffice Base";
-    base.settings.NoDisplay = "true";
-
-    draw.name = "LibreOffice Draw";
-    draw.settings.NoDisplay = "true";
-  };
+  programs.sherlock.settings.ignore = "LibreOffice *";
 
 }
diff --git a/config/home/zaphyra/programs/loupe.nix b/config/home/zaphyra/programs/loupe.nix
@@ -0,0 +1,39 @@
+{
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.loupe ];
+
+  xdg.mimeApps = {
+    enable = true;
+    defaultApplications = lib.genAttrs [
+      "image/jpeg"
+      "image/png"
+      "image/gif"
+      "image/webp"
+      "image/tiff"
+      "mage/bmp"
+      "image/svg+xml"
+      "image/svg+xml-compressed"
+      "image/avif"
+      "image/heic"
+    ] (_name: [ "org.gnome.Loupe.desktop" ]);
+    associations.added = lib.genAttrs [
+      "image/jpeg"
+      "image/png"
+      "image/gif"
+      "image/webp"
+      "image/tiff"
+      "mage/bmp"
+      "image/svg+xml"
+      "image/svg+xml-compressed"
+      "image/avif"
+      "image/heic"
+    ] (_name: [ "org.gnome.Loupe.desktop" ]);
+  };
+
+}
diff --git a/config/home/zaphyra/programs/mcfly.nix b/config/home/zaphyra/programs/mcfly.nix
@@ -1,8 +1,11 @@
-{ config, lib, ... }:
+{
+  config,
+  ...
+}:
 
 {
 
-  home.persistence."/nix/persist/home/zaphyra".directories = [
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
     "mcfly/.local/share/mcfly"
   ];
 
diff --git a/config/home/zaphyra/programs/micro.nix b/config/home/zaphyra/programs/micro.nix
@@ -1,37 +1,221 @@
-{ pkgs, lib, ... }:
+{
+  config,
+  systemConfig,
+  pkgs,
+  lib,
+  ...
+}:
 
 {
 
-  home = {
-    sessionVariables.EDITOR = "micro";
-    shellAliases.nano = "micro";
+  options.programs.micro.lsp-servers = lib.mkOption {
+    default = { };
+    type = lib.types.attrsOf (
+      lib.types.submodule {
+        options = {
+          command = lib.mkOption {
+            type = lib.types.str;
+          };
+          options = lib.mkOption {
+            inherit ((pkgs.formats.json { })) type;
+            default = { };
+          };
+        };
+      }
+    );
   };
 
-  programs.micro = {
-    enable = true;
-    settings = {
-      "*.nix".tabstospaces = true;
-      "*.nix".tabmovement = true;
-      "*.nix".tabsize = 2;
+  config = {
+    programs = {
+      sherlock.settings.ignore = "Micro";
+      micro = {
+        enable = true;
+        package =
+          if systemConfig.modules.presets.graphical.enable then pkgs.micro-with-wl-clipboard else pkgs.micro;
+        settings = {
+          "*.nix".tabstospaces = true;
+          "*.nix".tabmovement = true;
+          "*.nix".tabsize = 2;
+
+          "*.nim".tabstospaces = true;
+          "*.nim".tabmovement = true;
+          "*.nim".tabsize = 2;
 
-      "*.nim".tabstospaces = true;
-      "*.nim".tabmovement = true;
-      "*.nim".tabsize = 2;
+          clipboard = "terminal";
 
-      scrollbar = true;
-      eofnewline = false;
-      wordwrap = true;
-      softwrap = true;
+          scrollbar = true;
+          eofnewline = false;
+          wordwrap = true;
+          softwrap = true;
 
-      ignorecase = true;
-      savehistory = false;
+          ignorecase = true;
+          savehistory = false;
+
+          "lsp.formatOnSave" = true;
+          "lsp.tabcompletion" = true;
+          "lsp.autocompleteDetails" = false;
+          "lsp.server" =
+            if !systemConfig.modules.presets.graphical.enable then
+              ""
+            else
+              (lib.concatMapAttrsStringSep "," (
+                name: value:
+                lib.concatStringsSep "=" (
+                  [
+                    name
+                    value.command
+                  ]
+                  ++ (lib.optionals (lib.hasAttr "options" value) [
+                    (builtins.toJSON value.options)
+                  ])
+                )
+              ) config.programs.micro.lsp-servers);
+        };
+      };
     };
-  };
 
-  xdg = lib.mkIf pkgs.stdenv.isLinux {
-    desktopEntries.micro = {
-      name = "micro";
-      settings.NoDisplay = "true";
+    home = {
+      sessionVariables.EDITOR = "micro";
+      shellAliases.nano = "micro";
+      file = {
+        # keybindings
+        "${config.xdg.configHome}/micro/bindings.json".source = pkgs.writeText "micro-keybindings.json" (
+          builtins.toJSON {
+            "Alt-," = "PreviousTab";
+            "Alt-." = "NextTab";
+            "Alt-Backspace" = "DeleteWordLeft";
+            "Alt-CtrlH" = "DeleteWordLeft";
+            "Alt-F" = "FindLiteral";
+            "Alt-[" = "DiffPrevious|CursorStart";
+            "Alt-]" = "DiffNext|CursorEnd";
+            "Alt-a" = "StartOfLine";
+            "Alt-b" = "WordLeft";
+            "Alt-c" = "RemoveAllMultiCursors";
+            "Alt-e" = "EndOfLine";
+            "Alt-f" = "WordRight";
+            "Alt-g" = "ToggleKeyMenu";
+            "Alt-m" = "SpawnMultiCursorSelect";
+            "Alt-n" = "SpawnMultiCursor";
+            "Alt-p" = "RemoveMultiCursor";
+            "Alt-x" = "SkipMultiCursor";
+            "Alt-{" = "ParagraphPrevious";
+            "Alt-}" = "ParagraphNext";
+            "AltDown" = "MoveLinesDown";
+            "AltLeft" = "StartOfTextToggle";
+            "AltRight" = "EndOfLine";
+            "AltShiftDown" = "SpawnMultiCursorDown";
+            "AltShiftLeft" = "SelectToStartOfTextToggle";
+            "AltShiftRight" = "SelectToEndOfLine";
+            "AltShiftUp" = "SpawnMultiCursorUp";
+            "AltUp" = "MoveLinesUp";
+            "Backspace" = "Backspace";
+            "Backtab" = "OutdentSelection|OutdentLine";
+            "Ctrl-MouseLeft" = "MouseMultiCursor";
+            "Ctrl-a" = "SelectAll";
+            "Ctrl-b" = "ShellMode";
+            "Ctrl-c" = "Copy|CopyLine";
+            "Ctrl-d" = "DuplicateLine";
+            "Ctrl-e" = "CommandMode";
+            "Ctrl-f" = "Find";
+            "Ctrl-g" = "ToggleHelp";
+            "Ctrl-h" = "Backspace";
+            "Ctrl-j" = "PlayMacro";
+            "Ctrl-k" = "CutLine";
+            "Ctrl-l" = "command-edit:goto ";
+            "Ctrl-n" = "FindNext";
+            "Ctrl-o" = "OpenFile";
+            "Ctrl-p" = "FindPrevious";
+            "Ctrl-q" = "Quit";
+            "Ctrl-r" = "ToggleRuler";
+            "Ctrl-s" = "Save";
+            "Ctrl-t" = "AddTab";
+            "Ctrl-u" = "ToggleMacro";
+            "Ctrl-v" = "Paste";
+            "Ctrl-w" = "NextSplit";
+            "Ctrl-x" = "Cut|CutLine";
+            "Ctrl-y" = "Redo";
+            "Ctrl-z" = "Undo";
+            "CtrlDown" = "CursorEnd";
+            "CtrlEnd" = "CursorEnd";
+            "CtrlHome" = "CursorStart";
+            "CtrlPageDown" = "NextTab";
+            "CtrlPageUp" = "PreviousTab";
+            "AltPageDown" = "NextTab";
+            "AltPageUp" = "PreviousTab";
+            "CtrlShiftDown" = "SelectToEnd";
+            "CtrlShiftLeft" = "SelectWordLeft";
+            "CtrlShiftRight" = "SelectWordRight";
+            "CtrlShiftUp" = "SelectToStart";
+            "CtrlUp" = "CursorStart";
+            "Delete" = "Delete";
+            "Down" = "CursorDown";
+            "End" = "EndOfLine";
+            "Enter" = "InsertNewline";
+            "Esc" = "Escape";
+            "F10" = "Quit";
+            "F2" = "Save";
+            "F3" = "Find";
+            "F4" = "Quit";
+            "F7" = "Find";
+            "Home" = "StartOfText";
+            "Insert" = "ToggleOverwriteMode";
+            "Left" = "CursorLeft";
+            "MouseLeft" = "MousePress";
+            "MouseLeftDrag" = "MouseDrag";
+            "MouseLeftRelease" = "MouseRelease";
+            "MouseMiddle" = "PastePrimary";
+            "MouseWheelDown" = "ScrollDown";
+            "MouseWheelUp" = "ScrollUp";
+            "PageDown" = "CursorPageDown";
+            "PageUp" = "CursorPageUp";
+            "Right" = "CursorRight";
+            "ShiftDown" = "SelectDown";
+            "ShiftEnd" = "SelectToEndOfLine";
+            "ShiftHome" = "SelectToStartOfTextToggle";
+            "ShiftLeft" = "SelectLeft";
+            "ShiftPageDown" = "SelectPageDown";
+            "ShiftPageUp" = "SelectPageUp";
+            "ShiftRight" = "SelectRight";
+            "ShiftUp" = "SelectUp";
+            "Tab" = "Autocomplete|IndentSelection|InsertTab";
+            "Up" = "CursorUp";
+
+            # plugins
+            "Alt-/" = "lua:comment.comment";
+            "Alt-d" = "command:definition";
+            #      "Alt-f" = "command:format";
+            "Alt-k" = "command:hover";
+            "Alt-r" = "command:references";
+            "CtrlSpace" = "command:lspcompletion";
+            "CtrlUnderscore" = "lua:comment.comment";
+            "F1" = "command:cheat";
+            #      "F4" = "command:jumptag";
+            "F5" = "lua:wc.wordCount";
+          }
+        );
+
+        # plugins
+        "${config.xdg.configHome}/micro/plug/lsp".source = pkgs.fetchFromGitHub {
+          owner = "AndCake";
+          repo = "micro-plugin-lsp";
+          rev = "v0.6.3";
+          sha256 = "sha256-rZ9Vw9WPGNaJBGHKU40F6cBIYQ1JFtSKPDrheazKkPY=";
+        };
+
+        "${config.xdg.configHome}/micro/plug/detectindent".source = pkgs.fetchFromGitHub {
+          owner = "dmaluka";
+          repo = "micro-detectindent";
+          rev = "v1.1.0";
+          sha256 = "sha256-5bKEkOnhz0pyBR2UNw5vvYiTtpd96fBPTYW9jnETvq4=";
+        };
+
+        "${config.xdg.configHome}/micro/plug/wc".source = pkgs.fetchFromGitHub {
+          owner = "adamnpeace";
+          repo = "micro-wc-plugin";
+          rev = "b2c9957e521770eadc1ecae9d54c0a30f40a0a3d";
+          sha256 = "sha256-Z6MC2cet8+7XHv41G+SlAZViCqlh/9dk0CSt7HklnTg=";
+        };
+      };
     };
   };
 
diff --git a/config/home/zaphyra/programs/mpv.nix b/config/home/zaphyra/programs/mpv.nix
@@ -1,7 +1,5 @@
 {
-  config,
   pkgs,
-  lib,
   ...
 }:
 

@@ -12,9 +10,4 @@
     mpv.scripts = [ pkgs.mpvScripts.mpris ];
   };
 
-  xdg.desktopEntries = {
-    umpv.name = "umpv Media Player";
-    umpv.settings.NoDisplay = "true";
-  };
-
 }
diff --git a/config/home/zaphyra/programs/nautilus.nix b/config/home/zaphyra/programs/nautilus.nix
@@ -1,7 +1,7 @@
 {
-  inputs,
+  config,
+  lib,
   pkgs,
-  systemConfig,
   ...
 }:
 

@@ -13,13 +13,37 @@
   ];
 
   home.sessionVariables = {
-    NAUTILUS_4_EXTENSION_DIR = "${systemConfig.system.path}/lib/nautilus/extensions-4";
+    NAUTILUS_4_EXTENSION_DIR = "${config.home.profileDirectory}/lib/nautilus/extensions-4";
   };
 
   xdg.mimeApps.enable = true;
-  xdg.mimeApps.defaultApplications = {
-    "inode/directory" = [ "org.gnome.Nautilus.desktop" ];
-  };
+  xdg.mimeApps.defaultApplications = lib.genAttrs [
+    "inode/directory"
+    "application/x-7z-compressed"
+    "application/x-7z-compressed-tar"
+    "application/x-bzip"
+    "application/x-bzip-compressed-tar"
+    "application/x-compress"
+    "application/x-compressed-tar"
+    "application/x-cpio"
+    "application/x-gzip"
+    "application/x-lha"
+    "application/x-lzip"
+    "application/x-lzip-compressed-tar"
+    "application/x-lzma"
+    "application/x-lzma-compressed-tar"
+    "application/x-tar"
+    "application/x-tarz"
+    "application/x-xar"
+    "application/x-xz"
+    "application/x-xz-compressed-tar"
+    "application/zip"
+    "application/gzip"
+    "application/bzip2"
+    "application/x-bzip2-compressed-tar"
+    "application/vnd.rar;application/zstd"
+    "application/x-zstd-compressed-tar"
+  ] (_name: [ "org.gnome.Nautilus.desktop" ]);
 
   gtk.gtk4.extraCss = ''
     /* remove 'starred' in nautilus side-panel */

@@ -31,7 +55,7 @@
     }
   '';
 
-  dconf.settings = with inputs.homeManager.lib.hm.gvariant; {
+  dconf.settings = {
     "org/gnome/nautilus/list-view" = {
       use-tree-view = true;
       default-zoom-level = "small";
diff --git a/config/home/zaphyra/programs/networkManagerDmenu.nix b/config/home/zaphyra/programs/networkManagerDmenu.nix
@@ -0,0 +1,46 @@
+{
+  pkgs,
+  lib,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.networkmanager_dmenu ];
+
+  home.file.".config/networkmanager-dmenu/config.ini".text = lib.generators.toINI { } {
+    dmenu = {
+      dmenu_command = "${lib.getExe pkgs.fuzzel} --anchor=top-right --x-margin=13 --y-margin=13";
+      active_chars = "==";
+      highlight = true;
+      highlight_bold = true;
+      compact = false;
+      pinentry = lib.getExe pkgs.pinentry-gnome3;
+      wifi_icons = "󰤯󰤟󰤢󰤥󰤨";
+      format = "{name:<{max_len_name}s}  {sec:<{max_len_sec}s} {icon:>4}";
+      list_saved = false;
+      prompt = "Networks";
+    };
+
+    dmenu_passphrase = {
+      obscure = false;
+      obscure_color = "#222222";
+    };
+
+    pinentry = {
+      description = "Get network password";
+      prompt = "Password:";
+    };
+
+    editor = {
+      terminal = lib.getExe pkgs.ghostty;
+      gui_if_available = true;
+      gui = "${pkgs.networkmanagerapplet}/bin/nm-connection-editor";
+    };
+
+    nmdm.rescan_delay = 5;
+  };
+
+  programs.sherlock.settings.ignore = "NetworkManager Dmenu";
+
+}
diff --git a/config/home/zaphyra/programs/nim.nix b/config/home/zaphyra/programs/nim.nix
@@ -1,14 +0,0 @@
-{ pkgs, ... }:
-
-{
-
-  home.packages = with pkgs; [
-    nim
-    nimble
-  ];
-
-  programs.helix.extraPackages = [
-    pkgs.nimlangserver
-  ];
-
-}
diff --git a/config/home/zaphyra/programs/niri.nix b/config/home/zaphyra/programs/niri.nix
@@ -0,0 +1,250 @@
+{
+  config,
+  lib,
+  ...
+}:
+
+{
+
+  programs.niri.settings = {
+    input = {
+      workspace-auto-back-and-forth = true;
+
+      focus-follows-mouse = {
+        enable = true;
+        max-scroll-amount = "0%";
+      };
+
+      touchpad.click-method = "clickfinger";
+
+      keyboard.xkb = {
+        layout = "us,de,ru";
+        variant = "mac,qwerty,mac";
+        options = "grp:alt_shift_toggle";
+      };
+    };
+
+    outputs."eDP-1".scale = 1;
+
+    cursor.theme = config.gtk.cursorTheme.name;
+
+    gestures.hot-corners.enable = false;
+
+    layout = {
+      always-center-single-column = true;
+      gaps = 15;
+
+      default-column-width = {
+        proportion = 1.0;
+      };
+
+      focus-ring = {
+        width = 2;
+        inactive.color = "rgba(59, 135, 86, .9)";
+        active.color = "rgba(74, 169, 108, .9)";
+      };
+
+      tab-indicator = {
+        gaps-between-tabs = 10;
+        position = "top";
+      };
+    }
+    // (lib.genAttrs [ "preset-column-widths" "preset-window-heights" ] (_name: [
+      { proportion = 1.0; }
+      { proportion = 0.75; }
+      { proportion = 0.5; }
+      { proportion = 1.0 / 3.0; }
+      { proportion = 0.25; }
+    ]));
+
+    environment = {
+      QT_QPA_PLATFORM = "wayland";
+      QT_WAYLAND_FORCE_DPI = "physical";
+      QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
+    };
+
+    prefer-no-csd = true;
+
+    workspaces = {
+      "01-Web".name = "Web";
+      "02-Mail".name = "Mail";
+      "03-Term".name = "Term";
+      "04-Chat".name = "Chat";
+    };
+
+    window-rules = [
+      {
+        shadow.enable = true;
+        matches = [
+          {
+            is-floating = true;
+          }
+        ];
+      }
+      {
+        geometry-corner-radius = lib.genAttrs [ "bottom-left" "bottom-right" "top-left" "top-right" ] (
+          _name: 6.0
+        );
+        clip-to-geometry = true;
+      }
+      {
+        matches = [
+          {
+            at-startup = true;
+            app-id = "org.gnome.Fractal$";
+          }
+          {
+            at-startup = true;
+            app-id = "im.dino.Dino$";
+          }
+          {
+            at-startup = true;
+            app-id = "org.gajim.Gajim$";
+          }
+        ];
+
+        open-on-workspace = "Chat";
+        default-column-display = "tabbed";
+      }
+      {
+        matches = [
+          { app-id = "firefox$"; }
+          { app-id = "thunderbird$"; }
+        ];
+
+        open-maximized = true;
+      }
+      {
+        matches = [
+          { app-id = "org.gnome.NautilusPreviewer$"; }
+        ];
+
+        open-floating = true;
+      }
+      {
+        matches = [
+          { app-id = "thunderbird$"; }
+        ];
+
+        open-on-workspace = "Mail";
+      }
+      {
+        matches = [
+          {
+            app-id = "firefox$";
+            title = "^Picture-in-Picture$";
+          }
+        ];
+
+        open-floating = true;
+        default-column-width.fixed = 480;
+        default-window-height.fixed = 270;
+        default-floating-position = {
+          x = 32;
+          y = 32;
+          relative-to = "bottom-right";
+        };
+      }
+    ];
+
+    binds = with config.lib.niri.actions; {
+      "Mod+Shift+E".action = quit;
+      "Mod+Space".action = lib.mkDefault (spawn (lib.getExe pkgs.fuzzel));
+      "Mod+Return".action = lib.mkDefault (spawn config.home.sessionVariables.TERMINAL);
+
+      "Mod+L".action = spawn (lib.getExe' pkgs.systemd "loginctl") "lock-session";
+      "Mod+Z".action = power-off-monitors;
+      # "Mod+Z".action = spawn (lib.getExe' pkgs.systemd "systemctl") "suspend";
+
+      "Mod+W" = {
+        action = close-window;
+        repeat = false;
+      };
+
+      "XF86AudioRaiseVolume" = {
+        allow-when-locked = true;
+        action = lib.mkDefault (spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "1%+");
+      };
+      "XF86AudioLowerVolume" = {
+        allow-when-locked = true;
+        action = lib.mkDefault (spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "1%-");
+      };
+      "XF86MonBrightnessUp" = {
+        allow-when-locked = true;
+        action = lib.mkDefault (spawn (lib.getExe pkgs.brightnessctl) "s" "+5%");
+      };
+      "XF86MonBrightnessDown" = {
+        allow-when-locked = true;
+        action = lib.mkDefault (spawn (lib.getExe pkgs.brightnessctl) "s" "5%-");
+      };
+
+      "Mod+Tab".action = toggle-overview;
+
+      "Mod+1".action = focus-workspace "Web";
+      "Mod+2".action = focus-workspace "Mail";
+      "Mod+3".action = focus-workspace "Term";
+      "Mod+4".action = focus-workspace "Chat";
+      "Mod+5".action = focus-workspace 5;
+      "Mod+6".action = focus-workspace 6;
+      "Mod+7".action = focus-workspace 7;
+      "Mod+8".action = focus-workspace 8;
+      "Mod+9".action = focus-workspace 9;
+
+      "Mod+Shift+1".action.move-column-to-workspace = "Web";
+      "Mod+Shift+2".action.move-column-to-workspace = "Mail";
+      "Mod+Shift+3".action.move-column-to-workspace = "Term";
+      "Mod+Shift+4".action.move-column-to-workspace = "Chat";
+      "Mod+Shift+5".action.move-column-to-workspace = 5;
+      "Mod+Shift+6".action.move-column-to-workspace = 6;
+      "Mod+Shift+7".action.move-column-to-workspace = 7;
+      "Mod+Shift+8".action.move-column-to-workspace = 8;
+      "Mod+Shift+9".action.move-column-to-workspace = 9;
+
+      "Mod+Prior".action = focus-workspace-up;
+      "Mod+Next".action = focus-workspace-down;
+
+      "Mod+Shift+Prior".action = move-window-up-or-to-workspace-up;
+      "Mod+Shift+Next".action = move-window-down-or-to-workspace-down;
+
+      "Mod+Ctrl+Prior".action = focus-monitor-up;
+      "Mod+Ctrl+Next".action = focus-monitor-down;
+
+      "Mod+Left".action = focus-column-left;
+      "Mod+Right".action = focus-column-right;
+      "Mod+Up".action = focus-window-or-workspace-up;
+      "Mod+Down".action = focus-window-or-workspace-down;
+
+      "Mod+Shift+Left".action = move-column-left;
+      "Mod+Shift+Right".action = move-column-right;
+      "Mod+Shift+Up".action = move-window-up;
+      "Mod+Shift+Down".action = move-window-down;
+
+      "Mod+R".action = switch-preset-column-width;
+      "Mod+Shift+R".action = switch-preset-window-height;
+      "Mod+Ctrl+R".action = reset-window-height;
+
+      "Mod+C".action = center-window;
+
+      "Mod+F".action = maximize-column;
+      "Mod+Ctrl+F".action = expand-column-to-available-width;
+      "Mod+Shift+F".action = fullscreen-window;
+      "Mod+Alt+F".action = set-column-width "50%";
+
+      "Mod+Minus".action = set-column-width "-10%";
+      "Mod+Equal".action = set-column-width "+10%";
+      "Mod+Shift+Minus".action = set-window-height "-10%";
+      "Mod+Shift+Equal".action = set-window-height "+10%";
+
+      "Mod+Shift+Space".action = toggle-window-floating;
+
+      "Mod+Shift+Return".action = spawn (lib.getExe pkgs.tgc.nirius) "toggle-follow-mode";
+
+      "Mod+T".action = toggle-column-tabbed-display;
+
+      "Mod+Print".action = spawn (lib.getExe pkgs.hyprpicker) "--lowercase-hex" "--autocopy";
+      "Print".action = screenshot;
+      "Alt+Print".action = screenshot-window;
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/programs/nix-cleanup.nix b/config/home/zaphyra/programs/nix-cleanup.nix
@@ -1,22 +0,0 @@
-{ pkgs, ... }:
-
-{
-
-  home.packages = [
-    (pkgs.writeShellScriptBin "nix-cleanup" ''
-      set -eu
-
-      # Delete everything from this profile that isn't currently needed
-      nix-env --delete-generations old
-
-      # Delete generations older than a week
-      nix-collect-garbage
-      nix-collect-garbage --delete-older-than 7d
-
-      # Optimize
-      nix-store --gc --print-dead
-      nix-store --optimise
-    '')
-  ];
-
-}
diff --git a/config/home/zaphyra/programs/nmgui.nix b/config/home/zaphyra/programs/nmgui.nix
@@ -0,0 +1,21 @@
+{
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.unstable.nmgui ];
+
+  programs.niri.settings.window-rules = [
+    {
+      matches = [ { app-id = "com.network.manager$"; } ];
+
+      open-floating = true;
+      open-focused = true;
+      default-column-width.fixed = 500;
+      default-window-height.fixed = 600;
+    }
+  ];
+
+}
diff --git a/config/home/zaphyra/programs/ocrmypdf.nix b/config/home/zaphyra/programs/ocrmypdf.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/programs/overskride.nix b/config/home/zaphyra/programs/overskride.nix
@@ -0,0 +1,10 @@
+{
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.overskride ];
+
+}
diff --git a/config/home/zaphyra/programs/paper-plane.nix b/config/home/zaphyra/programs/paper-plane.nix
@@ -1,7 +0,0 @@
-{ pkgs, ... }:
-
-{
-
-  home.packages = [ pkgs.paper-plane ];
-
-}
diff --git a/config/home/zaphyra/programs/papers.nix b/config/home/zaphyra/programs/papers.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/programs/password-store.nix b/config/home/zaphyra/programs/password-store.nix
@@ -1,13 +1,11 @@
-{ pkgs, lib, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
-  home = {
-    packages = [ pkgs.pwgen ];
-    sessionVariables = {
-      PASSWORD_STORE_DIR = lib.mkForce "\$HOME/.local/share/password-store";
-    };
-  };
+  home.packages = [ pkgs.pwgen ];
 
   programs = {
     password-store = {
diff --git a/config/home/zaphyra/programs/pdfarranger.nix b/config/home/zaphyra/programs/pdfarranger.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/programs/phockup.nix b/config/home/zaphyra/programs/phockup.nix
@@ -1,7 +0,0 @@
-{ pkgs, ... }:
-
-{
-
-  home.packages = [ pkgs.phockup ];
-
-}
diff --git a/config/home/zaphyra/programs/pipewire.nix b/config/home/zaphyra/programs/pipewire.nix
@@ -0,0 +1,61 @@
+{
+  config,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = with pkgs; [
+    pwvucontrol
+    sonusmix
+  ];
+
+  home.file."${config.xdg.configHome}/pipewire/pipewire.conf.d/10-chloe-raop.conf".text =
+    let
+      raopSink = ipAddr: name: {
+        name = "libpipewire-module-raop-sink";
+        args = {
+          "raop.ip" = ipAddr;
+          "raop.port" = 7000;
+          "raop.name" = name;
+          "raop.encryption.type" = "auth_setup";
+        };
+      };
+
+    in
+    builtins.toJSON {
+      "context.modules" = [
+        { name = "libpipewire-module-zeroconf-discover"; }
+        {
+          name = "libpipewire-module-raop-discover";
+          args."roap.discover-local" = true;
+        }
+        (raopSink "192.168.2.63" "Living Room")
+        (raopSink "192.168.2.57" "Bed Room")
+        (raopSink "192.168.2.54" "Datacenter")
+        (raopSink "192.168.2.80" "Kitchen")
+        {
+          name = "libpipewire-module-combine-stream";
+          args = {
+            "node.name" = "combine_sink";
+            "node.description" = "Multi-Room";
+            "combine.mode" = "sink";
+            "combine.latency-compensate" = false;
+            "stream.rules" = [
+              {
+                actions."create-stream" = { };
+                matches = [
+                  {
+                    "media.class" = "Audio/Sink";
+                    "node.name" = "~raop_sink.*";
+                  }
+                ];
+              }
+            ];
+          };
+        }
+      ];
+    };
+
+}
diff --git a/config/home/zaphyra/programs/plattenalbum.nix b/config/home/zaphyra/programs/plattenalbum.nix
@@ -0,0 +1,10 @@
+{
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.plattenalbum ];
+
+}
diff --git a/config/home/zaphyra/programs/profanity.nix b/config/home/zaphyra/programs/profanity.nix
@@ -0,0 +1,16 @@
+{
+  config,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "profanity/.config/profanity/"
+    "profanity/.local/share/profanity/"
+  ];
+
+  home.packages = [ pkgs.profanity ];
+
+}
diff --git a/config/home/zaphyra/programs/shellUtilities.nix b/config/home/zaphyra/programs/shellUtilities.nix
@@ -1,4 +1,8 @@
-{ pkgs, ... }:
+{
+  config,
+  pkgs,
+  ...
+}:
 
 {
 

@@ -18,55 +22,57 @@
     grep = "rg";
     find = "fd";
 
-    backgrounditems = ''bgiparser -f  "$HOME/Library/Application Support/com.apple.backgroundtaskmanagementagent/backgrounditems.btm" -c'';
+    zzz = "sleep 1 && systemctl suspend";
 
-    zzz = (if pkgs.stdenv.isLinux then "sleep 1 && systemctl suspend" else "pmset sleepnow");
+    wget = "wget --hsts-file=\"${config.xdg.dataHome}/wget-hsts\"";
   };
 
-  home.packages =
-    with pkgs;
-    [
-      coreutils
-      trash-cli
+  home.packages = with pkgs; [
+    coreutils
+    trash-cli
+
+    pwgen
 
-      pwgen
+    (pkgs.writeShellScriptBin "use" ''
+      declare -a all
+      for p in "$@"; do
+        all+=("''${NIXPKGS_PATH}#$p")
+      done
+      eval nix shell ''${all[@]}
+    '')
 
-      (pkgs.writeShellScriptBin "use" ''
-        declare -a all
-        for p in "$@"; do
-          all+=("''${NIXPKGS_PATH}#$p")
-        done
-        eval nix shell ''${all[@]}
-      '')
+    wget
+    curl
+    rsync
 
-      wget
-      curl
-      rsync
+    ripgrep
+    fd
 
-      ripgrep
-      fd
+    fx
+    file
+    bc
 
-      fx
-      file
-      bc
+    unzip
 
-      unzip
+    smartmontools
 
-      smartmontools
+    gptfdisk
+    e2fsprogs
+    dosfstools
 
-      gptfdisk
-      e2fsprogs
-      dosfstools
-    ]
-    ++ lib.optionals pkgs.stdenv.isLinux [
-      (pkgs.writeShellScriptBin "open" ''
-        ${pkgs.coreutils}/bin/nohup ${pkgs.xdg-utils}/bin/xdg-open "$@" > /dev/null 2>&1
-      '')
+    (pkgs.writeShellScriptBin "open" (
+      lib.concatStringsSep " " [
+        (lib.getExe' pkgs.coreutils "nohup")
+        (lib.getExe' pkgs.xdg-utils "xdg-open")
+        "$@"
+        "> /dev/null 2>&1"
+      ]
+    ))
 
-      usbutils
-      pciutils
+    usbutils
+    pciutils
 
-      lm_sensors
-    ];
+    lm_sensors
+  ];
 
 }
diff --git a/config/home/zaphyra/programs/sherlock-launcher.nix b/config/home/zaphyra/programs/sherlock-launcher.nix
@@ -0,0 +1,89 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "sherlock/.cache/sherlock"
+  ];
+
+  programs.niri.settings.binds = with config.lib.niri.actions; {
+    "Mod+Space".action = spawn (lib.getExe pkgs.sherlock-launcher);
+  };
+
+  programs.sherlock = {
+    enable = true;
+    settings = {
+      style = ''
+        window {
+          border-radius: 5px;
+          border: 2px solid rgba(255, 255, 255, 0.08);
+        }
+      '';
+      ignore = ''
+        btop++
+      '';
+      config = {
+        default_apps = {
+          terminal = "${config.home.sessionVariables.TERMINAL} -e";
+          browser = "${config.home.sessionVariables.BROWSER} %u";
+        };
+        behavior.global_prefix = "app2unit";
+        caching.enable = true;
+      };
+      launchers = [
+        {
+          name = "Weather";
+          type = "weather";
+          args.location = "darmstadt";
+          args.update_interval = 30;
+          home = "OnlyHome";
+          priority = 1;
+          async = true;
+          shortcut = false;
+          spawn_focus = false;
+          actions = [
+            {
+              name = "Show on wttr.in";
+              exec = "https://www.wttr.in/darmstadt";
+              icon = "emblem-symbolic-link";
+              method = "web_launcher";
+            }
+          ];
+        }
+        {
+          name = "App Launcher";
+          type = "app_launcher";
+          alias = "app";
+          priority = 3;
+          home = "OnlyHome";
+        }
+        {
+          name = "Emoji Picker";
+          type = "emoji_picker";
+          alias = "emoji";
+          priority = 4;
+          home = "OnlyHome";
+        }
+      ];
+    };
+  };
+
+  # systemd.user.services.sherlock = {
+  #   Unit = {
+  #     Description = "sherlock daemon";
+  #     After = [ "graphical-session.target" ];
+  #   };
+  #   Service = {
+  #     ExecStart = "${lib.getExe pkgs.sherlock-launcher} --daemonize";
+  #     Restart = "on-failure";
+  #     RestartSec = 5;
+  #   };
+  #   Install.WantedBy = [ "graphical-session.target" ];
+  # };
+
+}
diff --git a/config/home/zaphyra/programs/ssh.nix b/config/home/zaphyra/programs/ssh.nix
@@ -1,8 +1,12 @@
-{ ... }:
+{
+  config,
+  ...
+}:
 
 {
 
-  home.persistence."/nix/persist/home/zaphyra".files = [
+  home.file.".ssh/known_hosts".force = true;
+  home.persistence."/nix/persist/home/${config.home.username}".files = [
     "ssh/.ssh/known_hosts"
   ];
 
diff --git a/config/home/zaphyra/programs/swaylock.nix b/config/home/zaphyra/programs/swaylock.nix
@@ -0,0 +1,44 @@
+{
+  inputs,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  programs.swaylock = {
+    enable = true;
+    package = pkgs.swaylock-plugin-fprintd;
+    settings = {
+      # clock = true;
+
+      indicator = true;
+      ring-color = "4aa96c";
+      show-failed-attempts = true;
+      fingerprint = true;
+
+      command = "${lib.getExe pkgs.tgc.shaderbg} '*' --fps 10 ${inputs.self.resources.shaders.background1}";
+
+      # image = "/home/zaphyra/Pictures/Backgrounds/lock.png";
+      # scaling = "fit";
+      # color = "ffffaf";
+    };
+  };
+
+  systemd.user.services.swaylock = {
+    Unit = {
+      OnSuccess = [ "unlock.target" ];
+      PartOf = [ "lock.target" ];
+      After = [ "lock.target" ];
+    };
+    Service = {
+      ExecStart = lib.getExe config.programs.swaylock.package;
+      Restart = "on-failure";
+      RestartSec = 0;
+    };
+    Install.WantedBy = [ "lock.target" ];
+  };
+
+}
diff --git a/config/home/zaphyra/programs/texlive.nix b/config/home/zaphyra/programs/texlive.nix
@@ -1,7 +0,0 @@
-{ pkgs, ... }:
-
-{
-
-  home.packages = [ pkgs.texlive.combined.scheme-full ];
-
-}
diff --git a/config/home/zaphyra/programs/thunderbird.nix b/config/home/zaphyra/programs/thunderbird.nix
@@ -1,4 +1,5 @@
 {
+  systemConfig,
   config,
   pkgs,
   lib,

@@ -7,20 +8,32 @@
 
 {
 
-  home.packages = [ pkgs.thunderbird ];
-
-  home.persistence."/nix/persist/home/zaphyra".directories = [
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
     "thunderbird/.thunderbird/"
     "thunderbird/.cache/thunderbird"
   ];
 
-  systemd.user.services.thunderbird = lib.mkIf config.wayland.windowManager.sway.enable {
+  home.packages = [ pkgs.thunderbird ];
+
+  systemd.user.services.thunderbird = {
     Unit.After = [ "graphical-session-pre.target" ];
     Unit.PartOf = [ "graphical-session.target" ];
 
     Service = {
-      Environment = "PATH=/run/wrappers/bin:/home/zaphyra/.nix-profile/bin:/etc/profiles/per-user/zaphyra/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin";
-      ExecStart = "${pkgs.thunderbird}/bin/thunderbird";
+      Environment =
+        "PATH="
+        + (lib.makeBinPath [
+          "/run/wrappers"
+          (
+            if !systemConfig.nix.settings.use-xdg-base-directories then
+              "/home/${config.home.username}/.nix-profile"
+            else
+              "/home/${config.home.username}/.local/state/nix/profile"
+          )
+          "/nix/var/nix/profiles/default"
+          "/run/current-system/sw"
+        ]);
+      ExecStart = lib.getExe pkgs.thunderbird;
       Restart = "always";
       RestartSec = 5;
     };

@@ -28,13 +41,6 @@
     Install.WantedBy = [ "graphical-session.target" ];
   };
 
-  wayland.windowManager.sway.config.startup = [
-    {
-      always = true;
-      command = "systemctl --user restart thunderbird";
-    }
-  ];
-
   xdg = {
     enable = true;
     mime.enable = true;
diff --git a/config/home/zaphyra/programs/tmux.nix b/config/home/zaphyra/programs/tmux.nix
@@ -1,4 +1,4 @@
-{ config, lib, ... }:
+_:
 
 {
 
diff --git a/config/home/zaphyra/programs/tuba.nix b/config/home/zaphyra/programs/tuba.nix
@@ -1,13 +1,17 @@
-{ lib, pkgs, ... }:
-
 {
+  config,
+  pkgs,
+  ...
+}:
 
-  home.packages = [ pkgs.tuba ];
+{
 
-  home.persistence."/nix/persist/home/zaphyra".directories = [
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
     "tuba/.cache/tuba"
   ];
 
+  home.packages = [ pkgs.tuba ];
+
   dconf.settings = {
     "dev/geopjr/Tuba" = {
       work-in-background = true;
diff --git a/config/home/zaphyra/programs/typst.nix b/config/home/zaphyra/programs/typst.nix
@@ -1,12 +1,21 @@
-{ lib, pkgs, ... }:
+{
+  lib,
+  pkgs,
+  ...
+}:
 
 {
 
   home.packages = with pkgs; [
     typst
     typst-live
+    typewriter
   ];
 
+  programs.micro.lsp-servers.typ = {
+    command = lib.getExe pkgs.unstable.tinymist;
+  };
+
   programs.helix.languages = {
     language-server.tinymist = {
       command = lib.getExe pkgs.unstable.tinymist;
diff --git a/config/home/zaphyra/programs/wleave.nix b/config/home/zaphyra/programs/wleave.nix
@@ -0,0 +1,50 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.packages = [
+    (pkgs.writeShellScriptBin "wleave" ''
+      ${lib.getExe pkgs.wleave} --buttons-per-row 5 --column-spacing 10 --margin-bottom 440 --margin-top 440 $@
+    '')
+  ];
+
+  home.file."${config.xdg.configHome}/wleave/layout".text = lib.concatStringsSep "\n" (
+    lib.map (elem: builtins.toJSON elem) [
+      {
+        label = "lock";
+        action = "loginctl lock-session";
+        text = "Lock";
+        keybind = "l";
+      }
+      {
+        label = "suspend";
+        action = "systemctl suspend";
+        text = "Suspend";
+        keybind = "u";
+      }
+      {
+        label = "logout";
+        action = "loginctl terminate-user $USER";
+        text = "Logout";
+        keybind = "e";
+      }
+      {
+        label = "shutdown";
+        action = "systemctl poweroff";
+        text = "Shutdown";
+        keybind = "s";
+      }
+      {
+        label = "reboot";
+        action = "systemctl reboot";
+        text = "Reboot";
+        keybind = "r";
+      }
+    ]
+  );
+}
diff --git a/config/home/zaphyra/programs/yazi.nix b/config/home/zaphyra/programs/yazi.nix
@@ -0,0 +1,37 @@
+_:
+
+{
+
+  programs.yazi = {
+    enable = true;
+    settings = {
+      mgr = {
+        show_hidden = false;
+        sort_by = "natural";
+        sort_dir_first = true;
+        sort_reverse = true;
+        linemode = "size_and_mtime";
+      };
+    };
+
+    initLua = ''
+      -- ~/.config/yazi/init.lua
+      function Linemode:size_and_mtime()
+        local time = math.floor(self._file.cha.mtime or 0)
+        if time == 0 then
+          time = ""
+        elseif os.date("%Y", time) == os.date("%Y") then
+          time = os.date("%b %d %H:%M", time)
+        else
+          time = os.date("%b %d  %Y", time)
+        end
+
+        local size = self._file:size()
+        return string.format("%s %s", size and ya.readable_size(size) or "-", time)
+      end
+    '';
+  };
+
+  programs.sherlock.settings.ignore = "Yazi";
+
+}
diff --git a/config/home/zaphyra/programs/yt-dlp.nix b/config/home/zaphyra/programs/yt-dlp.nix
@@ -1,7 +1,5 @@
 {
-  config,
   pkgs,
-  lib,
   ...
 }:
 
diff --git a/config/home/zaphyra/programs/zathura.nix b/config/home/zaphyra/programs/zathura.nix
@@ -1,4 +1,7 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  ...
+}:
 
 {
 
diff --git a/config/home/zaphyra/programs/zoxide.nix b/config/home/zaphyra/programs/zoxide.nix
@@ -1,7 +1,14 @@
-{ ... }:
+{
+  config,
+  ...
+}:
 
 {
 
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "zoxide/.local/share/zoxide"
+  ];
+
   programs.zoxide = {
     enable = true;
     enableFishIntegration = true;
diff --git a/config/home/zaphyra/services/batsignal.nix b/config/home/zaphyra/services/batsignal.nix
@@ -0,0 +1,23 @@
+_:
+
+{
+
+  services.batsignal = {
+    enable = true;
+    extraArgs = [
+      # expire notifications
+      "-e"
+      # show message when battery begins charging/discharging
+      "-p"
+      # minimum number of SECONDS to wait between battery checks
+      "-m10"
+      # bat levels
+      "-w20"
+      "-c10"
+      "-d5"
+      "-D"
+      "systemctl suspend"
+    ];
+  };
+
+}
diff --git a/config/home/zaphyra/services/dssd.nix b/config/home/zaphyra/services/dssd.nix
@@ -0,0 +1,17 @@
+{
+  config,
+  lib,
+  ...
+}:
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "dssd/.local/state/dssd"
+  ];
+
+  services = {
+    dssd.enable = true;
+    gnome-keyring.enable = lib.mkForce false;
+  };
+
+}
diff --git a/config/home/zaphyra/services/easyeffects.nix b/config/home/zaphyra/services/easyeffects.nix
@@ -1,28 +0,0 @@
-{ pkgs, ... }:
-
-{
-
-  home.packages = [ pkgs.easyeffects ];
-
-  systemd.user.services.easyeffects = {
-    Unit.After = [ "graphical-session-pre.target" ];
-    Unit.PartOf = [ "graphical-session.target" ];
-
-    Service = {
-      Environment = "PATH=/run/wrappers/bin:/home/zaphyra/.nix-profile/bin:/etc/profiles/per-user/zaphyra/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin";
-      ExecStart = "${pkgs.easyeffects}/bin/easyeffects --gapplication-service";
-      Restart = "always";
-      RestartSec = 5;
-    };
-
-    Install.WantedBy = [ "graphical-session.target" ];
-  };
-
-  wayland.windowManager.sway.config.startup = [
-    {
-      always = true;
-      command = "systemctl --user restart easyeffects";
-    }
-  ];
-
-}
diff --git a/config/home/zaphyra/services/gnome-keyring.nix b/config/home/zaphyra/services/gnome-keyring.nix
@@ -0,0 +1,20 @@
+{
+  config,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "keyring/.local/share/keyrings"
+  ];
+
+  services.gnome-keyring = {
+    enable = true;
+    components = [
+      "pkcs11"
+      "secrets"
+    ];
+  };
+
+}
diff --git a/config/home/zaphyra/services/gomuks-web.nix b/config/home/zaphyra/services/gomuks-web.nix
@@ -0,0 +1,27 @@
+{
+  inputs,
+  config,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "gomuks/.config/gomuks"
+    "gomuks/.local/share/gomuks"
+    "gomuks/.local/state/gomuks"
+    "gomuks/.cache/gomuks"
+  ];
+
+  tgc.services.gomuks-web = {
+    enable = true;
+    package = pkgs.tgc.gomuks-web.override {
+      extraPatches = [
+        inputs.self.resources.patches.gomuks-web-css
+      ];
+    };
+    disableAuth = true;
+  };
+
+}
diff --git a/config/home/zaphyra/services/mako.nix b/config/home/zaphyra/services/mako.nix
@@ -1,4 +1,8 @@
-{ pkgs, ... }:
+{
+  pkgs,
+  lib,
+  ...
+}:
 
 {
 

@@ -22,7 +26,7 @@
     Unit.PartOf = [ "graphical-session.target" ];
 
     Service = {
-      ExecStart = "${pkgs.mako}/bin/mako";
+      ExecStart = lib.getExe pkgs.mako;
       Restart = "always";
       RestartSec = 5;
     };

@@ -30,11 +34,4 @@
     Install.WantedBy = [ "graphical-session.target" ];
   };
 
-  wayland.windowManager.sway.config.startup = [
-    {
-      always = true;
-      command = "systemctl --user restart mako";
-    }
-  ];
-
 }
diff --git a/config/home/zaphyra/services/owntone.nix b/config/home/zaphyra/services/owntone.nix
@@ -0,0 +1,67 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "owntone/.local/share/owntone"
+  ];
+
+  systemd.user.services.owntone =
+    let
+      configFile = pkgs.writeText "owntone.conf" ''
+        general {
+          uid = "${config.home.username}"
+          db_path = "/home/${config.home.username}/.local/share/owntone/db_songs3.db"
+          loglevel = log
+          logfile = "/home/${config.home.username}/.local/share/owntone/owntone.log"
+          cache_dir = "/home/${config.home.username}/.local/share/owntone/cache"
+          speaker_autoselect = true
+        }
+
+        airplay_shared {
+          control_port = 7200
+          timing_port = 7201
+        }
+
+        library {
+          name = "owntone on %h"
+          port = 3689
+          clear_queue_on_stop_disable = true
+          directories = { "/home/${config.home.username}/Music", "/home/${config.home.username}/Audiobooks" }
+          audiobooks = { "/Audiobooks" }
+        }
+
+        audio {
+          nickname = "Computer"
+          type = "pulseaudio"
+        }
+
+        streaming {}
+      '';
+    in
+    {
+      Unit = {
+        Description = "owntone music server";
+        ConditionEnvironment = [ "WAYLAND_DISPLAY" ];
+        PartOf = [ "graphical-session.target" ];
+        After = [
+          "graphical-session.target"
+          "pipewire-pulse.service"
+        ];
+        StartLimitBurst = 5;
+        StartLimitIntervalSec = 10;
+      };
+      Service = {
+        ExecStart = "${lib.getExe pkgs.owntone} -f -c ${configFile}";
+        Restart = "on-failure";
+        RestartSec = 5;
+      };
+      Install.WantedBy = [ "graphical-session.target" ];
+    };
+
+}
diff --git a/config/home/zaphyra/services/playerctl.nix b/config/home/zaphyra/services/playerctl.nix
@@ -0,0 +1,21 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+
+{
+
+  services = {
+    playerctld.enable = true;
+    mpris-proxy.enable = true;
+  };
+
+  programs.niri.settings.binds = with config.lib.niri.actions; {
+    "XF86AudioPlay".action = spawn (lib.getExe pkgs.playerctl) "play-pause";
+    "XF86AudioNext".action = spawn (lib.getExe pkgs.playerctl) "next";
+    "XF86AudioPrev".action = spawn (lib.getExe pkgs.playerctl) "previous";
+  };
+
+}
diff --git a/config/home/zaphyra/services/shaderbg.nix b/config/home/zaphyra/services/shaderbg.nix
@@ -0,0 +1,20 @@
+{
+  inputs,
+  ...
+}:
+
+{
+
+  tgc.services.shaderbg = {
+    enable = true;
+    systemd = {
+      enable = true;
+      extraArgs = [
+        "--fps"
+        "10"
+      ];
+      shaderFile = inputs.self.resources.shaders.background1;
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/services/swayidle.nix b/config/home/zaphyra/services/swayidle.nix
@@ -0,0 +1,28 @@
+{
+  systemConfig,
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  services.swayidle = {
+    enable = true;
+    timeouts = [
+      {
+        timeout = 175;
+        command = "${lib.getExe systemConfig.programs.niri.package} msg action power-off-monitors";
+      }
+      {
+        timeout = 180;
+        command = "${lib.getExe' pkgs.systemd "loginctl"} lock-session";
+      }
+      {
+        timeout = 30 * 60;
+        command = "${lib.getExe' pkgs.systemd "systemctl"} spspend";
+      }
+    ];
+  };
+
+}
diff --git a/config/home/zaphyra/services/swaync.nix b/config/home/zaphyra/services/swaync.nix
@@ -0,0 +1,256 @@
+{
+  lib,
+  pkgs,
+  homeManagerModules,
+  ...
+}:
+
+{
+
+  imports = [
+    homeManagerModules.zaphyra.programs.wleave
+  ];
+
+  services.swaync = {
+    enable = true;
+    settings = {
+      "$schema" = "/etc/xdg/swaync/configSchema.json";
+
+      keyboard-shortcuts = true;
+
+      cssPriority = "user";
+      positionX = "center";
+      positionY = "top";
+      fit-to-screen = false;
+      control-center-layer = "top";
+      control-center-height = 900;
+      control-center-positionX = "none";
+      control-center-positionY = "none";
+
+      widgets = [
+        "buttons-grid#actions"
+        "buttons-grid#powerprofiles"
+        "backlight"
+        "volume"
+        "title"
+      ];
+
+      widget-config = {
+        volume.label = "";
+        backlight.label = "󰃟";
+        title = {
+          text = "Notification Center";
+          clear-all-button = true;
+          button-text = "󰆴 Clear";
+        };
+
+        "buttons-grid#powerprofiles".actions = [
+          {
+            type = "toggle";
+            label = "   Power Saver ";
+            update-command = "sh -c '[[ $(powerprofilesctl get) == \"power-saver\" ]] && echo true || echo false'";
+            command = "sh -c 'swaync-client -cp; powerprofilesctl set power-saver'";
+          }
+          {
+            type = "toggle";
+            label = "   Balanced ";
+            update-command = "sh -c '[[ $(powerprofilesctl get) == \"balanced\" ]] && echo true || echo false'";
+            command = "sh -c 'swaync-client -cp; powerprofilesctl set balanced'";
+          }
+          {
+            type = "toggle";
+            label = "  Performance ";
+            update-command = "sh -c '[[ $(powerprofilesctl get) == \"performance\" ]] && echo true || echo false'";
+            command = "sh -c 'swaync-client -cp; powerprofilesctl set performance'";
+          }
+        ];
+        "buttons-grid#actions".actions = [
+          {
+            type = "toggle";
+            label = " ☕ ";
+            command = "systemctl --user is-active --quiet swayidle.service && systemctl --user stop swayidle.service || systemctl --user start swayidle.service";
+            update-command = "systemctl --user is-active --quiet swayidle.service && echo false || echo true";
+          }
+          {
+            type = "toggle";
+            label = "󰂛";
+            command = "swaync-client -d";
+            tooltip = "Do not disturb";
+            update-command = "swaync-client --get-dnd";
+          }
+          {
+            type = "toggle";
+            active = true;
+            label = "󰥻 󰛨";
+            command = "sh -c '[[ $SWAYNC_TOGGLE_STATE == true ]] && ${lib.getExe pkgs.brightnessctl} --device='tpacpi::kbd_backlight' set 1 || ${lib.getExe pkgs.brightnessctl} --device='tpacpi::kbd_backlight' set 0'";
+            update-command = "sh -c '[[ $(${lib.getExe pkgs.brightnessctl} --device='tpacpi::kbd_backlight' get) == \"1\" ]] && echo true || echo false'";
+          }
+          {
+            type = "toggle";
+            active = true;
+            label = "直";
+            command = "sh -c '[[ $SWAYNC_TOGGLE_STATE == true ]] && nmcli radio wifi on || nmcli radio wifi off'";
+            update-command = "sh -c '[[ $(nmcli radio wifi) == \"enabled\" ]] && echo true || echo false'";
+          }
+          {
+            type = "toggle";
+            label = "";
+            # command = "swaync-client -cp; ${config.home.sessionVariables.TERMINAL} --confirm-close-surface=false -e ${lib.getExe pkgs.bluetui}";
+            command = "swaync-client -cp; ${lib.getExe pkgs.overskride}";
+            update-command = "sh -c 'bluetoothctl show | grep -q \\\"Powered: yes\\\" && echo true || echo false'";
+          }
+          {
+            label = "";
+            command = "swaync-client -cp; wleave";
+          }
+        ];
+      };
+    };
+    style = ''
+      @define-color border-color rgba(255, 255, 255, 0.08);
+
+      * {
+        font-family: "Adwaita Sans", "Symbols Nerd Font";
+      }
+
+      .control-center {
+        background-color: #222226;
+        border-radius: 0 0 10px 10px;
+        border: 2px solid @border-color;
+        border-top: 0;
+        box-shadow: 0 0 10px 0 rgba(0,0,0,.80);
+        padding: 4px;
+      }
+
+      .widget-title > button {
+        background: rgba(255, 255, 255, 0.06);
+        border: 1px solid @border-color;
+        border-radius: 4px;
+      }
+      .widget-title > button:hover {
+        background: rgba(255, 255, 255, 0.1);
+      }
+
+      .widget-backlight, .widget-volume, .widget-buttons-grid {
+        background: transparent;
+      }
+
+      .widget-backlight,
+      .widget-volume {
+        margin: 0px;
+        padding: 5px 10px;
+      }
+
+      /* Buttons */
+      .widget-buttons-grid {
+        padding: 0px;        
+      }
+
+      .widget-buttons-grid > flowbox > flowboxchild > button {
+        background: rgba(255, 255, 255, 0.06);
+        border: 1px solid @border-color;
+        border-radius: 4px;
+      }
+
+      .widget-buttons-grid > flowbox > flowboxchild > button:checked {
+        border-bottom: 2px solid rgb(74, 169, 108);
+      }
+
+      .widget-buttons-grid > flowbox > flowboxchild > button:hover {
+        background: rgba(255, 255, 255, 0.1);
+      }
+
+      /* Sliders */
+      scale {
+        padding: 2px;
+        margin: 0px 5px 0px 5px;
+      }
+
+      scale trough {
+        background: rgba(255, 255, 255, 0.06);
+      }
+
+      scale highlight {
+        background: rgb(74, 169, 108);
+        border-radius: 5px;
+      }
+
+
+      /* Notification */
+      .control-center .notification {
+        box-shadow: unset;
+        background: rgba(47, 47, 51, 0.95);
+        border: 1px solid @border-color;
+      }
+
+      .close-button {
+        border-radius: 0;
+        margin-top: 0;
+        margin-right: -2px;
+        background: unset;
+      }
+
+      .close-button:hover {
+        background: rgba(255, 255, 255, 0.1);
+        border-bottom-left-radius: 4px;
+        border-top-right-radius: 4px;
+      }
+
+      .notification-group-headers {
+        margin-bottom: 4px;
+      }
+
+      .notification-group-icon {
+        opacity: 0;
+      }
+
+      .notification-group .notification-group-header {
+        font-weight: 400;
+        font-size: 16pt;
+      }
+
+      .notification-group .notification-group-buttons {
+        margin: 4px;
+      }
+
+      .notification-group-collapse-button,
+      .notification-group-close-all-button {
+        border-radius: 4px;
+        background: rgba(47, 47, 51, 0.95);
+        border: 1px solid @border-color;
+        margin: 0 4px;
+      }
+
+      .notification-background {
+        padding: 5px 5px;
+      }
+
+      .notification {
+        background: rgba(0, 0, 0, 0.5);
+        border: 2px solid rgba(59, 135, 86, 0.5);
+        border-radius: 4px;
+      }
+
+      .notification .notification-default-action:hover,
+      .notification button:hover {
+        background: rgba(255, 255, 255, 0.06);
+        border-radius: 0;
+      }
+
+      .notification .text-box {
+        margin: 2px;
+      }
+
+      .notification .text-box .image {
+        border-radius: 10px;
+      }
+
+      .notification .text-box .time {
+        font-weight: 200;
+        font-size: 13px;
+        margin-right: 0;
+      }
+    '';
+  };
+
+}
diff --git a/config/home/zaphyra/services/swayosd.nix b/config/home/zaphyra/services/swayosd.nix
@@ -0,0 +1,63 @@
+{
+  config,
+  pkgs,
+  ...
+}:
+
+{
+
+  services.swayosd = {
+    enable = true;
+    topMargin = 0.05;
+    stylePath = pkgs.writeText "swayosd.css" ''
+      window#osd {
+        padding: 10px 15px;
+        border-radius: 10px;
+        border: 1px solid rgba(255, 255, 255, .08);
+        background: alpha(#303030, 0.8);
+      }
+      window#osd #container {
+          margin: 10px;
+      }
+      window#osd #container > image {
+        -gtk-icon-transform: scale(1.2);
+      }
+      window#osd image, window#osd label {
+        color: rgba(255, 255, 255, .20);
+      }
+      window#osd progressbar:disabled, window#osd image:disabled {
+          opacity: 0.5;
+      }
+      window#osd progressbar {
+        min-height: 6px;
+        border-radius: 999px;
+        background: transparent;
+        border: none;
+      }
+      window#osd trough {
+        min-height: inherit;
+        border-radius: inherit;
+        border: none;
+        background: rgba(255, 255, 255, .06);
+      }
+      window#osd progress {
+        min-height: inherit;
+        border-radius: inherit;
+        border: none;
+        background: rgb(74, 169, 108);
+      }
+    '';
+  };
+
+  programs.niri.settings.binds = with config.lib.niri.actions; {
+    "XF86AudioRaiseVolume".action =
+      spawn "swayosd-client" "--output-volume" "raise" "--max-volume"
+        "150";
+    "XF86AudioLowerVolume".action =
+      spawn "swayosd-client" "--output-volume" "lower" "--max-volume"
+        "150";
+
+    "XF86MonBrightnessUp".action = spawn "swayosd-client" "--brightness" "raise";
+    "XF86MonBrightnessDown".action = spawn "swayosd-client" "--brightness" "lower";
+  };
+}
diff --git a/config/home/zaphyra/services/syncthing.nix b/config/home/zaphyra/services/syncthing.nix
@@ -0,0 +1,14 @@
+_:
+
+{
+
+  services.syncthing = {
+    enable = true;
+
+    cert = "";
+    key = "";
+
+    settings = { };
+  };
+
+}
diff --git a/config/home/zaphyra/services/waybar.nix b/config/home/zaphyra/services/waybar.nix
@@ -1,89 +1,168 @@
-{ pkgs, ... }:
+{
+  config,
+  homeManagerModules,
+  pkgs,
+  lib,
+  ...
+}:
 
 {
 
-  wayland.windowManager.sway.config.startup = [
-    {
-      always = true;
-      command = "systemctl --user restart waybar";
-    }
+  imports = with homeManagerModules.zaphyra; [
+    programs.networkManagerDmenu
+    programs.nmgui
   ];
 
-  systemd.user.services.waybar.Service.Environment = "PATH=$PATH:${pkgs.iwd}/bin";
-
   programs.waybar = {
     enable = true;
     systemd.enable = true;
 
-    package = pkgs.waybar.override {
-      hyprlandSupport = false;
-    };
-
     settings = [
       {
         layer = "top";
         position = "top";
 
-        height = 40;
+        height = 26;
 
         modules-left = [
-          "sway/workspaces"
-          "sway/mode"
+          "niri/workspaces"
+          "custom/arrow1"
+        ];
+        modules-center = [
+          "clock"
+          "custom/notification"
         ];
-        modules-center = [ "clock" ];
         modules-right = [
           "tray"
-          "disk"
-          "memory"
-          "cpu"
-          "idle_inhibitor"
-          "network#wifi"
+          "custom/arrow2"
+          "network"
+          "wireplumber"
+          "custom/airpodsctl"
           "battery"
-          "pulseaudio"
+          "niri/language"
         ];
 
-        "sway/workspaces" = {
-          disable-scroll = true;
+        "niri/workspaces" = {
+          format = "{index}: {value}";
         };
 
-        "sway/mode" = {
-          tooltip = false;
-          format = "<span style=\"italic\">{}</span>";
+        "niri/language" = {
+          format = "{}";
+          format-en = "US";
+          format-de = "DE";
+          format-ru = "RU";
         };
 
         clock = {
-          interval = 1;
-          format = "{:%H:%M:%S}";
-          format-alt = "{:%Y-%m-%d}";
-          tooltip-format = "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
+          on-click = "swaync-client -t -sw";
+          on-click-right = lib.getExe pkgs.gnome-calendar;
+          format = "{:%d. %b %H:%M}";
+          tooltip-format = "{:%x %T}";
+        };
+
+        "custom/notification" = {
+          tooltip = false;
+          format = "{icon}";
+          format-icons = {
+            notification = "<small></small>";
+            dnd-notification = "";
+            dnd-none = "";
+            inhibited-notification = "";
+            dnd-inhibited-notification = "";
+            dnd-inhibited-none = "";
+          };
+          return-type = "json";
+          exec-if = "which swaync-client";
+          exec = "swaync-client -swb";
+          on-click = "swaync-client -t -sw";
+          on-click-right = "swaync-client -d -sw";
+          escape = true;
         };
 
         tray = {
           tooltip = false;
-          #             icon-size = 21;
           spacing = 10;
         };
 
-        disk = {
-          format = "  {}%";
-          tooltip-format = "SSD: {used} / {total} used";
-        };
+        "network" =
+          let
+            format = [
+              "<b>Interface:</b> {ifname}"
+              "<b>IP-Address:</b> {ipaddr}/{cidr}"
+              "<b>Gateway:</b> {gwaddr}"
+            ];
+
+          in
+          {
+            interval = 5;
+            # family = "ipv4_6";
+
+            # on-click = lib.getExe pkgs.networkmanager_dmenu;
+            on-click = lib.getExe pkgs.unstable.nmgui;
+
+            tooltip-format = lib.concatStringsSep "\n" format;
+            tooltip-format-wifi = lib.concatStringsSep "\n" (
+              format
+              ++ [
+                ""
+                "<b>Signal strength:</b> {signalStrength}% {signaldBm}dBm"
+                "<b>Frequency:</b> {frequency}Ghz"
+              ]
+            );
+
+            format-ethernet = "󰈀 ";
+            format-wifi = "󰖩  {essid} ({signalStrength}%)";
+            format-linked = "󰌹 ";
+            format-disconnected = "󰌙 ";
+          };
+
+        wireplumber = {
+          max-volume = 150;
+          scroll-step = 1;
+
+          on-click = lib.concatStringsSep " " [
+            config.home.sessionVariables.TERMINAL
+            "--confirm-close-surface=false"
+            "-e"
+            (lib.getExe pkgs.ncpamixer)
+          ];
 
-        memory = {
-          format = "  {}%";
-          tooltip-format = "RAM: {used:0.1f}G / {total:0.1f}G used";
+          format = "{icon} {volume}%";
+          format-muted = "󰝟";
+          format-icons = [
+            "󰕿"
+            "󰖀"
+            "󰖀"
+            "󰕾"
+            "󰕾"
+          ];
         };
 
-        cpu = {
-          format = "  {usage}%";
-          tooltip = false;
+        "custom/airpodsctl" = {
+          exec = "${lib.getExe pkgs.airpodsctl} --device=6C:12:70:1F:13:C6 --format=waybar --notify monitor";
+          return-type = "json";
+          format = "󰋋 {icon} {percentage}%";
+          format-icons = [
+            "󰂎"
+            "󰁺"
+            "󰁻"
+            "󰁼"
+            "󰁽"
+            "󰁾"
+            "󰁿"
+            "󰂀"
+            "󰂁"
+            "󰂂"
+            "󰁹"
+          ];
         };
 
         battery = {
-          bat = "BAT0";
-          adapter = "AC";
+          on-click = lib.getExe pkgs.gnome-power-manager;
+
           interval = 10;
           full-at = 99;
+
           states = {
             full = 100;
             good = 99;

@@ -91,128 +170,114 @@
             critical = 15;
           };
 
-          format = "{icon}  <span color='white'>{capacity}%</span>";
-          format-charging = "  <span color='white'>{capacity}%</span>";
-          format-plugged = "  <span color='white'>{capacity}%</span>";
-          format-empty = "";
-          format-full = "";
+          # Connected to AC
+          format = "󰚥 <span color='white'>{capacity}%</span>";
+          # Not connected to AC
+          format-discharging = "{icon} <span color='white'>{capacity}%</span>";
           format-icons = [
-            ""
-            ""
-            ""
-            ""
-            ""
+            "󱃍"
+            "󰂎"
+            "󰁺"
+            "󰁻"
+            "󰁼"
+            "󰁽"
+            "󰁾"
+            "󰁿"
+            "󰂀"
+            "󰂁"
+            "󰂂"
+            "󰁹"
           ];
+          tooltip-format = "{power} W, {timeTo}";
         };
 
-        "network#wifi" = {
-          interface = "wlan0*";
-          tooltip-format = "{ifname}: {ipaddr}/{cidr}";
-
-          on-click = "${pkgs.rofi-wayland}/bin/rofi -show wifi -modi 'wifi:${pkgs.rofi-iwd-wifi-menu}/bin/iwdrofimenu'";
-
-          format-ethernet = "";
-          format-wifi = "  {essid} ({signalStrength}%)";
-          format-linked = "";
-          format-disconnected = "";
-        };
-
-        pulseaudio = {
-          scroll-step = 1;
-          on-click = "${pkgs.pavucontrol}/bin/pavucontrol";
-
-          format = "{format_source} {icon}  {volume}%";
-          format-bluetooth = "{format_source} {icon} {volume}%";
-          format-bluetooth-muted = "{format_source}  ";
-          format-muted = "{format_source} ";
-          format-source = "";
-          format-source-muted = "";
-          format-icons = {
-            headphone = "";
-            phone = "";
-            portable = "";
-            car = "";
-            default = [
-              ""
-              ""
-              ""
-            ];
-          };
+        "custom/arrow1" = {
+          format = "";
+          tooltip = false;
         };
 
-        idle_inhibitor = {
-          format = "{icon}";
-          format-icons = {
-            activated = "";
-            deactivated = "";
-          };
+        "custom/arrow2" = {
+          format = "";
+          tooltip = false;
         };
       }
     ];
 
     style = ''
       @keyframes blink {
-          to {
-              background: transparent;
-              color: #fff;
-          }
+        to {
+          background: transparent;
+          color: #fff;
+        }
       }
 
       * {
-          font-family: 'Noto Sans';
-          font-size: 15px;
-          border: none;
-          border-radius: 0;
-          min-height: 0;
-          transition: none;
-          box-shadow: none;
+        font-family: "Adwaita Sans", "Symbols Nerd Font";
+        font-size: 14px;
+        border: none;
+        border-radius: 0;
+        min-height: 0;
+        transition: none;
+        box-shadow: none;
       }
 
       window#waybar {
-          /* background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); */
-          background: rgba(0, 0, 0, 0.5);
-          color: white;
-          border-bottom: 2px solid rgba(59, 135, 86, 0.5);
+        color: white;
+        background: rgba(0, 0, 0, 0.5);
+        border-bottom: 2px solid rgba(59, 135, 86, 0.5);
       }
 
+      #workspaces {
+        background: rgba(255, 255, 255, 0.06);
+      }
       #workspaces button.focused {
-          background: rgba(255, 255, 255, 0.1);
-          border-bottom: 3px solid rgb(74, 169, 108);
+        background: rgba(255, 255, 255, 0.1);
+        border-bottom: 2px solid rgb(74, 169, 108);
       }
-
       #workspaces button:hover {
-          background: rgba(255, 255, 255, 0.06);
+        background: rgba(255, 255, 255, 0.06);
       }
 
       #clock {
-          font-size: 16px;
-          font-family: 'Noto Mono', monospace;
+        font-size: 14px;
+        font-family: 'Noto Mono', monospace;
+        padding: 0px 5px;
       }
 
-      #disk, #memory, #cpu, #idle_inhibitor, #battery, #pulseaudio, #network {
-          padding: 0px 15px;
+      #tray {
+        padding: 0px 15px;
+      }
+
+      #network, #wireplumber, #custom-airpodsctl, #battery, #language {
+        background: rgba(255, 255, 255, 0.06);
+        padding: 0px 15px;
       }
 
       #battery {
-          color: #a3be8c;
+        color: #a3be8c;
       }
 
       #battery.charging {
-          color: #a3be8c;
+        color: #a3be8c;
       }
 
       #battery.critical:not(.charging) {
-          background: rgba(245, 60, 60, 0.4);
-          color: #fff;
+        background: rgba(245, 60, 60, 0.4);
+        color: #fff;
 
-          border-radius: 15px;
-          margin: 6px;
+        border-radius: 15px;
+        margin: 6px;
+
+        animation-name: blink;
+        animation-duration: 1s;
+        animation-timing-function: linear;
+        animation-iteration-count: infinite;
+        animation-direction: alternate;
+      }
 
-          animation-name: blink;
-          animation-duration: 1s;
-          animation-timing-function: linear;
-          animation-iteration-count: infinite;
-          animation-direction: alternate;
+      #custom-arrow1, #custom-arrow2 {
+        font-size: 20pt;
+        color: rgba(255, 255, 255, 0.06);
       }
     '';
   };
diff --git a/config/home/zaphyra/services/wlsunset.nix b/config/home/zaphyra/services/wlsunset.nix
@@ -1,4 +1,4 @@
-{ ... }:
+_:
 
 {
 
diff --git a/config/home/zaphyra/services/wob.nix b/config/home/zaphyra/services/wob.nix
@@ -0,0 +1,39 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  services.wob = {
+    enable = true;
+    settings."" = {
+      anchor = "top center";
+      background_color = "00000080";
+      border_color = "4aa96ce6";
+      bar_color = "ffffffa6";
+    };
+  };
+
+  programs.niri.settings.binds = with config.lib.niri.actions; {
+    "XF86AudioMute".action =
+      spawn (lib.getExe pkgs.bash) "-c"
+        "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle && (wpctl get-volume @DEFAULT_AUDIO_SINK@ | ${lib.getExe pkgs.gnugrep} -q MUTED && echo 0 > $XDG_RUNTIME_DIR/wob.sock) || wpctl get-volume @DEFAULT_AUDIO_SINK@ | ${lib.getExe pkgs.gnused} 's/[^0-9]//g' > $XDG_RUNTIME_DIR/wob.sock)";
+    "XF86AudioRaiseVolume".action =
+      spawn (lib.getExe pkgs.bash) "-c"
+        "(wpctl get-volume @DEFAULT_AUDIO_SINK@ | ${lib.getExe pkgs.gnugrep} -q MUTED && echo 0 > $XDG_RUNTIME_DIR/wob.sock) || (wpctl set-volume @DEFAULT_AUDIO_SINK@ 2%+ && wpctl get-volume @DEFAULT_AUDIO_SINK@ | ${lib.getExe pkgs.gnused} 's/[^0-9]//g' > $XDG_RUNTIME_DIR/wob.sock)";
+    "XF86AudioLowerVolume".action =
+      spawn (lib.getExe pkgs.bash) "-c"
+        "(wpctl get-volume @DEFAULT_AUDIO_SINK@ | ${lib.getExe pkgs.gnugrep} -q MUTED && echo 0 > $XDG_RUNTIME_DIR/wob.sock) || (wpctl set-volume @DEFAULT_AUDIO_SINK@ 2%- && wpctl get-volume @DEFAULT_AUDIO_SINK@ | ${lib.getExe pkgs.gnused} 's/[^0-9]//g' > $XDG_RUNTIME_DIR/wob.sock)";
+
+    "XF86MonBrightnessUp".action =
+      spawn (lib.getExe pkgs.bash) "-c"
+        "${lib.getExe pkgs.brightnessctl} set +2% | ${lib.getExe pkgs.gnused} -En 's/.*\\(([0-9]+)%\\).*/\\1/p' > $XDG_RUNTIME_DIR/wob.sock";
+    "XF86MonBrightnessDown".action =
+      spawn (lib.getExe pkgs.bash) "-c"
+        "${lib.getExe pkgs.brightnessctl} set 2%- | ${lib.getExe pkgs.gnused} -En 's/.*\\(([0-9]+)%\\).*/\\1/p' > $XDG_RUNTIME_DIR/wob.sock";
+  };
+
+}
diff --git a/config/home/zaphyra/services/wpaperd.nix b/config/home/zaphyra/services/wpaperd.nix
@@ -0,0 +1,49 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+
+{
+
+  home.persistence."/nix/persist/home/${config.home.username}".directories = [
+    "wpaperd/.local/state/wpaperd"
+  ];
+
+  services.wpaperd = {
+    enable = true;
+    settings = {
+      default = {
+        duration = "30m";
+        mode = "center";
+        sorting = "ascending";
+        transition.bounce = { };
+      };
+
+      any.path = pkgs.buildEnv {
+        name = "nixos-artwork";
+        paths = lib.pipe pkgs.nixos-artwork.wallpapers [
+          lib.attrNames
+          (lib.remove "override")
+          (lib.remove "overrideDerivation")
+          # removed because too bright
+          (lib.remove "binary-white")
+          (lib.remove "catppuccin-latte")
+          (lib.remove "moonscape")
+          (lib.remove "nineish-catppuccin-latte")
+          (lib.remove "nineish-catppuccin-latte-alt")
+          (lib.remove "nineish-solarized-light")
+          (lib.remove "nineish")
+          (lib.remove "simple-light-gray")
+          (map (name: "${pkgs.nixos-artwork.wallpapers.${name}}/share/backgrounds/nixos"))
+        ];
+      };
+    };
+  };
+
+  programs.niri.settings.binds = with config.lib.niri.actions; {
+    "Mod+Home".action = spawn (lib.getExe' pkgs.wpaperd "wpaperctl") "next";
+  };
+
+}
diff --git a/config/nixos/dns.nix b/config/nixos/dns.nix
@@ -35,26 +35,24 @@ in
     zoneFiles = {
       type = types.attrsOf types.path;
       readOnly = true;
-      default = (
-        cfg.allZones
-        |> lib.mapAttrs (
-          name: zone:
-          toString (
-            pkgs.writeTextFile {
-              name = "${name}.zone";
-              text = dnsNix.types.zoneToString name (dnsNix.evalZone name zone);
-            }
-          )
+      default = lib.mapAttrs (
+        name: zone:
+        toString (
+          pkgs.writeTextFile {
+            name = "${name}.zone";
+            text = dnsNix.types.zoneToString name (dnsNix.evalZone name zone);
+          }
         )
-      );
+      ) cfg.allZones;
     };
   };
 
   config = lib.mkIf cfg.enable {
     # serve records defined in all host configs
     dns.allZones = lib.mkMerge (
-      inputs.self.nixosConfigurations
-      |> lib.mapAttrsToList (hostName: hostConfig: hostConfig.config.dns.zones)
+      lib.mapAttrsToList (
+        _hostName: hostConfig: hostConfig.config.dns.zones
+      ) inputs.self.nixosConfigurations
     );
   };
 
diff --git a/config/nixos/modules/boot/plymouth.nix b/config/nixos/modules/boot/plymouth.nix
@@ -32,7 +32,7 @@ in
       ];
       plymouth = {
         enable = true;
-        inherit (cfg) theme;
+        #inherit (cfg) theme;
       };
     };
   };
diff --git a/config/nixos/modules/filesystem/impermanence.nix b/config/nixos/modules/filesystem/impermanence.nix
@@ -1,16 +1,13 @@
 {
-  pov,
   povSelf,
   hostConfig,
   config,
   lib,
-  pkgs,
   ...
 }:
 
 let
   inherit (lib) types;
-  cfgFilesystem = lib.getAttrFromPath pov config;
   cfg = lib.getAttrFromPath povSelf config;
   perms = {
     user = lib.mkOption {

@@ -49,7 +46,8 @@ in
             (submodule {
               options = {
                 directory = lib.mkOption { type = types.str; };
-              } // perms;
+              }
+              // perms;
             })
           ]);
       };

@@ -66,7 +64,8 @@ in
                   type = with types; nullOr (submodule perms);
                   default = null;
                 };
-              } // perms;
+              }
+              // perms;
             })
           ]);
       };

@@ -78,9 +77,12 @@ in
     (lib.mkIf cfg.home.enable {
       assertions = [
         {
-          assertion = config.modules.filesystem.rootDisk.type == "zfs";
+          assertion = builtins.elem config.modules.filesystem.rootDisk.type [
+            "btrfs"
+            "zfs"
+          ];
           message = ''
-            Impermanence is currently only available for ZFS.
+            Impermanence is currently only available for BTRFS and ZFS.
           '';
         }
       ];

@@ -91,17 +93,54 @@ in
     (lib.mkIf cfg.system.enable {
       assertions = [
         {
-          assertion = config.modules.filesystem.rootDisk.type == "zfs";
+          assertion = builtins.elem config.modules.filesystem.rootDisk.type [
+            "btrfs"
+            "zfs"
+          ];
           message = ''
-            Impermanence is currently only available for ZFS.
+            Impermanence is currently only available for BTRFS and ZFS.
           '';
         }
       ];
 
       modules.filesystem.rootDisk.parts.system = true;
-      boot.initrd.systemd.services = {
-        defenestrate = {
-          description = "Defenestrate old root";
+
+      boot.initrd.systemd.services.defenestrate = lib.mkMerge [
+        (lib.mkIf (config.modules.filesystem.rootDisk.type == "btrfs") {
+          description = "Defenestrate old btrfs-root";
+          wantedBy = [ "initrd.target" ];
+          after = [ "cryptsetup.target" ];
+          before = [ "sysroot.mount" ];
+          onFailure = [ "emergency.target" ];
+          unitConfig.DefaultDependencies = "no";
+          serviceConfig.Type = "oneshot";
+          script = ''
+            mkdir /btrfs_tmp
+            mount /dev/mapper/root /btrfs_tmp
+            if [[ -e /btrfs_tmp/root ]]; then
+                mkdir -p /btrfs_tmp/old_roots
+                timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
+                mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
+            fi
+
+            delete_subvolume_recursively() {
+                IFS=$'\n'
+                for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
+                    delete_subvolume_recursively "/btrfs_tmp/$i"
+                done
+                btrfs subvolume delete "$1"
+            }
+
+            for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do
+                delete_subvolume_recursively "$i"
+            done
+
+            btrfs subvolume create /btrfs_tmp/root
+            umount /btrfs_tmp
+          '';
+        })
+        (lib.mkIf (config.modules.filesystem.rootDisk.type == "zfs") {
+          description = "Defenestrate old zfs-root";
           wantedBy = [ "initrd.target" ];
           after = [ "zfs-import.target" ];
           before = [ "sysroot.mount" ];

@@ -122,8 +161,8 @@ in
               zfs rename ${prefix}1 ${prefix}2 || true
               zfs create -o devices=off -o exec=off -o mountpoint=legacy -o setuid=off ${prefix}1
             '';
-        };
-      };
+        })
+      ];
 
       environment.persistence."/nix/persist/system" = {
         enable = true;

@@ -133,10 +172,12 @@ in
           "/var/log"
           "/var/lib/nixos"
           "/var/lib/systemd/coredump"
-        ] ++ cfg.system.dirs;
+        ]
+        ++ cfg.system.dirs;
         files = [
           "/etc/machine-id"
-        ] ++ cfg.system.files;
+        ]
+        ++ cfg.system.files;
       };
 
       #zaphyra: hack to persist `/var/lib/private/<service>` (see https://github.com/nix-community/impermanence/issues/213)
diff --git a/config/nixos/modules/filesystem/root.nix.bak b/config/nixos/modules/filesystem/root.nix.bak
@@ -0,0 +1,138 @@
+{
+  povSelf,
+  hostConfig,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+  users = lib.pipe config.modules.users [
+    (lib.mapAttrsToList (name: value: if value.enable then name else null))
+    (lib.filter (element: !builtins.isNull element))
+  ];
+  part =
+    name: content:
+    if cfg.encrypt then
+      {
+        type = "luks";
+        settings.allowDiscards = true;
+        inherit name content;
+      }
+    else
+      content;
+in
+{
+
+  options = {
+    enable = {
+      type = types.bool;
+      default = false;
+    };
+    disks = {
+      type = types.listOf types.path;
+    };
+    type = {
+      type = types.enum [
+        "lvm"
+        "zfs"
+      ];
+    };
+    encrypt = {
+      type = types.bool;
+      default = false;
+    };
+    parts = {
+      home = {
+        type = types.bool;
+        default = false;
+      };
+      homePerUser = {
+        type = types.bool;
+        default = cfg.parts.home;
+      };
+      nix = {
+        type = types.bool;
+        default = true;
+      };
+      tmp = {
+        type = types.bool;
+        default = false;
+      };
+      system = {
+        type = types.bool;
+        default = false;
+      };
+    };
+    reservedSpace = {
+      type = types.nullOr types.str;
+      default = "8G";
+    };
+    swap = {
+      enable = {
+        type = types.bool;
+        default = false;
+      };
+      size = {
+        type = types.strMatching "[0-9]+[KMGTP]";
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    disko.devices = {
+      disk = listToAttrs (imap0 (i: device: { name = "${hostConfig.hostName}-dsk${toString i}"; value = {
+        inherit device;
+        content = {
+          type = "gpt";
+          partitions = {
+            boot = {
+              size = "512M";
+              type = "EF00";
+              content = {
+                type = "filesystem";
+                format = "vfat";
+                # FIXME: Multidisk?
+                mountpoint = "/boot";
+                mountOptions = [
+                  "umask=0077"
+                  "dmask=0077"
+                  "nofail"
+                ];
+              };
+            };
+            cryptroot = {
+              size = "100%";
+              content = {
+                type = "luks";
+                settings = {
+                  allowDiscards = true; # FIXME: If disk is an SSD??
+                };
+                content = {
+                  type = "lvm_pv"; # FIXME: Or ZFS?
+                  vg = hostConfig.hostName;
+                };
+              };
+            };
+          };
+        };
+      }) cfg.disks);
+      lvm_vg = {
+        ${hostConfig.hostName} = {
+          lvs = {
+            swap = {
+              size = cfg.swap.size;
+              content.type = "swap";
+            };
+            root = {};
+            nix = {};
+            persist = {};
+            home = {};
+          };
+        };
+      };
+  };
+}
diff --git a/config/nixos/modules/filesystem/rootDisk.nix b/config/nixos/modules/filesystem/rootDisk.nix
@@ -3,23 +3,22 @@
   hostConfig,
   config,
   lib,
-  pkgs,
   ...
 }:
 
 let
   inherit (lib) types;
   cfg = lib.getAttrFromPath povSelf config;
-  users = (
-    config.modules.users
-    |> lib.mapAttrsToList (name: value: if value.enable then name else null)
-    |> lib.filter (element: !builtins.isNull element)
-  );
+  users = lib.pipe config.modules.users [
+    (lib.mapAttrsToList (name: value: if value.enable then name else null))
+    (lib.filter (element: !builtins.isNull element))
+  ];
   part =
     name: content:
     if cfg.encrypt then
       {
         type = "luks";
+        settings.allowDiscards = true;
         inherit name content;
       }
     else

@@ -34,8 +33,9 @@ in
     };
     type = {
       type = types.enum [
-        "zfs"
         "ext4"
+        "btrfs"
+        "zfs"
       ];
     };
     path = {

@@ -84,6 +84,9 @@ in
 
   config = lib.mkIf cfg.enable (
     lib.mkMerge [
+      (lib.mkIf (cfg.type == "btrfs") {
+        services.btrfs.autoScrub.enable = true;
+      })
       (lib.mkIf (cfg.type == "zfs") {
         assertions = [
           {

@@ -313,21 +316,74 @@ in
                   })
 
                   {
-                    root.content = (
-                      lib.mkMerge [
-                        (lib.mkIf (cfg.type == "ext4") (
-                          part "root" {
-                            type = "filesystem";
-                            format = "ext4";
-                            mountpoint = "/";
-                          }
-                        ))
-                        (lib.mkIf (cfg.type == "zfs") {
-                          type = "zfs";
-                          pool = hostConfig.hostName;
-                        })
-                      ]
-                    );
+                    root.content = lib.mkMerge [
+                      (lib.mkIf (cfg.type == "ext4") (
+                        part "root" {
+                          type = "filesystem";
+                          format = "ext4";
+                          mountpoint = "/";
+                        }
+                      ))
+                      (lib.mkIf (cfg.type == "btrfs") (
+                        part "root" {
+                          type = "btrfs";
+                          subvolumes = lib.mkMerge [
+                            {
+                              "/${hostConfig.hostName}/root" = {
+                                mountpoint = "/";
+                              };
+                            }
+                            (lib.mkIf cfg.parts.nix {
+                              "/${hostConfig.hostName}/nix" = {
+                                mountOptions = [
+                                  "compress=zstd"
+                                  "noatime"
+                                ];
+                                mountpoint = "/nix";
+                              };
+                            })
+                            (lib.mkIf cfg.parts.system {
+                              "/${hostConfig.hostName}/persist" = {
+                                mountOptions = [
+                                  "compress=zstd"
+                                  "noatime"
+                                ];
+                                mountpoint = "/nix/persist";
+                              };
+                            })
+                            (lib.mkIf (cfg.parts.home && !cfg.parts.homePerUser) {
+                              "/${hostConfig.hostName}/home" = {
+                                mountOptions = [ "compress=zstd" ];
+                                mountpoint = "/home";
+                              };
+                            })
+                            (lib.mkIf cfg.parts.homePerUser (
+                              lib.listToAttrs (
+                                lib.map (user: {
+                                  name =
+                                    if config.modules.filesystem.impermanence.home.enable then
+                                      "/${hostConfig.hostName}/persist/home/${user}"
+                                    else
+                                      "/${hostConfig.hostName}/home/${user}";
+                                  value = {
+                                    mountOptions = [ "compress=zstd" ];
+                                    mountpoint =
+                                      if config.modules.filesystem.impermanence.home.enable then
+                                        "/nix/persist/home/${user}"
+                                      else
+                                        "/home/${user}";
+                                  };
+                                }) users
+                              )
+                            ))
+                          ];
+                        }
+                      ))
+                      (lib.mkIf (cfg.type == "zfs") {
+                        type = "zfs";
+                        pool = hostConfig.hostName;
+                      })
+                    ];
                   }
                   (
                     if cfg.swap.enable then
diff --git a/config/nixos/modules/font.nix b/config/nixos/modules/font.nix
@@ -2,7 +2,6 @@
   povSelf,
   config,
   lib,
-  pkgs,
   ...
 }:
 

@@ -24,16 +23,6 @@ in
       fontDir.enable = true;
       enableGhostscriptFonts = true;
       enableDefaultPackages = true;
-      packages = with pkgs; [
-        dejavu_fonts
-        liberation_ttf
-        ttf_bitstream_vera
-        noto-fonts
-        noto-fonts-emoji
-        fira-code
-        fira-mono
-        meslo-lgs-nf
-      ];
     };
   };
 
diff --git a/config/nixos/modules/gnomeMinimal.nix b/config/nixos/modules/gnomeMinimal.nix
@@ -28,7 +28,7 @@ in
         default = { };
       };
       settings = {
-        type = settingsFormat.type;
+        inherit (settingsFormat) type;
         default = { };
       };
     };

@@ -38,7 +38,7 @@ in
     let
       configFile = settingsFormat.generate "custom.conf" cfg.gdm.settings;
 
-      nixos-background-info = pkgs.writeTextFile rec {
+      nixos-background-info = pkgs.writeTextFile {
         name = "nixos-background-info";
         destination = "/share/gnome-background-properties/nixos.xml";
         text = ''

@@ -135,9 +135,9 @@ in
 
               # Change hardcoded paths to nix store paths.
               (prev.replaceVars inputs.self.resources.patches.gdm-fix-paths {
-                coreutils = final.coreutils;
-                plymouth = final.plymouth;
-                dbus = final.dbus;
+                inherit (final) coreutils;
+                inherit (final) plymouth;
+                inherit (final) dbus;
               })
             ];
             postPatch = ''

@@ -217,13 +217,15 @@ in
       };
 
       services = {
-        gnome.gnome-settings-daemon.enable = true;
-        gnome.glib-networking.enable = true;
         udisks2.enable = true;
         libinput.enable = true;
         accounts-daemon.enable = true;
-        gnome.at-spi2-core.enable = lib.mkDefault true;
-        gnome.gnome-keyring.enable = lib.mkDefault true;
+        gnome = {
+          gnome-settings-daemon.enable = true;
+          glib-networking.enable = true;
+          at-spi2-core.enable = lib.mkDefault true;
+          gnome-keyring.enable = lib.mkDefault true;
+        };
         pipewire.enable = lib.mkDefault true;
         hardware.bolt.enable = lib.mkDefault true;
         colord.enable = lib.mkDefault true;

@@ -248,14 +250,14 @@ in
         udev.packages = [ pkgs.mutter ];
         dbus.packages = [ pkgs.gdm ];
 
-        geoclue2.enable = lib.mkDefault true;
-        geoclue2.enableDemoAgent = false; # GNOME has its own geoclue agent
-        geoclue2.appConfig =
-          lib.genAttrs [ "gnome-datetime-panel" "gnome-color-panel" "org.gnome.Shell" ]
-            (name: {
-              isAllowed = true;
-              isSystem = true;
-            });
+        geoclue2 = {
+          enable = lib.mkDefault true;
+          enableDemoAgent = false; # GNOME has its own geoclue agent
+          appConfig = lib.genAttrs [ "gnome-datetime-panel" "gnome-color-panel" "org.gnome.Shell" ] (_name: {
+            isAllowed = true;
+            isSystem = true;
+          });
+        };
       };
 
       programs = {

@@ -270,12 +272,14 @@ in
         mime.enable = true;
         icons.enable = true;
 
-        portal.enable = true;
-        portal.configPackages = lib.mkDefault [ pkgs.gnome-session ];
-        portal.extraPortals = with pkgs; [
-          xdg-desktop-portal-gnome
-          xdg-desktop-portal-gtk
-        ];
+        portal = {
+          enable = true;
+          configPackages = lib.mkDefault [ pkgs.gnome-session ];
+          extraPortals = with pkgs; [
+            xdg-desktop-portal-gnome
+            xdg-desktop-portal-gtk
+          ];
+        };
       };
 
       systemd = {

@@ -292,73 +296,75 @@ in
         # We dont use the upstream gdm service
         # it has to be disabled since the gdm package has it
         # https://github.com/NixOS/nixpkgs/issues/108672
-        services.gdm.enable = false;
+        services = {
+          gdm.enable = false;
 
-        services.display-manager = {
-          description = "Display Manager";
+          display-manager = {
+            description = "Display Manager";
 
-          wants = [
-            "systemd-machined.service"
-            "accounts-daemon.service"
-          ];
-          conflicts = [
-            "getty@${pkgs.gdm.initialVT}.service"
-            "plymouth-quit.service"
-          ];
-          onFailure = [ "plymouth-quit.service" ];
-          wantedBy = [ "multi-user.target" ];
-          after = [
-            "systemd-logind.service"
-            "systemd-user-sessions.service"
-            "systemd-machined.service"
-            "getty@${pkgs.gdm.initialVT}.service"
-            "acpid.service"
-            "plymouth-quit.service"
-            "plymouth-start.service"
-          ];
+            wants = [
+              "systemd-machined.service"
+              "accounts-daemon.service"
+            ];
+            conflicts = [
+              "getty@${pkgs.gdm.initialVT}.service"
+              "plymouth-quit.service"
+            ];
+            onFailure = [ "plymouth-quit.service" ];
+            wantedBy = [ "multi-user.target" ];
+            after = [
+              "systemd-logind.service"
+              "systemd-user-sessions.service"
+              "systemd-machined.service"
+              "getty@${pkgs.gdm.initialVT}.service"
+              "acpid.service"
+              "plymouth-quit.service"
+              "plymouth-start.service"
+            ];
 
-          path = [ pkgs.gnome-session ];
-          environment = {
-            XDG_DATA_DIRS = lib.makeSearchPath "share" (
-              with pkgs;
-              [
-                gdm
-                gnome-session.sessions
-                gnome-control-center # for accessibility icon
-                adwaita-icon-theme
-                hicolor-icon-theme
-              ]
-            );
-          };
+            path = [ pkgs.gnome-session ];
+            environment = {
+              XDG_DATA_DIRS = lib.makeSearchPath "share" (
+                with pkgs;
+                [
+                  gdm
+                  gnome-session.sessions
+                  gnome-control-center # for accessibility icon
+                  adwaita-icon-theme
+                  hicolor-icon-theme
+                ]
+              );
+            };
 
-          serviceConfig = {
-            KillMode = "mixed";
-            IgnoreSIGPIPE = "no";
-            BusName = "org.gnome.DisplayManager";
-            StandardError = "inherit";
-            ExecStart = "${pkgs.gdm}/bin/gdm";
-            ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
-            KeyringMode = "shared";
-            EnvironmentFile = "-/etc/locale.conf";
-            Restart = "always";
-            RestartSec = "200ms";
-            SyslogIdentifier = "display-manager";
-          };
+            serviceConfig = {
+              KillMode = "mixed";
+              IgnoreSIGPIPE = "no";
+              BusName = "org.gnome.DisplayManager";
+              StandardError = "inherit";
+              ExecStart = "${pkgs.gdm}/bin/gdm";
+              ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
+              KeyringMode = "shared";
+              EnvironmentFile = "-/etc/locale.conf";
+              Restart = "always";
+              RestartSec = "200ms";
+              SyslogIdentifier = "display-manager";
+            };
 
-          restartIfChanged = false;
+            restartIfChanged = false;
 
-          # Stop restarting if the display manager stops (crashes) 2 times in one minute.
-          startLimitIntervalSec = 30;
-          startLimitBurst = 3;
-        };
+            # Stop restarting if the display manager stops (crashes) 2 times in one minute.
+            startLimitIntervalSec = 30;
+            startLimitBurst = 3;
+          };
 
-        # Prevent nixos-rebuild switch from bringing down the graphical
-        # session. (If multi-user.target wants plymouth-quit.service which
-        # conflicts display-manager.service, then when nixos-rebuild
-        # switch starts multi-user.target, display-manager.service is
-        # stopped so plymouth-quit.service can be started.)
-        services.plymouth-quit = lib.mkIf config.boot.plymouth.enable {
-          wantedBy = lib.mkForce [ ];
+          # Prevent nixos-rebuild switch from bringing down the graphical
+          # session. (If multi-user.target wants plymouth-quit.service which
+          # conflicts display-manager.service, then when nixos-rebuild
+          # switch starts multi-user.target, display-manager.service is
+          # stopped so plymouth-quit.service can be started.)
+          plymouth-quit = lib.mkIf config.boot.plymouth.enable {
+            wantedBy = lib.mkForce [ ];
+          };
         };
       };
 
diff --git a/config/nixos/modules/hardware/bluetooth.nix b/config/nixos/modules/hardware/bluetooth.nix
@@ -0,0 +1,31 @@
+{
+  config,
+  lib,
+  povSelf,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    modules.filesystem.impermanence.system.dirs = [
+      "/var/lib/bluetooth"
+    ];
+
+    hardware.bluetooth = {
+      enable = true;
+      powerOnBoot = lib.mkDefault false;
+      settings.General.Experimental = lib.mkDefault true;
+    };
+  };
+
+}
diff --git a/config/nixos/modules/hardware/fprint.nix b/config/nixos/modules/hardware/fprint.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  hostConfig,
   config,
   lib,
   pkgs,

@@ -23,6 +22,10 @@ in
       type = types.bool;
       default = false;
     };
+    disableOnLidClose = {
+      type = types.bool;
+      default = false;
+    };
   };
 
   config = lib.mkIf cfg.enable (

@@ -52,6 +55,12 @@ in
           driver = lib.mkDefault pkgs.libfprint-2-tod1-goodix;
         };
       })
+      (lib.mkIf cfg.disableOnLidClose {
+        services.fprintd.lid = {
+          authSkipLidClose = true;
+          path = "/proc/acpi/button/lid/LID/state";
+        };
+      })
     ]
   );
 
diff --git a/config/nixos/modules/hardware/quirks.nix b/config/nixos/modules/hardware/quirks.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  hostConfig,
   config,
   lib,
   ...
diff --git a/config/nixos/modules/hardware/smartcard.nix b/config/nixos/modules/hardware/smartcard.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  hostConfig,
   config,
   lib,
   pkgs,
diff --git a/config/nixos/modules/hardware/thunderbolt.nix b/config/nixos/modules/hardware/thunderbolt.nix
@@ -0,0 +1,24 @@
+{
+  config,
+  lib,
+  povSelf,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    boot.initrd.availableKernelModules = [ "thunderbolt" ];
+    services.hardware.bolt.enable = true;
+  };
+
+}
diff --git a/config/nixos/modules/hardware/video/enable.nix b/config/nixos/modules/hardware/video/enable.nix
@@ -1,23 +0,0 @@
-{
-  pov,
-  config,
-  lib,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath pov config;
-
-in
-{
-
-  option = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf cfg.enable {
-    hardware.graphics.enable = true;
-  };
-
-}
diff --git a/config/nixos/modules/hardware/video/intel.nix b/config/nixos/modules/hardware/video/intel.nix
@@ -1,5 +1,5 @@
 {
-  pov,
+  povSelf,
   config,
   lib,
   pkgs,

@@ -7,28 +7,30 @@
 }:
 let
   inherit (lib) types;
-  cfg = lib.getAttrFromPath pov config;
+  cfg = lib.getAttrFromPath povSelf config;
 
 in
 {
 
-  options = {
-    enable = {
-      type = types.bool;
-      default = false;
-    };
+  options.enable = {
+    type = types.bool;
+    default = false;
   };
 
-  config = lib.mkIf (cfg.enable && cfg.intel.enable) {
-    boot.initrd.kernelModules = [ "i915" ];
+  config = lib.mkIf cfg.enable {
+    hardware.intelgpu.driver = "xe";
+
+    services.xserver.videoDrivers = [ "intel" ];
+
+    environment.systemPackages = [ pkgs.vulkan-validation-layers ];
 
-    hardware.opengl = {
+    hardware.graphics = {
       enable = true;
+      enable32Bit = true;
       extraPackages = with pkgs; [
-        vaapiIntel
-        vaapiVdpau
         libvdpau-va-gl
-        intel-media-driver
+        vpl-gpu-rt
+        libva
       ];
     };
   };
diff --git a/config/nixos/modules/hardware/video/nvidia.nix b/config/nixos/modules/hardware/video/nvidia.nix
@@ -1,13 +1,13 @@
 {
-  pov,
+  povSelf,
   config,
   lib,
   ...
 }:
 let
   inherit (lib) types;
-  cfg = lib.getAttrFromPath pov config;
-  cfgRoot = lib.getAttrFromPath (lib.remove [ "hardware" "video" ] pov) config;
+  cfg = lib.getAttrFromPath povSelf config;
+  cfgRoot = lib.getAttrFromPath (lib.remove [ "hardware" "video" "nvidia" ] povSelf) config;
 
 in
 {

@@ -64,12 +64,12 @@ in
     };
   };
 
-  config = lib.mkIf (cfg.enable && cfg.nvidia.enable) (
+  config = lib.mkIf cfg.enable (
     lib.mkMerge [
       {
         assertions = [
           {
-            assertion = !cfg.nvidia.open -> cfgRoot.modules.unfree.enable;
+            assertion = !cfg.open -> cfgRoot.modules.unfree.enable;
             message = ''
               The programs.nvidia module uses unfree software if open is set to false.
               To use it you need to

@@ -105,6 +105,7 @@ in
         ];
 
         hardware = {
+          graphics.enable = true;
           # NVIDIA
           nvidia = {
             inherit (cfg.nvidia) open;

@@ -119,15 +120,15 @@ in
             # PowerManagement
             powerManagement.enable = cfg.powerManagement == "on" || cfg.powerManagement == "finegrained";
 
-            powerManagement.finegrained = cfg.nvidia.powerManagement == "finegrained";
+            powerManagement.finegrained = cfg.powerManagement == "finegrained";
 
             # Integrated GPU
             prime =
-              if cfg.nvidia.integrated.enable then
+              if cfg.integrated.enable then
                 {
                   offload.enable = true;
-                  "${config.hardware.cpu.vendor}BusId" = cfg.nvidia.integrated.integratedBus;
-                  nvidiaBusId = cfg.nvidia.integrated.dedicatedBus;
+                  "${config.hardware.cpu.vendor}BusId" = cfg.integrated.integratedBus;
+                  nvidiaBusId = cfg.integrated.dedicatedBus;
                 }
               else
                 { };
diff --git a/config/nixos/modules/homeManager.nix b/config/nixos/modules/homeManager.nix
@@ -26,18 +26,18 @@ in
     {
       home-manager = {
         useGlobalPkgs = true;
+        useUserPackages = true;
         extraSpecialArgs = {
           inherit (inputs.self) homeManagerModules;
 
-          inputs = inputs;
+          inherit inputs;
           systemConfig = config;
         };
 
         sharedModules = [
-          inputs.impermanence.homeManagerModules.impermanence
           {
             home.sessionVariables = {
-              NIXPKGS_PATH = NIXPKGS_PATH;
+              inherit NIXPKGS_PATH;
               NIX_PATH = "nixpkgs=${NIXPKGS_PATH}";
             };
           }
diff --git a/config/nixos/modules/networking/NetworkManager.nix b/config/nixos/modules/networking/NetworkManager.nix
@@ -0,0 +1,28 @@
+{
+  povSelf,
+  config,
+  lib,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    modules.filesystem.impermanence.system.dirs = [
+      "/var/lib/NetworkManager"
+      "/etc/NetworkManager/system-connections"
+    ];
+
+    networking.networkmanager.enable = true;
+  };
+
+}
diff --git a/config/nixos/modules/networking/dn42.nix b/config/nixos/modules/networking/dn42.nix
@@ -55,18 +55,32 @@ in
           };
         });
     };
+    babel.enable = {
+      type = types.bool;
+      default = false;
+    };
+    babel.peerings = {
+      default = { };
+      type =
+        with types;
+        attrsOf (submodule {
+          options = {
+            type = lib.mkOption {
+              type = types.str;
+              default = "tunnel";
+            };
+          };
+        });
+    };
   };
 
   config = lib.mkIf cfg.enable {
     networking.firewall.allowedUDPPorts = lib.mapAttrsToList (
-      name: peerConfig: peerConfig.listenPort
+      _name: peerConfig: peerConfig.listenPort
     ) cfg.peerings;
 
-    systemd.services.systemd-networkd.after = [ "sops-install-secrets.service" ];
-
-    sops.secrets = (
-      cfg.peerings
-      |> lib.mapAttrsToList (
+    sops.secrets = lib.pipe cfg.peerings [
+      (lib.mapAttrsToList (
         name: peerConfig:
         [
           (lib.nameValuePair "dn42/peerings/${name}/wgPrivateKey" {

@@ -80,71 +94,74 @@ in
             group = "systemd-network";
           })
         ]
-      )
-      |> lib.lists.flatten
-      |> lib.listToAttrs
-    );
-
-    systemd.network = {
-      netdevs = lib.mapAttrs' (
-        name: peerConfig:
-        lib.nameValuePair "20-dn42${name}" {
-          netdevConfig = {
-            Kind = "wireguard";
-            Name = "dn42${name}";
-          };
-          wireguardConfig =
-            {
+      ))
+      lib.lists.flatten
+      lib.listToAttrs
+    ];
+
+    systemd = {
+      network = {
+        netdevs = lib.mapAttrs' (
+          name: peerConfig:
+          lib.nameValuePair "20-dn42${name}" {
+            netdevConfig = {
+              Kind = "wireguard";
+              Name = "dn42${name}";
+            };
+            wireguardConfig = {
               ListenPort = peerConfig.listenPort;
               PrivateKeyFile = config.sops.secrets."dn42/peerings/${name}/wgPrivateKey".path;
             }
             // (lib.optionalAttrs peerConfig.hasPresharedKey {
               PresharedKeyFile = config.sops.secrets."dn42/peerings/${name}/wgPresharedKey".path;
             });
-          wireguardPeers = [
-            {
-              PersistentKeepalive = 30;
-              Endpoint = lib.mkIf (!builtins.isNull peerConfig.endpoint) peerConfig.endpoint;
-              PublicKey = peerConfig.publicKey;
-              AllowedIPs = [
-                "fd00::/8"
-                peerConfig.remoteLinkLocalAddress
-              ];
-            }
-          ];
-        }
-      ) cfg.peerings;
+            wireguardPeers = [
+              {
+                PersistentKeepalive = 30;
+                Endpoint = lib.mkIf (!builtins.isNull peerConfig.endpoint) peerConfig.endpoint;
+                PublicKey = peerConfig.publicKey;
+                AllowedIPs = [
+                  "fd00::/8"
+                  peerConfig.remoteLinkLocalAddress
+                ];
+              }
+            ];
+          }
+        ) cfg.peerings;
 
-      networks = lib.mapAttrs' (
-        name: peerConfig:
-        lib.nameValuePair "20-dn42${name}" {
-          matchConfig.Name = "dn42${name}";
-          linkConfig.RequiredForOnline = "no";
+        networks = lib.mapAttrs' (
+          name: peerConfig:
+          lib.nameValuePair "20-dn42${name}" {
+            matchConfig.Name = "dn42${name}";
+            linkConfig.RequiredForOnline = "no";
 
-          address = [ peerConfig.localLinkLocalAddress ];
-          routes = [ { Destination = "${peerConfig.remoteLinkLocalAddress}/128"; } ];
+            address = [ peerConfig.localLinkLocalAddress ];
+            routes = [ { Destination = "${peerConfig.remoteLinkLocalAddress}/128"; } ];
 
-          networkConfig = {
-            IPv6Forwarding = true;
-            IPv6AcceptRA = false;
-            DHCP = false;
-          };
-        }
-      ) cfg.peerings;
-    };
-
-    systemd.services.stayrtr = {
-      wantedBy = [
-        "multi-user.target"
-        "bird.service"
-      ];
-      serviceConfig.DynamicUser = true;
-      serviceConfig.ExecStart = ''
-        ${lib.getExe pkgs.stayrtr} \
-          -bind [::1]:8282 \
-          -cache=https://dn42.burble.com/roa/dn42_roa_46.json \
-          -checktime=false
-      '';
+            networkConfig = {
+              IPv6Forwarding = true;
+              IPv6AcceptRA = false;
+              DHCP = false;
+            };
+          }
+        ) cfg.peerings;
+      };
+      services = {
+        systemd-networkd.after = [ "sops-install-secrets.service" ];
+        stayrtr = {
+          wantedBy = [
+            "multi-user.target"
+            "bird.service"
+          ];
+          serviceConfig.DynamicUser = true;
+          serviceConfig.ExecStart = ''
+            ${lib.getExe pkgs.stayrtr} \
+              -bind [::1]:8282 \
+              -cache=https://dn42.burble.com/roa/dn42_roa_46.json \
+              -checktime=false
+          '';
+        };
+      };
     };
 
     services.bird = {

@@ -156,116 +173,149 @@ in
 
         cat -n bird.conf # here for debugging purposes
       '';
-      config =
-        ''
-          log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
-          log stderr all;
+      config = ''
+        log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
+        log stderr all;
 
-          define OWNAS = ${toString cfg.asn};
-          define OWNNET = ${cfg.range};
-          define OWNNETSET = [ ${cfg.range} ];
-          define OWNIP = ${cfg.address};
+        define OWNAS = ${toString cfg.asn};
+        define OWNNET = ${cfg.range};
+        define OWNNETSET = [ ${cfg.range} ];
+        define OWNIP = ${cfg.address};
 
-          router id ${toString cfg.routerId};
-          hostname "${config.networking.hostName}";
+        router id ${toString cfg.routerId};
+        hostname "${config.networking.hostName}";
 
-          roa6 table dn42_roa;
-
-          function is_self_net() -> bool {
-            return net ~ OWNNETSET;
-          }
+        roa6 table dn42_roa;
 
-          function is_valid_network() -> bool {
-            return net ~ [
-              fd00::/8{44,64}
-            ];
-          }
+        function is_self_net() -> bool {
+          return net ~ OWNNETSET;
+        }
 
-          function import_filter() {
-            if (net.type != NET_IP6 || ! is_valid_network() || is_self_net()) then
-              reject;
+        function is_valid_network() -> bool {
+          return net ~ [
+            fd00::/8{44,64}
+          ];
+        }
 
-            if (roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID) then {
-              # Reject when unknown or invalid according to ROA
-              print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
-              reject;
-            }
+        function import_filter() {
+          if (net.type != NET_IP6 || ! is_valid_network() || is_self_net()) then
+            reject;
 
-            accept;
+          if (roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID) then {
+            # Reject when unknown or invalid according to ROA
+            print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
+            reject;
           }
 
-          function export_filter() {
-            if ( ! is_valid_network() ) then
-              reject;
+          accept;
+        }
 
-            if (source !~ [RTS_STATIC, RTS_BGP]) then
-              reject;
+        function export_filter() {
+          if ( ! is_valid_network() ) then
+            reject;
 
-            accept;
-          }
+          if (source !~ [RTS_STATIC, RTS_BGP]) then
+            reject;
 
-          protocol rpki {
-            roa6 { table dn42_roa; };
-            remote ::1;
-            port 8282;
-            refresh 600;
-            retry 300;
-            expire 7200;
-          }
+          accept;
+        }
 
-          protocol device {
-            scan time 10;
-          }
+        protocol rpki {
+          roa6 { table dn42_roa; };
+          remote ::1;
+          port 8282;
+          refresh 600;
+          retry 300;
+          expire 7200;
+        }
 
-          protocol static {
-            route OWNNET unreachable;
+        protocol device {
+          scan time 10;
+        }
 
-            ipv6 {
-              import all;
-              export none;
-            };
-          }
+        protocol static {
+          route OWNNET unreachable;
 
-          protocol kernel {
-            scan time 20;
-
-            ipv6 {
-              import none;
-              export filter {
-                # dont export static routes
-                if source = RTS_STATIC then reject;
-                # preferred outgoing source address
-                krt_prefsrc = OWNIP;
-                accept;
-              };
+          ipv6 {
+            import all;
+            export none;
+          };
+        }
+
+        protocol kernel {
+          scan time 20;
+
+          ipv6 {
+            import none;
+            export filter {
+              # dont export static routes
+              if source = RTS_STATIC then reject;
+              # preferred outgoing source address
+              krt_prefsrc = OWNIP;
+              accept;
             };
-          }
+          };
+        }
 
-          template bgp dn42_peers {
-            local as OWNAS;
-            path metric 1;
-            advertise hostname on;
-            enforce first as on;
-            med metric on;
+        template bgp dn42_peers {
+          local as OWNAS;
+          path metric 1;
+          advertise hostname on;
+          enforce first as on;
+          med metric on;
 
-            ipv6 {
-              import keep filtered;
-              import limit 9000 action block;
-              import where import_filter();
-              next hop self; # advertise this router as next hop
+          ipv6 {
+            import keep filtered;
+            import limit 9000 action block;
+            import where import_filter();
+            next hop self; # advertise this router as next hop
 
-              export where export_filter();
-            };
+            export where export_filter();
+          };
+        }
+      ''
+      + (lib.concatStringsSep "\n" (
+        lib.mapAttrsToList (name: peerConfig: ''
+          protocol bgp ${name} from dn42_peers {
+            neighbor ${peerConfig.remoteLinkLocalAddress}%dn42${name} as ${toString peerConfig.asn};
+            enable extended messages;
           }
-        ''
-        + (lib.concatStringsSep "\n" (
-          lib.mapAttrsToList (name: peerConfig: ''
-            protocol bgp ${name} from dn42_peers {
-              neighbor ${peerConfig.remoteLinkLocalAddress}%dn42${name} as ${toString peerConfig.asn};
-              enable extended messages;
-            }
-          '') cfg.peerings
-        ));
+        '') cfg.peerings
+      ))
+      + (lib.optionalString cfg.babel.enable ''
+        /* babel config */
+        protocol direct {
+          ipv6 {
+            import where net ~ [ fd00::/8+ ];
+            export where net ~ [ fd00::/8+ ];
+          };
+
+          ${lib.concatStringsSep "\n" (
+            lib.mapAttrsToList (name: _peerConfig: ''
+              interface "${name}";
+            '') cfg.babel.peerings
+          )}
+        };
+
+        protocol babel {
+          randomize router id on;
+
+          ipv6 {
+            import where source != RTS_BGP && is_self_net();
+            export where source != RTS_BGP && is_self_net();
+          };
+
+          ${lib.concatStringsSep "\n" (
+            lib.mapAttrsToList (name: peerConfig: ''
+              interface "${name}" {
+                type ${peerConfig.type};
+                next hop prefer ipv6;
+              };
+            '') cfg.babel.peerings
+          )}
+        };
+        /* End of babel config */
+      '');
     };
   };
 
diff --git a/config/nixos/modules/nix/disableChannels.nix b/config/nixos/modules/nix/disableChannels.nix
@@ -2,7 +2,6 @@
   povSelf,
   config,
   lib,
-  pkgs,
   ...
 }:
 
diff --git a/config/nixos/modules/nix/enable.nix b/config/nixos/modules/nix/enable.nix
@@ -31,10 +31,11 @@ in
         settings = {
           nix-path = config.nix.nixPath;
           trusted-users = [ "@wheel" ];
+          use-xdg-base-directories = true;
           experimental-features = [
             "flakes"
             "nix-command"
-            "pipe-operator"
+            # "pipe-operator"
           ];
         };
       };
diff --git a/config/nixos/modules/presets/base.nix b/config/nixos/modules/presets/base.nix
@@ -23,17 +23,13 @@ in
   config = lib.mkIf cfg.enable {
     boot.kernel.sysctl."kernel.sysrq" = lib.mkDefault 1;
 
-    environment.defaultPackages = lib.mkForce [ ];
-
-    programs.command-not-found.enable = false;
-
     # make things more declerative
-    services.userborn.enable = lib.mkDefault true;
-    users.mutableUsers = lib.mkForce false;
+    #services.userborn.enable = lib.mkDefault true;
+    #users.mutableUsers = lib.mkForce false;
 
     networking = {
       hostId = builtins.substring 0 8 (builtins.hashString "sha256" hostConfig.hostName);
-      hostName = hostConfig.hostName;
+      inherit (hostConfig) hostName;
       domain = lib.mkDefault hostConfig.domain;
 
       useNetworkd = lib.mkDefault true;

@@ -46,8 +42,10 @@ in
     hardware.enableRedistributableFirmware = true;
 
     modules = {
-      boot.enable = lib.mkDefault true;
-      boot.type = lib.mkDefault "uefi";
+      boot = {
+        enable = lib.mkDefault true;
+        type = lib.mkDefault "uefi";
+      };
 
       locale.enable = lib.mkDefault true;
       unfree.enable = lib.mkDefault true;

@@ -81,29 +79,36 @@ in
       };
     };
 
+    programs = {
+      command-not-found.enable = false; # Not usable without channels; use nix-index instead.
+    };
+
     services = {
+      dbus.implementation = "broker";
       #fstrim.enable = lib.mkDefault true;
     };
 
     security.sudo.extraConfig = "Defaults lecture=\"never\""; # "We trust you have received the usual lecture from the local System Administrator."
 
-    # thanks piegames (https://git.darmstadt.ccc.de/piegames/home-config/-/blob/master/modules/generic.nix#L84)
-    system.activationScripts = {
-      diff = {
-        supportsDryActivation = true;
-        text = ''
-          ${pkgs.nvd}/bin/nvd --color=always --nix-bin-dir=${pkgs.nix}/bin diff "$(readlink /run/current-system)" "$systemConfig"
-          # Ignore "failures" because these tools have weird exit codes
-          ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \
-            -- "$(readlink /run/current-system)/activate" "$systemConfig/activate" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true
-          ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \
-            -x "os-release" -x "issue" \
-            -- "$(readlink /run/current-system)/etc" "$systemConfig/etc" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true
-          ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \
-            -x "environment.d" \
-            -x "hwdb.d" \
-            -- "$(readlink /run/current-system)/systemd" "$systemConfig/systemd" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true
-        '';
+    system = {
+      # thanks piegames (https://git.darmstadt.ccc.de/piegames/home-config/-/blob/master/modules/generic.nix#L84)
+      activationScripts = {
+        diff = {
+          supportsDryActivation = true;
+          text = ''
+            ${pkgs.nvd}/bin/nvd --color=always --nix-bin-dir=${pkgs.nix}/bin diff "$(readlink /run/current-system)" "$systemConfig"
+            # Ignore "failures" because these tools have weird exit codes
+            ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \
+              -- "$(readlink /run/current-system)/activate" "$systemConfig/activate" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true
+            ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \
+              -x "os-release" -x "issue" \
+              -- "$(readlink /run/current-system)/etc" "$systemConfig/etc" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true
+            ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \
+              -x "environment.d" \
+              -x "hwdb.d" \
+              -- "$(readlink /run/current-system)/systemd" "$systemConfig/systemd" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true
+          '';
+        };
       };
     };
   };
diff --git a/config/nixos/modules/presets/graphical/enable.nix b/config/nixos/modules/presets/graphical/enable.nix
@@ -17,6 +17,13 @@ in
   };
 
   config = lib.mkIf cfg {
+    environment.sessionVariables = {
+      _JAVA_AWT_WM_NONREPARENTING = "1";
+      NIXOS_OZONE_WL = "1";
+      SDL_VIDEODRIVER = "wayland"; # Can break some native games
+      WLR_NO_HARDWARE_CURSORS = "1";
+    };
+
     modules = {
       audio.enable = true;
       boot = {

@@ -25,6 +32,7 @@ in
       };
       font.enable = true;
       homeManager.enable = lib.mkDefault true;
+      programs.nixUtilities.enable = lib.mkDefault true;
     };
   };
 
diff --git a/config/nixos/modules/presets/graphical/type.nix b/config/nixos/modules/presets/graphical/type.nix
@@ -1,12 +1,9 @@
 {
-  povSelf,
-  config,
   lib,
   ...
 }:
 let
   inherit (lib) types;
-  cfg = lib.getAttrFromPath povSelf config;
 
 in
 {

@@ -15,6 +12,8 @@ in
     type = types.nullOr (
       types.enum [
         "gnomeMinimal"
+        "niri"
+        "sway"
       ]
     );
     default = null;
diff --git a/config/nixos/modules/presets/graphical/typeGnomeMinimal.nix b/config/nixos/modules/presets/graphical/typeGnomeMinimal.nix
@@ -6,7 +6,6 @@
   ...
 }:
 let
-  inherit (lib) types;
   cfg = lib.getAttrFromPath pov config;
 
 in

@@ -14,7 +13,7 @@ in
 
   config = lib.mkIf (cfg.enable && (cfg.type == "gnomeMinimal")) {
     nixpkgs.overlays = [
-      (final: prev: {
+      (_final: prev: {
         # patch gdm to automaticly select the first user
         gnome-shell = prev.gnome-shell.overrideAttrs (prevAttrs: {
           patches = prevAttrs.patches ++ [ inputs.self.resources.patches.gdm-autoselect-user ];

@@ -23,11 +22,6 @@ in
     ];
 
     modules.filesystem.impermanence.system.dirs = [
-      "/var/lib/bluetooth"
-      "/var/lib/NetworkManager"
-      "/etc/NetworkManager/system-connections"
-      "/var/lib/power-profiles-daemon"
-      "/var/lib/upower"
       {
         directory = "/var/lib/colord";
         mode = "u=rwx,g=rx,o=";

@@ -38,14 +32,19 @@ in
 
     modules = {
       gnomeMinimal.enable = true;
-      services.earlyoom.avoid = [
-        "gnome-shell"
-        "gdm"
-        "mutter"
-      ];
+      hardware.bluetooth.enable = true;
+      networking.NetworkManager.enable = true;
+      services = {
+        upower.enable = true;
+        power-profiles-daemon.enable = true;
+        earlyoom.avoid = [
+          "gnome-shell"
+          "gdm"
+          "mutter"
+        ];
+      };
     };
 
-    networking.networkmanager.enable = true;
   };
 
 }
diff --git a/config/nixos/modules/presets/graphical/typeNiri.nix b/config/nixos/modules/presets/graphical/typeNiri.nix
@@ -0,0 +1,44 @@
+{
+  pov,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  cfg = lib.getAttrFromPath pov config;
+
+in
+{
+
+  config = lib.mkIf (cfg.enable && (cfg.type == "niri")) {
+    modules = {
+      hardware.bluetooth.enable = true;
+      networking.NetworkManager.enable = true;
+
+      services = {
+        udisks2.enable = true;
+        gvfs.enable = true;
+
+        upower.enable = true;
+        power-profiles-daemon.enable = true;
+
+        swaylock.enable = lib.mkDefault true;
+        greetd = {
+          enable = lib.mkDefault true;
+          greeter = lib.mkDefault "tuigreet";
+          autoLogin.command = lib.mkDefault "niri-session -l";
+        };
+      };
+    };
+
+    security.polkit.enable = true;
+
+    programs = {
+      dconf.enable = true;
+      niri.enable = true;
+      niri.package = pkgs.unstable.niri;
+    };
+  };
+
+}
diff --git a/config/nixos/modules/presets/graphical/typeSway.nix b/config/nixos/modules/presets/graphical/typeSway.nix
@@ -0,0 +1,43 @@
+{
+  pov,
+  config,
+  lib,
+  ...
+}:
+let
+  cfg = lib.getAttrFromPath pov config;
+
+in
+{
+
+  config = lib.mkIf (cfg.enable && (cfg.type == "sway")) {
+    modules = {
+      #hardware.bluetooth.enable = true;
+      networking.NetworkManager.enable = true; # TODO: why is this *here*?
+
+      services = {
+        #udisks2.enable = true;
+        #gvfs.enable = true;
+
+        upower.enable = true;
+        power-profiles-daemon.enable = true;
+
+        #swaylock.enable = lib.mkDefault true;
+        greetd = {
+          enable = lib.mkDefault true;
+          greeter = lib.mkDefault "regreet";
+          autoLogin.command = lib.mkDefault "sway";
+        };
+      };
+    };
+
+    security.polkit.enable = true;
+
+    programs = {
+      #dconf.enable = true;
+      #niri.enable = true;
+      #niri.package = pkgs.unstable.niri;
+    };
+  };
+
+}
diff --git a/config/nixos/modules/presets/minimal.nix b/config/nixos/modules/presets/minimal.nix
@@ -0,0 +1,60 @@
+{
+  povSelf,
+  lib,
+  config,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options = {
+    enable = {
+      type = types.bool;
+      default = false;
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    boot.enableContainers = lib.mkDefault false;
+
+    system.disableInstallerTools = lib.mkDefault true;
+
+    documentation = {
+      enable = lib.mkDefault false;
+      doc.enable = lib.mkDefault false;
+      info.enable = lib.mkDefault false;
+      man.enable = lib.mkDefault false;
+      nixos.enable = lib.mkDefault false;
+    };
+
+    environment = {
+      defaultPackages = lib.mkDefault [ ];
+      stub-ld.enable = lib.mkDefault false;
+    };
+
+    programs = {
+      less.lessopen = lib.mkDefault null;
+      command-not-found.enable = lib.mkDefault false;
+      fish.generateCompletions = lib.mkDefault false;
+    };
+
+    services = {
+      logrotate.enable = lib.mkDefault false;
+      udisks2.enable = lib.mkDefault false;
+    };
+
+    xdg = {
+      autostart.enable = lib.mkDefault false;
+      icons.enable = lib.mkDefault false;
+      mime.enable = lib.mkDefault false;
+      sounds.enable = lib.mkDefault false;
+    };
+
+  };
+
+}
diff --git a/config/nixos/modules/presets/netcup.nix b/config/nixos/modules/presets/netcup.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  pkgs,
   lib,
   config,
   hostConfig,
diff --git a/config/nixos/modules/presets/networkManagerProfiles/cccdaWifi.nix b/config/nixos/modules/presets/networkManagerProfiles/cccdaWifi.nix
@@ -3,7 +3,6 @@
   pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/networkManagerProfiles/grogHomeWifi.nix b/config/nixos/modules/presets/networkManagerProfiles/grogHomeWifi.nix
@@ -0,0 +1,57 @@
+{
+  povSelf,
+  inputs,
+  lib,
+  config,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options = {
+    enable = {
+      type = types.bool;
+      default = false;
+    };
+    username.type = types.str;
+    envFile.type = types.path;
+  };
+
+  config = lib.mkIf cfg.enable {
+    sops.secrets."environments/networkManagerProfiles/grogHome" = {
+      sopsFile = inputs.self.sopsSecrets.common;
+    };
+
+    networking.networkmanager.ensureProfiles = {
+      environmentFiles = [ config.sops.secrets."environments/networkManagerProfiles/grogHome".path ];
+      profiles."grogHome" = {
+        connection = {
+          id = "grogHome";
+          type = "wifi";
+          uuid = "1bbc0cce-148f-4afa-876e-fa6db67d884e";
+        };
+        ipv4 = {
+          method = "auto";
+        };
+        ipv6 = {
+          addr-gen-mode = "default";
+          method = "auto";
+        };
+        proxy = { };
+        wifi = {
+          mode = "infrastructure";
+          ssid = "$GROG_HOME_SSID";
+        };
+        wifi-security = {
+          key-mgmt = "wpa-psk";
+          psk = "$GROG_HOME_PASS";
+        };
+      };
+    };
+  };
+
+}
diff --git a/config/nixos/modules/presets/networkManagerProfiles/voidHomeWifi.nix b/config/nixos/modules/presets/networkManagerProfiles/voidHomeWifi.nix
@@ -1,10 +1,8 @@
 {
   povSelf,
   inputs,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/networkManagerProfiles/voidPhoneWifi.nix b/config/nixos/modules/presets/networkManagerProfiles/voidPhoneWifi.nix
@@ -1,10 +1,8 @@
 {
   povSelf,
   inputs,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/networkManagerProfiles/zaphyraHomeWifi.nix b/config/nixos/modules/presets/networkManagerProfiles/zaphyraHomeWifi.nix
@@ -1,10 +1,8 @@
 {
   povSelf,
   inputs,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/networkManagerProfiles/zaphyraPhoneWifi.nix b/config/nixos/modules/presets/networkManagerProfiles/zaphyraPhoneWifi.nix
@@ -1,10 +1,8 @@
 {
   povSelf,
   inputs,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/void/enable.nix b/config/nixos/modules/presets/void/enable.nix
@@ -1,9 +1,7 @@
 {
   povSelf,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let

@@ -19,9 +17,14 @@ in
   };
 
   config = lib.mkIf cfg {
+    boot.bcache.enable = false;
     fonts.fontconfig.defaultFonts = {
       monospace = [ "MesloLGS NF" ];
     };
+    modules.hardware.smartcard.enable = lib.mkDefault config.modules.presets.graphical.enable;
+    programs = {
+      nix-index.enable = true;
+    };
   };
 
 }
diff --git a/config/nixos/modules/presets/void/stylix.nix b/config/nixos/modules/presets/void/stylix.nix
@@ -0,0 +1,49 @@
+{
+  config,
+  inputs,
+  lib,
+  pkgs,
+  ...
+}:
+
+{
+
+  config = lib.mkIf (config.modules.presets.void.enable && config.modules.presets.graphical.enable) {
+    home-manager.sharedModules = [
+      {
+        dconf.settings."org/gnome/desktop/interface".color-scheme = lib.mkForce "prefer-dark";
+        stylix.targets.librewolf = {
+          #colorTheme.enable = true;
+          profileNames = [ "default" ];
+        };
+      }
+    ];
+    stylix = {
+      enable = true;
+      base16Scheme = "${pkgs.base16-schemes}/share/themes/catppuccin-mocha.yaml";
+      image = inputs.self.resources.void.background;
+      fonts = {
+        serif = {
+          #package = pkgs.roboto;
+          #name = "Roboto Serif";
+        };
+        sansSerif = {
+          #package = pkgs.roboto;
+          #name = "Roboto Sans";
+        };
+        monospace = {
+          package = pkgs.nerd-fonts.fira-code;
+          name = "FiraCode Nerd Font";
+        };
+      };
+      iconTheme = {
+        enable = true;
+        package = pkgs.papirus-icon-theme;
+        dark = "Papirus-Dark";
+        light = "Papirus-Light";
+      };
+      opacity.terminal = 0.9;
+    };
+  };
+
+}
diff --git a/config/nixos/modules/presets/zaphyra/dn42.nix b/config/nixos/modules/presets/zaphyra/dn42.nix
@@ -1,7 +1,5 @@
 {
-  inputs,
   povSelf,
-  pkgs,
   lib,
   config,
   hostConfig,

@@ -40,8 +38,76 @@ in
       };
     };
 
+    services.resolved = {
+      enable = true;
+      fallbackDns = [
+        "8.8.8.8"
+        "2001:4860:4860::8844"
+      ];
+    };
+
+    systemd.network = {
+      networks."20-dn42" = {
+        matchConfig.Name = "dn42";
+        routes = [ { Destination = "fd00::/8"; } ];
+        networkConfig = {
+          DNSDefaultRoute = false;
+          DNS = [ "fd6b:6174:6a61::1" ];
+          Domains = [
+            "~dn42"
+            "d.f.ip6.arpa"
+          ];
+        };
+      };
+    };
+
     modules.services.prometheusExporters.domain = "${lib.removeSuffix ".zaphyra.eu" config.networking.fqdn}.zaphyra.dn42";
 
+    security.pki.certificates = [
+      #dn42 root ca
+      ''
+        -----BEGIN CERTIFICATE-----
+        MIID8DCCAtigAwIBAgIFIBYBAAAwDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMC
+        WEQxDTALBgNVBAoMBGRuNDIxIzAhBgNVBAsMGmRuNDIgQ2VydGlmaWNhdGUgQXV0
+        aG9yaXR5MR8wHQYDVQQDDBZkbjQyIFJvb3QgQXV0aG9yaXR5IENBMCAXDTE2MDEx
+        NjAwMTIwNFoYDzIwMzAxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJYRDENMAsGA1UE
+        CgwEZG40MjEjMCEGA1UECwwaZG40MiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAd
+        BgNVBAMMFmRuNDIgUm9vdCBBdXRob3JpdHkgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
+        A4IBDwAwggEKAoIBAQDBGRDeAYYR8YIMsNTl/5rI46r0AAiCwM9/BXohl8G1i6PR
+        VO76BA931VyYS9mIGMEXEJLlJPrvYetdexHlvrqJ8mDJO4IFOnRUYCNmGtjNKHvx
+        6lUlmowEoP+dSFRMnbwtoN9xrmRHDed1BfTFAirSDL6jY1RiK60p62oIpF6o6/FS
+        FE7RXUEv0xm65II2etGj8oT2B7L2DDDb23bu6RQFx491tz/V1TVW0JJE3yYeAPqu
+        y3rJUGddafj5/SWnHdtAsUK8RVfhyRxCummAHuolmRKfbyOj0i5KzRXkfEn50cDw
+        GQwVUM6mUbuqFrKC7PRhRIwc3WVgBHewTZlnF/sJAgMBAAGjgaowgacwDgYDVR0P
+        AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFR2iLLAtTDQ/E/J
+        bTv5jFURrBUVMB8GA1UdIwQYMBaAFFR2iLLAtTDQ/E/JbTv5jFURrBUVMEQGA1Ud
+        HgQ9MDugOTAHggUuZG40MjAKhwisFAAA//wAADAihyD9QgAAAAAAAAAAAAAAAAAA
+        //8AAAAAAAAAAAAAAAAAADANBgkqhkiG9w0BAQsFAAOCAQEAXKQ7QaCBaeJxmU11
+        S1ogDSrZ7Oq8jU+wbPMuQRqgdfPefjrgp7nbzfUW5GrL58wqj+5/FAqltflmSIHl
+        aB4MpqM8pyvjlc/jYxUNFglj2WYxO0IufBrlKI5ePZ4omUjpR4YR4gQpYCuWlZmu
+        P6v/P0WrfgdFTk0LGEA9OwKcTqkPpcI/SjB3rmZcs42yQWvimAF94GtScE09uKlI
+        9QLS2UBmtl5EJRFVrDEC12dyamq8dDRfddyaT4MoQOAq3D9BQ1pHByu3pz/QFaJC
+        1zAi8vbktPY7OMprTOc8pHDL3q8KFP8jJcoEzZ5Jw0vkCrULhLXvtFtjB0djzVxQ
+        C0IKqQ==
+        -----END CERTIFICATE-----
+      ''
+    ];
+
+    environment.etc."whois.conf".text = ''
+      \.dn42$           whois.dn42
+      \-DN42$           whois.dn42
+      # dn42 range 64512-65534
+      ^as6(4(5(1[2-9]|[2-9][0-9])|[6-9][0-9]{2})|5([0-4][0-9]{2}|5([0-2][0-9]|3[0-4])))$ whois.dn42
+      # dn42 range 76100-76199
+      ^as761[0-9][0-9]$   whois.dn42
+      # dn42 range 4242420000-4242429999
+      ^as424242[0-9]{4}$ whois.dn42
+      # dn42 ipv4 address space
+      ^172\.2[0-3]\.[0-9]{1,3}\.[0-9]{1,3}(/(1[56789]|2[0-9]|3[012]))?$ whois.dn42
+
+      # dn42 ula ipv6 address space
+      ^fd**:****:****:****:****:****:****:**** whois.dn42
+    '';
   };
 
 }
diff --git a/config/nixos/modules/presets/zaphyra/dnsServer.nix b/config/nixos/modules/presets/zaphyra/dnsServer.nix
@@ -1,10 +1,8 @@
 {
   inputs,
   povSelf,
-  pkgs,
   lib,
   config,
-  hostConfig,
   dnsNix,
   ...
 }:

@@ -111,12 +109,8 @@ in
             inherit SOA NS CAA;
 
             subdomains = {
-              ns1 = (
-                host inputs.self.hosts.morio.networking.ip4Address inputs.self.hosts.morio.networking.ip6Address
-              );
-              ns2 = (
-                host inputs.self.hosts.novus.networking.ip4Address inputs.self.hosts.novus.networking.ip6Address
-              );
+              ns1 = host inputs.self.hosts.morio.networking.ip4Address inputs.self.hosts.morio.networking.ip6Address;
+              ns2 = host inputs.self.hosts.novus.networking.ip4Address inputs.self.hosts.novus.networking.ip6Address;
 
               _atproto.TXT = [ "did=did:plc:zaeuok3fmh2pcp4cjiicku4i" ];
             };

@@ -131,7 +125,10 @@ in
             inherit SOA NS CAA;
             A = [ "94.16.104.148" ];
             AAAA = [ "2a03:4000:50:e8::1" ];
-            subdomains.client.CNAME = [ "zuggeschmack.de." ];
+            subdomains = {
+              trabbi.CNAME = [ "zuggeschmack.de." ];
+              client.CNAME = [ "zuggeschmack.de." ];
+            };
           };
         };
 

@@ -145,7 +142,7 @@ in
 
       dns = {
         enable = true;
-        allZones = allZones;
+        inherit allZones;
       };
 
       modules.services = {

@@ -153,15 +150,12 @@ in
           enable = true;
           primary = cfg.isPrimary;
           zones = lib.mkIf cfg.isPrimary (
-            config.dns.zoneFiles
-            |> lib.mapAttrs (
-              name: value: {
-                file = value;
-                journal-content = "all";
-                zonefile-sync = -1;
-                zonefile-load = "difference-no-serial";
-              }
-            )
+            lib.mapAttrs (_name: value: {
+              file = value;
+              journal-content = "all";
+              zonefile-sync = -1;
+              zonefile-load = "difference-no-serial";
+            }) config.dns.zoneFiles
           );
         };
         knotACME = lib.mkIf cfg.isPrimary {
diff --git a/config/nixos/modules/presets/zaphyra/enable.nix b/config/nixos/modules/presets/zaphyra/enable.nix
@@ -52,8 +52,11 @@ in
 
           hardware.smartcard.enable = lib.mkDefault config.modules.presets.graphical.enable;
 
-          presets.zaphyra = {
-            syncthing.enable = lib.mkDefault true;
+          presets = {
+            minimal.enable = true;
+            zaphyra = {
+              syncthing.enable = lib.mkDefault true;
+            };
           };
 
           services = {

@@ -87,53 +90,26 @@ in
             };
             certs."${config.networking.fqdn}" = {
               group = lib.mkIf config.services.nginx.enable "nginx";
-              extraDomainNames = (
-                config.services.nginx.virtualHosts
-                |> lib.mapAttrsToList (
+              extraDomainNames = lib.pipe config.services.nginx.virtualHosts [
+                (lib.mapAttrsToList (
                   key: config: [
-                    (if config ? serverAliases then config.serverAliases else [ ])
+                    (config.serverAliases or [ ])
                     key
                   ]
-                )
-                |> lib.flatten
-                |> lib.filter (domain: !(lib.hasSuffix "dn42" domain))
-              );
+                ))
+                lib.flatten
+                (lib.filter (domain: !(lib.hasSuffix "dn42" domain)))
+              ];
             };
           };
-          pki.certificates = [
-            ''
-              -----BEGIN CERTIFICATE-----
-              MIID8DCCAtigAwIBAgIFIBYBAAAwDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMC
-              WEQxDTALBgNVBAoMBGRuNDIxIzAhBgNVBAsMGmRuNDIgQ2VydGlmaWNhdGUgQXV0
-              aG9yaXR5MR8wHQYDVQQDDBZkbjQyIFJvb3QgQXV0aG9yaXR5IENBMCAXDTE2MDEx
-              NjAwMTIwNFoYDzIwMzAxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJYRDENMAsGA1UE
-              CgwEZG40MjEjMCEGA1UECwwaZG40MiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAd
-              BgNVBAMMFmRuNDIgUm9vdCBBdXRob3JpdHkgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
-              A4IBDwAwggEKAoIBAQDBGRDeAYYR8YIMsNTl/5rI46r0AAiCwM9/BXohl8G1i6PR
-              VO76BA931VyYS9mIGMEXEJLlJPrvYetdexHlvrqJ8mDJO4IFOnRUYCNmGtjNKHvx
-              6lUlmowEoP+dSFRMnbwtoN9xrmRHDed1BfTFAirSDL6jY1RiK60p62oIpF6o6/FS
-              FE7RXUEv0xm65II2etGj8oT2B7L2DDDb23bu6RQFx491tz/V1TVW0JJE3yYeAPqu
-              y3rJUGddafj5/SWnHdtAsUK8RVfhyRxCummAHuolmRKfbyOj0i5KzRXkfEn50cDw
-              GQwVUM6mUbuqFrKC7PRhRIwc3WVgBHewTZlnF/sJAgMBAAGjgaowgacwDgYDVR0P
-              AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFR2iLLAtTDQ/E/J
-              bTv5jFURrBUVMB8GA1UdIwQYMBaAFFR2iLLAtTDQ/E/JbTv5jFURrBUVMEQGA1Ud
-              HgQ9MDugOTAHggUuZG40MjAKhwisFAAA//wAADAihyD9QgAAAAAAAAAAAAAAAAAA
-              //8AAAAAAAAAAAAAAAAAADANBgkqhkiG9w0BAQsFAAOCAQEAXKQ7QaCBaeJxmU11
-              S1ogDSrZ7Oq8jU+wbPMuQRqgdfPefjrgp7nbzfUW5GrL58wqj+5/FAqltflmSIHl
-              aB4MpqM8pyvjlc/jYxUNFglj2WYxO0IufBrlKI5ePZ4omUjpR4YR4gQpYCuWlZmu
-              P6v/P0WrfgdFTk0LGEA9OwKcTqkPpcI/SjB3rmZcs42yQWvimAF94GtScE09uKlI
-              9QLS2UBmtl5EJRFVrDEC12dyamq8dDRfddyaT4MoQOAq3D9BQ1pHByu3pz/QFaJC
-              1zAi8vbktPY7OMprTOc8pHDL3q8KFP8jJcoEzZ5Jw0vkCrULhLXvtFtjB0djzVxQ
-              C0IKqQ==
-              -----END CERTIFICATE-----
-            ''
-          ];
         };
 
         services = {
           timesyncd.enable = lib.mkDefault true;
           fstrim.enable = lib.mkDefault true;
 
+          speechd.enable = false;
+
           journald.extraConfig = "SystemMaxUse=2.5G";
 
           logind.killUserProcesses = lib.mkDefault true;
diff --git a/config/nixos/modules/presets/zaphyra/mailServer.nix b/config/nixos/modules/presets/zaphyra/mailServer.nix
@@ -130,7 +130,7 @@ in
             };
           };
         }
-        // (lib.mapAttrs (domain: dkimKey: {
+        // (lib.mapAttrs (_domain: dkimKey: {
           inherit MX TXT;
 
           subdomains = {

@@ -139,7 +139,8 @@ in
           };
         }) cfg.extraDomains);
 
-      systemd.services.dovecot.after = [ "sops-install-secrets.service" ];
+      systemd.services.dovecot2.after = [ "sops-install-secrets.service" ];
+
       sops.secrets = {
         "mailPasswords/katja@zaphyra.eu" = { };
         "mailPasswords/gts@zaphyra.eu" = { };

@@ -151,8 +152,9 @@ in
           sopsFile = inputs.self.sopsSecrets.zaphyra.sieve;
           key = "katja@zaphyra.eu";
           restartUnits = [ "dovecot2.service" ];
-          owner = "dovecot2";
-          path = "/etc/dovecot/sieve/katja@zaphyra.eu.sieve";
+          owner = "virtualMail";
+          group = "virtualMail";
+          path = "/etc/dovecot/sieve/katja-zaphyra-eu.sieve";
         };
       };
 

@@ -243,14 +245,15 @@ in
 
         domains = [
           cfg.primaryDomain
-        ] ++ (lib.attrNames cfg.extraDomains);
+        ]
+        ++ (lib.attrNames cfg.extraDomains);
 
         loginAccounts = {
           "katja@zaphyra.eu" = {
             hashedPasswordFile = config.sops.secrets."mailPasswords/katja@zaphyra.eu".path;
             sieveScript = ''
               require ["include"];
-              include :global "katja@zaphyra.eu";
+              include :global "katja-zaphyra-eu";
             '';
             aliases = [
               "@zaphyra.eu"

@@ -281,6 +284,10 @@ in
         };
       };
 
+      services.dovecot2.pluginSettings = {
+        sieve_global = "/etc/dovecot/sieve";
+      };
+
       modules.services.resticBackup.paths.mail = {
         passwordFile = config.sops.secrets."resticPasswords/mail".path;
         paths = [
diff --git a/config/nixos/modules/presets/zaphyra/mautrixBridges/signal.nix b/config/nixos/modules/presets/zaphyra/mautrixBridges/signal.nix
@@ -3,7 +3,6 @@
   pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let

@@ -21,14 +20,14 @@ in
   config = lib.mkIf cfg.enable {
     assertions = [
       {
-        assertion = config.modules.websites."grapevine.zaphyra.eu".enable == true;
+        assertion = config.modules.websites."grapevine.zaphyra.eu".enable;
         message = "The option 'modules.websites.\"grapevine.zaphyra.eu\"' must be enabled in order to use this module.";
       }
     ];
 
     sops.secrets."environments/mautrixBridges/signal" = { };
 
-    modules.services.mautrixBridge.signal = {
+    tgc.services.mautrixBridge.signal = {
       enable = true;
       package = pkgs.mautrix-signal.override { withGoolm = true; };
       environmentFile = config.sops.secrets."environments/mautrixBridges/signal".path;

@@ -66,16 +65,15 @@ in
 
           permissions."${homeserver.domain}" = "admin";
 
-          cleanup_on_logout =
-            {
-              enabled = true;
-            }
-            // (lib.genAttrs [ "manual" "bad_credentials" ] (name: {
-              shared_has_users = "delete";
-              shared_no_users = "delete";
-              relayed = "delete";
-              private = "delete";
-            }));
+          cleanup_on_logout = {
+            enabled = true;
+          }
+          // (lib.genAttrs [ "manual" "bad_credentials" ] (_name: {
+            shared_has_users = "delete";
+            shared_no_users = "delete";
+            relayed = "delete";
+            private = "delete";
+          }));
         };
       };
     };
diff --git a/config/nixos/modules/presets/zaphyra/mautrixBridges/telegram.nix b/config/nixos/modules/presets/zaphyra/mautrixBridges/telegram.nix
@@ -3,7 +3,6 @@
   pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let

@@ -21,16 +20,16 @@ in
   config = lib.mkIf cfg.enable {
     assertions = [
       {
-        assertion = config.modules.websites."grapevine.zaphyra.eu".enable == true;
+        assertion = config.modules.websites."grapevine.zaphyra.eu".enable;
         message = "The option 'modules.websites.\"grapevine.zaphyra.eu\"' must be enabled in order to use this module.";
       }
     ];
 
     sops.secrets."environments/mautrixBridges/telegram" = { };
 
-    modules.services.mautrixBridge.telegram = {
+    tgc.services.mautrixBridge.telegram = {
       enable = true;
-      package = pkgs.mautrix-telegramgo.override { withGoolm = true; };
+      package = pkgs.tgc.mautrix-telegramgo;
       environmentFile = config.sops.secrets."environments/mautrixBridges/telegram".path;
       serviceDependencies = [ "grapevine.service" ];
       settings = rec {

@@ -68,16 +67,15 @@ in
 
           permissions."${homeserver.domain}" = "admin";
 
-          cleanup_on_logout =
-            {
-              enabled = true;
-            }
-            // (lib.genAttrs [ "manual" "bad_credentials" ] (name: {
-              shared_has_users = "delete";
-              shared_no_users = "delete";
-              relayed = "delete";
-              private = "delete";
-            }));
+          cleanup_on_logout = {
+            enabled = true;
+          }
+          // (lib.genAttrs [ "manual" "bad_credentials" ] (_name: {
+            shared_has_users = "delete";
+            shared_no_users = "delete";
+            relayed = "delete";
+            private = "delete";
+          }));
         };
       };
     };
diff --git a/config/nixos/modules/presets/zaphyra/mautrixBridges/whatsapp.nix b/config/nixos/modules/presets/zaphyra/mautrixBridges/whatsapp.nix
@@ -3,7 +3,6 @@
   pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let

@@ -21,14 +20,14 @@ in
   config = lib.mkIf cfg.enable {
     assertions = [
       {
-        assertion = config.modules.websites."grapevine.zaphyra.eu".enable == true;
+        assertion = config.modules.websites."grapevine.zaphyra.eu".enable;
         message = "The option 'modules.websites.\"grapevine.zaphyra.eu\"' must be enabled in order to use this module.";
       }
     ];
 
     sops.secrets."environments/mautrixBridges/whatsapp" = { };
 
-    modules.services.mautrixBridge.whatsapp = {
+    tgc.services.mautrixBridge.whatsapp = {
       enable = true;
       package = pkgs.mautrix-whatsapp.override { withGoolm = true; };
       serviceDependencies = [ "grapevine.service" ];

@@ -41,9 +40,11 @@ in
           url_previews = true;
           history_sync = {
             request_full_sync = true;
-            full_sync_config.days_limit = 1000;
-            full_sync_config.size_mb_limit = 1024;
-            full_sync_config.storage_quota_mb = 1024;
+            full_sync_config = {
+              days_limit = 1000;
+              size_mb_limit = 1024;
+              storage_quota_mb = 1024;
+            };
           };
         };
 

@@ -77,16 +78,15 @@ in
 
           permissions."${homeserver.domain}" = "admin";
 
-          cleanup_on_logout =
-            {
-              enabled = true;
-            }
-            // (lib.genAttrs [ "manual" "bad_credentials" ] (name: {
-              shared_has_users = "delete";
-              shared_no_users = "delete";
-              relayed = "delete";
-              private = "delete";
-            }));
+          cleanup_on_logout = {
+            enabled = true;
+          }
+          // (lib.genAttrs [ "manual" "bad_credentials" ] (_name: {
+            shared_has_users = "delete";
+            shared_no_users = "delete";
+            relayed = "delete";
+            private = "delete";
+          }));
         };
       };
     };
diff --git a/config/nixos/modules/presets/zaphyra/networkManagerProfiles/dn42.nix b/config/nixos/modules/presets/zaphyra/networkManagerProfiles/dn42.nix
@@ -1,9 +1,7 @@
 {
   povSelf,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let

@@ -38,7 +36,7 @@ in
         ipv6 = {
           addr-gen-mode = "default";
           address1 = "fd6b:6174:6a61::3/128";
-          dns = "fd42:d42:d42:54::1;fd42:d42:d42:53::1;";
+          dns = "fd6b:6174:6a61::1;";
           dns-search = "~dn42;";
           method = "manual";
         };
diff --git a/config/nixos/modules/presets/zaphyra/router/enable.nix b/config/nixos/modules/presets/zaphyra/router/enable.nix
@@ -4,7 +4,6 @@
   pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let

@@ -50,42 +49,47 @@ in
     };
 
     services = {
-      resolved.enable = false;
-
-      avahi.enable = true;
-      avahi.reflector = true;
-      avahi.allowInterfaces = [ "brlan" ];
-
-      kresd.enable = true;
-      kresd.listenPlain = [ "53" ];
-      kresd.extraConfig = ''
-        require 'math'
-        math.randomseed(os.time())
-
-        modules.load('dns64')
-        modules.load('view')
-
-        dns64.config('64:ff9b::')
-
-        -- disable dns64 for all IPv4 source addresses
-        view:addr('0.0.0.0/0', policy.all(policy.FLAGS('DNS64_DISABLE')))
-
-        dns_providers = {
-          { -- Quad9
-            '9.9.9.9', '149.112.112.112'
-          },
-          { -- Cloudflare
-            '1.1.1.1', '1.0.0.1'
-          },
-          { -- Google
-            '8.8.8.8', '8.8.4.4'
+      avahi = {
+        enable = true;
+        reflector = true;
+        allowInterfaces = [ "brlan" ];
+      };
+
+      kresd = {
+        enable = true;
+        listenPlain = [
+          "10.0.0.1:53"
+          "[fd6b:6174:6a61::5]:53"
+        ];
+        extraConfig = ''
+          require 'math'
+          math.randomseed(os.time())
+
+          modules.load('dns64')
+          modules.load('view')
+
+          dns64.config('64:ff9b::')
+
+          -- disable dns64 for all IPv4 source addresses
+          view:addr('0.0.0.0/0', policy.all(policy.FLAGS('DNS64_DISABLE')))
+
+          dns_providers = {
+            { -- Quad9
+              '9.9.9.9', '149.112.112.112'
+            },
+            { -- Cloudflare
+              '1.1.1.1', '1.0.0.1'
+            },
+            { -- Google
+              '8.8.8.8', '8.8.4.4'
+            }
           }
-        }
 
-        policy.add(function (request, query)
-          return policy.FORWARD(dns_providers[math.random(1, #dns_providers)])
-        end)
-      '';
+          policy.add(function (request, query)
+            return policy.FORWARD(dns_providers[math.random(1, #dns_providers)])
+          end)
+        '';
+      };
     };
 
   };
diff --git a/config/nixos/modules/presets/zaphyra/router/pppd.nix b/config/nixos/modules/presets/zaphyra/router/pppd.nix
@@ -1,10 +1,7 @@
 {
   povSelf,
-  pkgs,
   lib,
   config,
-  hostConfig,
-  utils,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/zaphyra/router/systemd-networkd.nix b/config/nixos/modules/presets/zaphyra/router/systemd-networkd.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  pkgs,
   lib,
   config,
   hostConfig,
diff --git a/config/nixos/modules/presets/zaphyra/smarthome/enable.nix b/config/nixos/modules/presets/zaphyra/smarthome/enable.nix
@@ -1,10 +1,7 @@
 {
-  inputs,
   pov,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/zaphyra/smarthome/mosqitto.nix b/config/nixos/modules/presets/zaphyra/smarthome/mosqitto.nix
@@ -1,9 +1,7 @@
 {
   povSelf,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/zaphyra/smarthome/mqttWebUI.nix b/config/nixos/modules/presets/zaphyra/smarthome/mqttWebUI.nix
@@ -20,7 +20,7 @@ in
   };
 
   config = lib.mkIf cfg {
-    dns.zones."zaphyra.eu".subdomains."smart.home.infra".AAAA = [ hostConfig.networking.ip6Address ];
+    dns.zones."zaphyra.eu".subdomains."smart.home.infra".AAAA = [ hostConfig.networking.dn42Address ];
 
     services.nginx = {
       enable = true;
diff --git a/config/nixos/modules/presets/zaphyra/smarthome/telegraf.nix b/config/nixos/modules/presets/zaphyra/smarthome/telegraf.nix
@@ -1,9 +1,7 @@
 {
   povSelf,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let
diff --git a/config/nixos/modules/presets/zaphyra/smarthome/zigbee2mqtt.nix b/config/nixos/modules/presets/zaphyra/smarthome/zigbee2mqtt.nix
@@ -21,7 +21,7 @@ in
 
   config = lib.mkIf cfg {
     dns.zones."zaphyra.eu".subdomains."zigbee2mqtt.home.infra".AAAA = [
-      hostConfig.networking.ip6Address
+      hostConfig.networking.dn42Address
     ];
 
     modules.filesystem.impermanence.system.dirs = [
diff --git a/config/nixos/modules/presets/zaphyra/syncthing.nix b/config/nixos/modules/presets/zaphyra/syncthing.nix
@@ -1,10 +1,8 @@
 {
   inputs,
   povSelf,
-  pkgs,
   lib,
   config,
-  hostConfig,
   ...
 }:
 let

@@ -42,6 +40,7 @@ in
         "zaphyra-audiobooks"
         "zaphyra-documents"
         "zaphyra-pictures"
+        "zaphyra-music"
         "zaphyra-videos"
         "zaphyra-db-richtlinien"
       ];

@@ -58,6 +57,7 @@ in
         #servers
         polaris.name = "polaris.home.infra.zaphyra.eu";
         polaris.id = "QI2EPUE-4VMZ3XV-LXX3GXP-RHCWTRY-AACLSGL-YG7MIYV-THST74N-KJGIBQ6";
+        pratorum.id = "JUIJQZE-AWVYZIZ-CR6E66M-TAJIRDH-NEPEPZW-FHO37MJ-QM2MV5Q-OFJTEQI";
       };
 
       defaultVersioning = {

@@ -67,35 +67,35 @@ in
         };
       };
 
-      isCurrentHost = key: value: key != config.networking.hostName;
+      isCurrentHost = key: _value: key != config.networking.hostName;
 
-      deviceNames = (syncthingDevices |> lib.filterAttrs isCurrentHost |> builtins.attrNames);
+      deviceNames = lib.pipe syncthingDevices [
+        (lib.filterAttrs isCurrentHost)
+        builtins.attrNames
+      ];
 
       shareDeviceNames =
         share:
-        (
-          syncthingDevices
-          |> lib.filterAttrs isCurrentHost
-          |> lib.filterAttrs (
-            name: value:
+        (lib.pipe syncthingDevices [
+          (lib.filterAttrs isCurrentHost)
+          (lib.filterAttrs (
+            name: _value:
             let
               syncthingCfg = inputs.self.zaphyraHosts."${name}".config.modules.presets.zaphyra.syncthing;
             in
-            (
-              if (inputs.self.zaphyraHosts ? name) then
-                if (syncthingCfg.enable) then lib.elem share syncthingCfg.enabledShares else false
-              else
-                false
-            )
-          )
-          |> builtins.attrNames
-        );
+            if (inputs.self.zaphyraHosts ? name) then
+              if syncthingCfg.enable then lib.elem share syncthingCfg.enabledShares else false
+            else
+              false
+          ))
+          builtins.attrNames
+        ]);
 
       devices = lib.filterAttrs isCurrentHost syncthingDevices;
 
       folders =
         let
-          dataDir = config.services.syncthing.dataDir;
+          inherit (config.services.syncthing) dataDir;
 
         in
         {

@@ -166,9 +166,9 @@ in
 
     in
     {
-      sops.secrets = lib.genAttrs [ "syncthing/cert" "syncthing/key" ] (name: {
+      sops.secrets = lib.genAttrs [ "syncthing/cert" "syncthing/key" ] (_name: {
         owner = cfg.user;
-        group = cfg.group;
+        inherit (cfg) group;
       });
 
       services.syncthing = {

@@ -176,14 +176,14 @@ in
         openDefaultPorts = true;
         guiAddress = "[::1]:8384";
 
-        user = cfg.user;
-        group = cfg.group;
+        inherit (cfg) user;
+        inherit (cfg) group;
 
         cert = config.sops.secrets."syncthing/cert".path;
         key = config.sops.secrets."syncthing/key".path;
 
-        dataDir = cfg.dataDir;
-        configDir = cfg.configDir;
+        inherit (cfg) dataDir;
+        inherit (cfg) configDir;
 
         settings.devices = devices;
         settings.folders = folders;
diff --git a/config/nixos/modules/programs/nixUtilities.nix b/config/nixos/modules/programs/nixUtilities.nix
@@ -0,0 +1,31 @@
+{
+  config,
+  lib,
+  pkgs,
+  povSelf,
+  ...
+}:
+
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = with pkgs; [
+      deadnix
+      nixfmt-rfc-style
+      nixfmt-tree
+      nixd
+      statix
+    ];
+  };
+
+}
diff --git a/config/nixos/modules/programs/shellUtilities.nix b/config/nixos/modules/programs/shellUtilities.nix
@@ -19,23 +19,29 @@ in
   };
 
   config = lib.mkIf cfg.enable {
-    environment.systemPackages = with pkgs; [
-      age
-      eza
-      file
-      gnupg
-      helix
-      nmap
-      nvd
-      openssh
-      openssl
-      p7zip
-      progress
-      screen
-      sops
-      unzip
-      rsync
-    ];
+    environment = {
+      variables = {
+        HISTFILE = "\"\${XDG_STATE_HOME}\"/bash/history";
+      };
+
+      systemPackages = with pkgs; [
+        age
+        eza
+        file
+        gnupg
+        nmap
+        nvd
+        openssh
+        openssl
+        p7zip
+        progress
+        screen
+        sops
+        unzip
+        rsync
+        tgc.nix-cleanup
+      ];
+    };
 
     programs = {
       bat.enable = true;
diff --git a/config/nixos/modules/programs/steam.nix b/config/nixos/modules/programs/steam.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  pkgs,
   lib,
   config,
   ...

@@ -28,7 +27,7 @@ in
         '';
       }
       {
-        assertion = cfg.enable -> config.modules.filesystem.impermernance.home.enable;
+        assertion = cfg.enable -> !config.modules.filesystem.impermanence.home.enable;
         message = ''
           The programs.steam module can't be used when impermancence is used inside of home-directories.
         '';

@@ -36,6 +35,8 @@ in
     ];
     modules.unfree.list = [
       "steam"
+      "steam-original"
+      "steam-run"
       "steam-unwrapped"
     ];
     programs.steam = {
diff --git a/config/nixos/modules/programs/yubikey.nix b/config/nixos/modules/programs/yubikey.nix
@@ -1,10 +1,8 @@
 {
-  inputs,
   povSelf,
   config,
   lib,
   pkgs,
-  homeManagerModules,
   ...
 }:
 let
diff --git a/config/nixos/modules/services/earlyoom.nix b/config/nixos/modules/services/earlyoom.nix
@@ -30,18 +30,17 @@ in
     services.earlyoom = {
       enable = true;
       enableNotifications = true;
-      extraArgs =
-        [
-          "--ignore-root-user"
-        ]
-        ++ (lib.optionals (cfg.avoid != [ ]) [
-          "--avoid"
-          "(^|/)(${lib.concatStringsSep "|" cfg.avoid})$"
-        ])
-        ++ (lib.optionals (cfg.prefer != [ ]) [
-          "--prefer"
-          "(^|/)(${lib.concatStringsSep "|" cfg.prefer})$"
-        ]);
+      extraArgs = [
+        "--ignore-root-user"
+      ]
+      ++ (lib.optionals (cfg.avoid != [ ]) [
+        "--avoid"
+        "(^|/)(${lib.concatStringsSep "|" cfg.avoid})$"
+      ])
+      ++ (lib.optionals (cfg.prefer != [ ]) [
+        "--prefer"
+        "(^|/)(${lib.concatStringsSep "|" cfg.prefer})$"
+      ]);
     };
   };
 
diff --git a/config/nixos/modules/services/gitolite.nix b/config/nixos/modules/services/gitolite.nix
@@ -81,29 +81,28 @@ in
       commands = lib.mapAttrs (name: script: (pkgs.writeShellScript name script)) cfg.commands;
       manageGitoliteRc = cfg.extraGitoliteRc != "";
       rcDir = pkgs.runCommand "gitolite-rc" { preferLocalBuild = true; } rcDirScript;
-      rcDirScript =
-        ''
-          mkdir "$out"
-          export HOME=temp-home
-          mkdir -p "$HOME/.gitolite/logs" # gitolite can't run without it
-          '${pkgs.gitolite}'/bin/gitolite print-default-rc >>"$out/gitolite.rc.default"
-          cat <<END >>"$out/gitolite.rc"
-          # This file is managed by NixOS.
-          # Use services.gitolite options to control it.
-
-          END
-          cat "$out/gitolite.rc.default" >>"$out/gitolite.rc"
-        ''
-        + lib.optionalString (cfg.extraGitoliteRc != "") ''
-          echo -n ${lib.escapeShellArg ''
-
-            # Added by NixOS:
-            ${lib.removeSuffix "\n" cfg.extraGitoliteRc}
-
-            # per perl rules, this should be the last line in such a file:
-            1;
-          ''} >>"$out/gitolite.rc"
-        '';
+      rcDirScript = ''
+        mkdir "$out"
+        export HOME=temp-home
+        mkdir -p "$HOME/.gitolite/logs" # gitolite can't run without it
+        '${pkgs.gitolite}'/bin/gitolite print-default-rc >>"$out/gitolite.rc.default"
+        cat <<END >>"$out/gitolite.rc"
+        # This file is managed by NixOS.
+        # Use services.gitolite options to control it.
+
+        END
+        cat "$out/gitolite.rc.default" >>"$out/gitolite.rc"
+      ''
+      + lib.optionalString (cfg.extraGitoliteRc != "") ''
+        echo -n ${lib.escapeShellArg ''
+
+          # Added by NixOS:
+          ${lib.removeSuffix "\n" cfg.extraGitoliteRc}
+
+          # per perl rules, this should be the last line in such a file:
+          1;
+        ''} >>"$out/gitolite.rc"
+      '';
 
     in
     {

@@ -111,8 +110,8 @@ in
         {
           directory = cfg.dataDir;
           mode = "0755";
-          user = cfg.user;
-          group = cfg.group;
+          inherit (cfg) user;
+          inherit (cfg) group;
         }
       ];
 

@@ -123,9 +122,14 @@ in
       users.users.${cfg.user} = {
         home = cfg.dataDir;
         uid = config.ids.uids.gitolite;
-        group = cfg.group;
+        inherit (cfg) group;
         extraGroups = [ "ssh" ];
         useDefaultShell = true;
+        packages = [
+          pkgs.gitolite
+          pkgs.git
+          pkgs.perl
+        ];
       };
 
       users.groups.${cfg.group}.gid = config.ids.gids.gitolite;

@@ -233,12 +237,6 @@ in
             gitolite setup # Upgrade if needed
           '';
       };
-
-      environment.systemPackages = [
-        pkgs.gitolite
-        pkgs.git
-        pkgs.perl
-      ];
     }
   );
 
diff --git a/config/nixos/modules/services/gotosocial.nix b/config/nixos/modules/services/gotosocial.nix
@@ -1,198 +0,0 @@
-{
-  povSelf,
-  config,
-  lib,
-  pkgs,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath povSelf config;
-  settingsFormat = pkgs.formats.json { };
-
-in
-{
-
-  options = {
-    enable = {
-      type = types.bool;
-      default = false;
-    };
-
-    package = {
-      type = types.package;
-      default = pkgs.gotosocial;
-    };
-
-    user = {
-      type = types.str;
-      default = "gotosocial";
-    };
-
-    group = {
-      type = types.str;
-      default = "gotosocial";
-    };
-
-    stateDir = {
-      type = types.str;
-      default = "/var/lib/gotosocial";
-      readOnly = true;
-    };
-
-    environmentFile = {
-      type = with types; nullOr path;
-      default = null;
-    };
-
-    settings = {
-      default = { };
-      description = ''
-        Configuration for GoToSocial, see
-        <link xlink:href="https://docs.gotosocial.org/en/latest/">
-        for supported values.
-      '';
-      type = types.submodule {
-        freeformType = settingsFormat.type;
-        options = {
-          host = lib.mkOption {
-            type = lib.types.nullOr lib.types.str;
-            default = null;
-            description = ''
-              Hostname that this server will be reachable at. Defaults to localhost for local testing,
-              but you should *definitely* change this when running for real, or your server won't work at all.
-              DO NOT change this after your server has already run once, or you will break things!
-            '';
-          };
-          port = lib.mkOption {
-            type = lib.types.port;
-            default = 8080;
-            description = ''
-              Int. Listen port for the GoToSocial webserver + API. If you're running behind a reverse proxy and/or in a docker,
-              container, just set this to whatever you like (or leave the default), and make sure it's forwarded properly.
-              If you are running with built-in letsencrypt enabled, and running GoToSocial directly on a host machine, you will
-              probably want to set this to 443 (standard https port), unless you have other services already using that port.
-              This *MUST NOT* be the same as the letsencrypt port specified below, unless letsencrypt is turned off.
-            '';
-          };
-        };
-      };
-    };
-  };
-
-  config = lib.mkIf cfg.enable (
-    let
-      configFile = settingsFormat.generate "gotosocial-config.yaml" cfg.settings;
-    in
-    {
-      assertions = [
-        {
-          assertion = cfg.settings.host != null;
-          message = "You have to define a hostname for GoToSocial, it cannot be changed later without starting over!";
-        }
-      ];
-
-      modules.filesystem.impermanence.system.dirs = [
-        {
-          directory = cfg.stateDir;
-          mode = "0755";
-          user = cfg.user;
-          group = cfg.group;
-        }
-      ];
-
-      modules.services.gotosocial.settings = {
-        # Defaults
-        user = lib.mkDefault cfg.user;
-        group = lib.mkDefault cfg.group;
-
-        storage-local-base-path = lib.mkDefault cfg.stateDir;
-
-        web-template-base-dir = lib.mkDefault "${cfg.package}/share/web/template/";
-        web-asset-base-dir = lib.mkDefault "${cfg.package}/share/web/assets/";
-      };
-
-      users = {
-        users."${cfg.user}" = {
-          home = cfg.stateDir;
-          group = cfg.group;
-          isSystemUser = true;
-        };
-        groups."${cfg.group}" = { };
-      };
-
-      environment.etc."gotosocial.yaml".source = configFile;
-
-      environment.systemPackages = [
-        (pkgs.writeShellScriptBin "gotosocial" ''
-          exec ${cfg.package}/bin/gotosocial --config-path ${configFile} "$@"
-        '')
-      ];
-
-      systemd.services = {
-        gotosocial = {
-          description = "GoToSocial ActivityPub Server";
-          wants = [ "network-online.target" ];
-          after = [
-            "network-online.target"
-            "sops-install-secrets.service"
-          ];
-          wantedBy = [ "multi-user.target" ];
-          environment = {
-            GTS_WAZERO_COMPILATION_CACHE = "${cfg.stateDir}/.cache";
-          };
-
-          serviceConfig = {
-            User = cfg.user;
-            Group = cfg.group;
-
-            Type = "exec";
-            WorkingDirectory = "~";
-            StateDirectory = lib.mkIf (
-              cfg.settings.storage-local-base-path != "/var/lib/gotosocial"
-            ) "gotosocial";
-            ReadOnlyPaths = [ cfg.package ];
-            ReadWritePaths = [ cfg.settings.storage-local-base-path ];
-            StateDirectoryMode = "750";
-
-            Restart = "always";
-            RestartSec = 3;
-
-            EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
-            ExecStart = "${cfg.package}/bin/gotosocial --config-path ${configFile} server start";
-
-            NoNewPrivileges = true;
-            PrivateTmp = true;
-            PrivateDevices = false;
-
-            RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
-            RestrictNamespaces = true;
-            RestrictRealtime = true;
-
-            ProtectSystem = "full";
-            ProtectControlGroups = true;
-            ProtectKernelModules = true;
-            ProtectKernelTunables = true;
-
-            DevicePolicy = "closed";
-            LockPersonality = true;
-            SystemCallFilter = "~@clock @debug @module @mount @obsolete @reboot @setuid @swap";
-
-            CapabilityBoundingSet = [
-              "~CAP_RAWIO CAP_MKNOD"
-              "~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE"
-              "~CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT"
-              "~CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK"
-              "~CAP_BLOCK_SUSPEND CAP_WAKE_ALARM"
-              "~CAP_SYS_TTY_CONFIG"
-              "~CAP_MAC_ADMIN CAP_MAC_OVERRIDE"
-              "~CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW"
-              "~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG"
-            ];
-          };
-        };
-      };
-    }
-  );
-
-}
diff --git a/config/nixos/modules/services/greetd.nix b/config/nixos/modules/services/greetd.nix
@@ -0,0 +1,169 @@
+{
+  config,
+  lib,
+  pkgs,
+  povSelf,
+  ...
+}:
+
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options = {
+    enable = {
+      type = types.bool;
+      default = false;
+    };
+    greeter = {
+      type = types.enum [
+        "regreet"
+        "tuigreet"
+      ];
+      default = "tuigreet";
+    };
+    autoLogin = {
+      enable = {
+        type = types.bool;
+        default = false;
+      };
+      user.type = types.str;
+      command.type = types.str;
+    };
+  };
+
+  config = lib.mkIf cfg.enable (
+    lib.mkMerge [
+      {
+        security.pam.services.greetd = {
+          fprintAuth = false; # This would break gnome-keyring auto unlocking
+          fprintAuthSkipLidClose = false;
+          #enableGnomeKeyring = true;
+        };
+
+        services.greetd = {
+          enable = true;
+          settings = {
+            default_session.user = "greeter";
+          };
+        };
+      }
+      (lib.mkIf cfg.autoLogin.enable {
+        services.greetd.settings = {
+          initial_session = {
+            inherit (cfg.autoLogin) user command;
+          };
+        };
+      })
+      (lib.mkIf (cfg.greeter == "regreet") {
+        modules.filesystem.impermanence.system.dirs = [
+          {
+            directory = "/var/cache/regreet";
+            mode = "755";
+            user = "greeter";
+            group = "greeter";
+          }
+        ];
+
+        systemd.tmpfiles.settings."greetd" = {
+          "/var/cache/regreet" = {
+            d = {
+              mode = "755";
+              user = "greeter";
+              group = "greeter";
+            };
+          };
+        };
+
+        programs.regreet = {
+          enable = true;
+          cageArgs = [ ];
+          settings = {
+            env = {
+              XKB_DEFAULT_LAYOUT = "gb";
+              XKB_DEFAULT_VARIANT = "colemak_dh";
+            };
+            GTK = {
+              # Whether to use the dark theme
+              application_prefer_dark_theme = lib.mkForce true;
+            };
+
+            commands = {
+              # The command used to reboot the system
+              reboot = [
+                "systemctl"
+                "reboot"
+              ];
+
+              # The command used to shut down the system
+              poweroff = [
+                "systemctl"
+                "poweroff"
+              ];
+            };
+
+            appearance = {
+              # The message that initially displays on startup
+              greeting_msg = "Welcome back to ${config.networking.hostName}!";
+            };
+          };
+        };
+
+        services.greetd = {
+          enable = true;
+          settings = {
+            default_session = {
+              #command = ''
+              #  ${pkgs.sway}/bin/sway --config ${swayConfig}
+              #'';
+              user = "greeter";
+            };
+          };
+        };
+
+      })
+      (lib.mkIf (cfg.greeter == "tuigreet") {
+        modules.filesystem.impermanence.system.dirs = [
+          {
+            directory = "/var/cache/tuigreet";
+            mode = "755";
+            user = "greeter";
+            group = "greeter";
+          }
+        ];
+
+        systemd.tmpfiles.settings."greetd" = {
+          "/var/cache/tuigreet" = {
+            d = {
+              mode = "755";
+              user = "greeter";
+              group = "greeter";
+            };
+          };
+        };
+
+        services.greetd.settings = {
+          default_session = {
+            command = lib.concatStringsSep " " [
+              (lib.getExe pkgs.greetd.tuigreet)
+              "--no-xsession-wrapper"
+              "--remember"
+              "--remember-session"
+              "--time"
+              "--user-menu"
+              "--asterisks"
+              "--power-shutdown"
+              "'systemctl poweroff'"
+              "--power-reboot"
+              "'systemctl reboot'"
+            ];
+          };
+        };
+      })
+    ]
+  );
+
+}
diff --git a/config/nixos/modules/services/gtklock.nix b/config/nixos/modules/services/gtklock.nix
@@ -0,0 +1,46 @@
+{
+  povSelf,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    security.pam.services.gtklock = { };
+
+    services.systemd-lock-handler.enable = true;
+
+    home-manager.sharedModules = [
+      {
+        systemd.user.services = {
+          gtklock = lib.mkDefault {
+            Unit = {
+              OnSuccess = [ "unlock.target" ];
+              PartOf = [ "lock.target" ];
+              After = [ "lock.target" ];
+            };
+            Install.WantedBy = [ "lock.target" ];
+            Service = {
+              ExecStart = lib.getExe pkgs.gtklock;
+              Restart = "on-failure";
+              RestartSec = 0;
+            };
+          };
+        };
+      }
+    ];
+  };
+
+}
diff --git a/config/nixos/modules/services/gvfs.nix b/config/nixos/modules/services/gvfs.nix
@@ -0,0 +1,62 @@
+{
+  povSelf,
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options = {
+    enable = {
+      type = types.bool;
+      default = false;
+    };
+    backends = {
+      afc = {
+        type = types.bool;
+        default = false;
+      };
+      afp = {
+        type = types.bool;
+        default = false;
+      };
+      mtp = {
+        type = types.bool;
+        default = false;
+      };
+      gphoto2 = {
+        type = types.bool;
+        default = false;
+      };
+      smb = {
+        type = types.bool;
+        default = false;
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    services.gvfs = {
+      enable = true;
+      package =
+        (pkgs.gvfs.overrideAttrs (old: {
+          mesonFlags = (old.mesonFlags or [ ]) ++ [
+            "-Dafp=${lib.boolToString cfg.backends.afp}"
+            "-Dafc=${lib.boolToString cfg.backends.afc}"
+            "-Dmtp=${lib.boolToString cfg.backends.mtp}"
+            "-Dgphoto2=${lib.boolToString cfg.backends.gphoto2}"
+          ];
+        })).override
+          {
+            samba = null;
+          };
+    };
+  };
+
+}
diff --git a/config/nixos/modules/services/keyd.nix b/config/nixos/modules/services/keyd.nix
@@ -4,6 +4,7 @@
   lib,
   ...
 }:
+
 let
   inherit (lib) types;
   cfg = lib.getAttrFromPath povSelf config;

@@ -20,14 +21,20 @@ in
     services.keyd = {
       enable = true;
       keyboards = {
-        seifenkiste = {
+        huntii = {
           ids = [ "0001:0001:70533846" ];
-          settings.main = {
-            "leftcontrol" = "leftalt";
-            "leftalt" = "leftcontrol";
-            "rightalt" = "rightcontrol";
-            "sysrq" = "rightalt";
-            "rightcontrol" = "sysrq";
+          settings = {
+            main = {
+              "leftcontrol" = "leftalt";
+              "leftalt" = "leftcontrol";
+              "rightalt" = "rightcontrol";
+              "sysrq" = "rightalt";
+              "rightcontrol" = "sysrq";
+              "s+d" = "oneshot(shift)";
+              "f+j" = "space";
+              "j+k" = "backspace";
+              "k+l" = "enter";
+            };
           };
         };
         lenovoKeyboard = {

@@ -43,6 +50,13 @@ in
             "rightcontrol" = "sysrq";
           };
         };
+        BlackShark = {
+          ids = [ "0c45:8006:d510c59d" ];
+          settings.main = {
+            "leftcontrol" = "leftalt";
+            "leftalt" = "leftcontrol";
+          };
+        };
       };
     };
   };
diff --git a/config/nixos/modules/services/knot.nix b/config/nixos/modules/services/knot.nix
@@ -13,17 +13,16 @@ let
 
   dnsServerAddresses =
     isPrimary:
-    lib.flatten (
-      inputs.self.nixosConfigurations
-      |> lib.filterAttrs (
-        hostName: hostConfig:
+    (lib.pipe inputs.self.nixosConfigurations [
+      (lib.filterAttrs (
+        _hostName: hostConfig:
         let
           cfgModule = lib.getAttrFromPath povSelf hostConfig.config;
         in
-        (cfgModule.enable && cfgModule.primary == isPrimary)
-      )
-      |> lib.mapAttrsToList (
-        hostName: hostConfig: [
+        cfgModule.enable && cfgModule.primary == isPrimary
+      ))
+      (lib.mapAttrsToList (
+        hostName: _hostConfig: [
           (lib.mkIf (inputs.self.hosts."${hostName}".networking.ip6Address != "")
             inputs.self.hosts."${hostName}".networking.ip6Address
           )

@@ -31,20 +30,20 @@ let
             inputs.self.hosts."${hostName}".networking.ip4Address
           )
         ]
-      )
-    );
+      ))
+      lib.flatten
+    ]);
 
-  dnsServerSecondaries = (
-    inputs.self.nixosConfigurations
-    |> lib.filterAttrs (
-      hostName: hostConfig:
+  dnsServerSecondaries = lib.pipe inputs.self.nixosConfigurations [
+    (lib.filterAttrs (
+      _hostName: hostConfig:
       let
         cfgModule = lib.getAttrFromPath povSelf hostConfig.config;
       in
-      (cfgModule.enable && !cfgModule.primary)
-    )
-    |> lib.mapAttrs (
-      hostName: hostConfig: {
+      cfgModule.enable && !cfgModule.primary
+    ))
+    (lib.mapAttrs (
+      hostName: _hostConfig: {
         address = [
           (lib.mkIf (inputs.self.hosts."${hostName}".networking.ip6Address != "")
             inputs.self.hosts."${hostName}".networking.ip6Address

@@ -54,8 +53,8 @@ let
           )
         ];
       }
-    )
-  );
+    ))
+  ];
 
 in
 {

@@ -82,12 +81,12 @@ in
     };
 
     zones = {
-      type = (pkgs.formats.yaml { }).type;
+      inherit ((pkgs.formats.yaml { })) type;
       default = { };
     };
 
     extraACL = {
-      type = (pkgs.formats.yaml { }).type;
+      inherit ((pkgs.formats.yaml { })) type;
       default = { };
     };
   };

@@ -96,10 +95,15 @@ in
     networking.firewall.allowedTCPPorts = [ 53 ];
     networking.firewall.allowedUDPPorts = [ 53 ];
 
+    users = {
+      users.knot.uid = 553;
+      groups.knot.gid = 553;
+    };
+
     modules.filesystem.impermanence.system.dirs = [
       {
         directory = cfg.dataDir;
-        mode = "0770";
+        mode = "770";
         user = "knot";
         group = "knot";
       }

@@ -139,7 +143,8 @@ in
 
           remote = {
             primary.address = primaryAddresses;
-          } // secondaries;
+          }
+          // secondaries;
 
           acl = {
             allowTransfer = lib.mkIf (secondaryAddresses != [ ]) {

@@ -149,7 +154,8 @@ in
 
             allowNotify.address = primaryAddresses;
             allowNotify.action = "notify";
-          } // cfg.extraACL;
+          }
+          // cfg.extraACL;
 
           template =
             let

@@ -202,7 +208,7 @@ in
                 }
             )
             // (lib.mapAttrs (
-              name: zone:
+              _name: zone:
               zone
               // {
                 template = "nixZone";
diff --git a/config/nixos/modules/services/knotACME.nix b/config/nixos/modules/services/knotACME.nix
@@ -37,53 +37,52 @@ in
     let
       generateACMERecord = recordName: ((builtins.hashString "sha1" recordName) + ".${cfg.zone}.");
 
-      nodesWithACMERecords = (
-        inputs.self.zaphyraHosts
-        |> lib.filterAttrs (hostName: nodeCfg: nodeCfg.config.security.acme.certs != { })
-      );
+      nodesWithACMERecords = lib.filterAttrs (
+        _hostName: nodeCfg: nodeCfg.config.security.acme.certs != { }
+      ) inputs.self.zaphyraHosts;
 
       getAllDomainsPerNode =
         hostName:
-        (
-          inputs.self.nixosConfigurations.${hostName}.config.security.acme.certs
-          |> lib.mapAttrsToList (domain: cfg: [ domain ] ++ cfg.extraDomainNames)
-          |> lib.flatten
-        );
+        (lib.pipe inputs.self.nixosConfigurations.${hostName}.config.security.acme.certs [
+          (lib.mapAttrsToList (domain: cfg: [ domain ] ++ cfg.extraDomainNames))
+          lib.flatten
+        ]);
 
       getACMERecordsPerNode =
         hostName:
-        (hostName |> getAllDomainsPerNode |> builtins.map (recordName: (generateACMERecord recordName)));
+        lib.pipe hostName [
+          getAllDomainsPerNode
+          (builtins.map (recordName: (generateACMERecord recordName)))
+        ];
 
       generateACMERecordsPerZone =
         zoneName:
-        (
-          nodesWithACMERecords
-          |> lib.mapAttrsToList (hostName: _: (getAllDomainsPerNode hostName))
-          |> lib.flatten
-          |> builtins.filter (lib.hasSuffix zoneName)
-          |> builtins.map (recordName: {
+        (lib.pipe nodesWithACMERecords [
+          (lib.mapAttrsToList (hostName: _: (getAllDomainsPerNode hostName)))
+          lib.flatten
+          (builtins.filter (lib.hasSuffix zoneName))
+          (builtins.map (recordName: {
             name = "_acme-challenge${
               if zoneName != recordName then "." else ""
             }${lib.removeSuffix "${if zoneName != recordName then "." else ""}${zoneName}" recordName}";
             value = {
               CNAME = [ (generateACMERecord recordName) ];
             };
-          })
-          |> builtins.listToAttrs
-        );
+          }))
+          builtins.listToAttrs
+        ]);
 
     in
     {
-      dns.allZones = (
-        cfg.zones
-        |> lib.map (
+      dns.allZones = lib.pipe cfg.zones [
+        (lib.map (
           element:
           lib.nameValuePair element {
             subdomains = generateACMERecordsPerZone element;
           }
-        )
-        |> lib.listToAttrs
-      );
+        ))
+        lib.listToAttrs
+      ];
 
       systemd.services.knot =
         let

@@ -139,25 +138,20 @@ in
             journal-content = "all";
 
             acl = lib.mkIf ((lib.attrNames nodesWithACMERecords) != [ ]) (
-              nodesWithACMERecords |> lib.mapAttrsToList (hostName: _: "acme-nix-${hostName}")
+              lib.mapAttrsToList (hostName: _: "acme-nix-${hostName}") nodesWithACMERecords
             );
           };
         };
-        extraACL = (
-          nodesWithACMERecords
-          |> lib.mapAttrs' (
-            hostName: _: {
-              name = "acme-nix-${hostName}";
-              value = {
-                key = [ "acme-nix-${hostName}" ];
-                action = "update";
-                update-owner = "name";
-                update-owner-match = "equal";
-                update-owner-name = getACMERecordsPerNode hostName;
-              };
-            }
-          )
-        );
+        extraACL = lib.mapAttrs' (hostName: _: {
+          name = "acme-nix-${hostName}";
+          value = {
+            key = [ "acme-nix-${hostName}" ];
+            action = "update";
+            update-owner = "name";
+            update-owner-match = "equal";
+            update-owner-name = getACMERecordsPerNode hostName;
+          };
+        }) nodesWithACMERecords;
       };
     }
   );
diff --git a/config/nixos/modules/services/mautrixBridge.nix b/config/nixos/modules/services/mautrixBridge.nix
@@ -1,156 +0,0 @@
-{
-  povSelf,
-  config,
-  lib,
-  pkgs,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath povSelf config;
-  forEachInstance =
-    f: lib.flip lib.mapAttrs' cfg (name: cfg: lib.nameValuePair "mautrixBridge-${name}" (f name cfg));
-
-in
-{
-
-  option = {
-    default = { };
-    type = types.attrsOf (
-      types.submodule ({
-        options = {
-          enable = lib.mkOption {
-            type = types.bool;
-            default = false;
-          };
-          package = lib.mkOption {
-            type = types.package;
-          };
-          settings = lib.mkOption {
-            type = (pkgs.formats.json { }).type;
-            default = { };
-          };
-          environmentFile = lib.mkOption {
-            type = with types; nullOr path;
-            default = null;
-          };
-          serviceDependencies = lib.mkOption {
-            type = with types; listOf str;
-            default = [ ];
-          };
-        };
-      })
-    );
-  };
-
-  config = {
-    modules.filesystem.impermanence.system.dirs = (
-      (lib.attrNames cfg) |> lib.map (element: "/var/lib/private/mautrix-${element}")
-    );
-
-    systemd.services = forEachInstance (
-      name: cfg:
-      let
-        dataDir = "/var/lib/mautrix-${name}";
-        registrationFile = "${dataDir}/registration.yaml";
-        settingsFile = "${dataDir}/config.yaml";
-        settingsFileUnsubstituted =
-          (pkgs.formats.json { }).generate "mautrix-${name}-config-unsubstituted.json"
-            cfg.settings;
-      in
-      {
-        enable = cfg.enable;
-        description = "mautrixBridge-${name}, a matrix puppeting bridge.";
-        restartTriggers = [ settingsFileUnsubstituted ];
-
-        wantedBy = [ "multi-user.target" ];
-        wants = [ "network-online.target" ] ++ cfg.serviceDependencies;
-        after = [ "network-online.target" ] ++ cfg.serviceDependencies;
-
-        path = [ pkgs.ffmpeg-headless ];
-
-        preStart = ''
-          # substitute the settings file by environment variables
-          # in this case read from EnvironmentFile
-          test -f '${settingsFile}' && rm -f '${settingsFile}'
-          old_umask=$(umask)
-          umask 0177
-          ${pkgs.envsubst}/bin/envsubst \
-            -o '${settingsFile}' \
-            -i '${settingsFileUnsubstituted}'
-          umask $old_umask
-
-          # generate the appservice's registration file if absent
-          if [ ! -f '${registrationFile}' ]; then
-            ${lib.getExe cfg.package} \
-              --generate-registration \
-              --config='${settingsFile}' \
-              --registration='${registrationFile}'
-          fi
-          chmod 640 ${registrationFile}
-
-          umask 0177
-          ${pkgs.yq}/bin/yq -s '
-              .[0].appservice.as_token = (.[0].appservice.as_token // .[1].as_token)
-            | .[0].appservice.hs_token = (.[0].appservice.hs_token // .[1].hs_token)
-          ${lib.optionalString (
-            name == "telegram"
-          ) "
-          | .[0].network.api_id = (.[0].network.api_id | tonumber)
-        "}
-            | .[0]' \
-            '${settingsFile}' '${registrationFile}' > '${settingsFile}.tmp'
-          mv '${settingsFile}.tmp' '${settingsFile}'
-          umask $old_umask
-        '';
-
-        serviceConfig = {
-          Type = "exec";
-
-          DynamicUser = true;
-          User = "mautrixBridge-${name}";
-          Group = "mautrixBridge-${name}";
-
-          EnvironmentFile = cfg.environmentFile;
-          StateDirectory = baseNameOf dataDir;
-          WorkingDirectory = dataDir;
-          UMask = 27;
-
-          ExecStart = ''
-            ${lib.getExe cfg.package} \
-            --no-update \
-            --config='${settingsFile}'
-          '';
-
-          Restart = "on-failure";
-          RestartSec = "30s";
-
-          LockPersonality = true;
-          NoNewPrivileges = true;
-          MemoryDenyWriteExecute = lib.mkIf (name != "signal") true;
-
-          PrivateDevices = true;
-          PrivateTmp = true;
-          PrivateUsers = true;
-
-          ProtectSystem = "strict";
-          ProtectClock = true;
-          ProtectHome = true;
-          ProtectHostname = true;
-          ProtectKernelLogs = true;
-          ProtectKernelModules = true;
-          ProtectKernelTunables = true;
-          ProtectControlGroups = true;
-
-          RestrictRealtime = true;
-          RestrictSUIDSGID = true;
-
-          SystemCallArchitectures = "native";
-          SystemCallErrorNumber = "EPERM";
-          SystemCallFilter = [ "@system-service" ];
-        };
-      }
-    );
-  };
-
-}
diff --git a/config/nixos/modules/services/openssh.nix b/config/nixos/modules/services/openssh.nix
@@ -36,6 +36,10 @@ in
       };
     };
 
+    systemd.services.sops-install-secrets.after =
+      lib.mkIf config.modules.filesystem.impermanence.system.enable
+        [ "nix-persist.mount" ];
+
     # this is required because the secrets need to be decryped before the users get created
     # but the impermanence bind-mounts get created _after_ the user creation...
     sops.age.sshKeyPaths = [
diff --git a/config/nixos/modules/services/power-profiles-daemon.nix b/config/nixos/modules/services/power-profiles-daemon.nix
@@ -0,0 +1,27 @@
+{
+  povSelf,
+  config,
+  lib,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    modules.filesystem.impermanence.system.dirs = [
+      "/var/lib/power-profiles-daemon"
+    ];
+
+    services.power-profiles-daemon.enable = true;
+  };
+
+}
diff --git a/config/nixos/modules/services/prosody.nix b/config/nixos/modules/services/prosody.nix
@@ -0,0 +1,156 @@
+{
+  povSelf,
+  config,
+  lib,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options = {
+    enable = {
+      type = types.bool;
+      default = false;
+    };
+    domain = {
+      type = types.str;
+    };
+    adminUsers = {
+      type = with types; listOf str;
+      default = [ ];
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    dns.zones."${cfg.domain}" = {
+      SRV = [
+        {
+          proto = "tcp";
+          service = "xmpp-server";
+          priority = 0;
+          weight = 5;
+          port = 5269;
+          target = "xmpp.${cfg.domain}.";
+        }
+        {
+          proto = "tcp";
+          service = "xmpp-client";
+          priority = 0;
+          weight = 5;
+          port = 5222;
+          target = "xmpp.${cfg.domain}.";
+        }
+      ];
+      subdomains = {
+        "muc.xmpp".SRV = [
+          {
+            proto = "tcp";
+            service = "xmpp-server";
+            priority = 0;
+            weight = 5;
+            port = 5269;
+            target = "xmpp.${cfg.domain}.";
+          }
+        ];
+        "upload.xmpp".CNAME = [ "${config.networking.fqdn}." ];
+        xmpp.CNAME = [ "${config.networking.fqdn}." ];
+      };
+    };
+
+    networking.firewall.allowedTCPPorts = [
+      5269
+      5222
+    ]
+    ++ config.services.prosody.httpsPorts;
+
+    modules.filesystem.impermanence.system.dirs = [
+      {
+        directory = config.services.prosody.dataDir;
+        mode = "755";
+        inherit (config.services.prosody) user;
+        inherit (config.services.prosody) group;
+      }
+    ];
+
+    security.acme.certs."${cfg.domain}" = {
+      inherit (config.services.prosody) group;
+      reloadServices = [ "prosody.service" ];
+      extraDomainNames = [
+        "xmpp.${cfg.domain}"
+        "muc.xmpp.${cfg.domain}"
+        "upload.xmpp.${cfg.domain}"
+      ];
+    };
+
+    services.prosody = {
+      enable = true;
+
+      allowRegistration = false;
+      authentication = "internal_hashed";
+      admins = cfg.adminUsers;
+
+      # c2sRequireEncryption = true;
+      # s2sSecureAuth = true;
+
+      modules = {
+        disco = true; # Service discovery
+        roster = true; # Allow users to have a roster. Recommended ;)
+        saslauth = true; # Authentication for clients and servers. Recommended if you want to log in.
+        tls = true; # Add support for secure TLS on c2s/s2s connections
+        blocklist = true; # Allow users to block communications with other users
+        bookmarks = true; # Synchronise the list of open rooms between clients
+        carbons = true; # Keep multiple online clients in sync
+        dialback = true; # Support for verifying remote servers using DNS
+        limits = true; # Enable bandwidth limiting for XMPP connections
+        pep = true; # Allow users to store public and private data in their account
+        private = true; # Private XML storage (for room bookmarks, etc.)
+        smacks = true; # Allow a client to resume a disconnected session, and prevent message loss
+        vcard = true; # User profiles (stored in PEP)
+        vcard_legacy = true; # Conversion between legacy vCard and PEP Avatar, vcard
+        csi = true; # Allows clients to report their active/inactive state
+        ping = true; # Replies to XMPP pings with pongs
+        register = true; # Allow users to register on this server using a client and change passwords
+        time = true; # Let others know the time here on this server
+        uptime = true; # Report how long server has been running
+        version = true; # Replies to server version requests
+        mam = true; # Store recent messages to allow multi-device synchronization
+      };
+
+      extraModules = [
+        "admin_adhoc" # Allows administration via an XMPP client that supports ad-hoc commands
+        "admin_shell" # Allow secure administration via 'prosodyctl shell'
+        "invites" # Create and manage invites
+        "invites_adhoc" # Allow admins/users to create invitations via their client
+        "invites_register" # Allows invited users to create accounts
+      ];
+
+      httpsPorts = [ 5281 ];
+      httpFileShare.domain = "upload.xmpp.${cfg.domain}";
+
+      ssl.cert = "${config.security.acme.certs."${cfg.domain}".directory}/fullchain.pem";
+      ssl.key = "${config.security.acme.certs."${cfg.domain}".directory}/key.pem";
+
+      virtualHosts = {
+        zaphyra = rec {
+          enabled = true;
+          domain = "zaphyra.eu";
+          ssl.cert = "${config.security.acme.certs."${domain}".directory}/fullchain.pem";
+          ssl.key = "${config.security.acme.certs."${domain}".directory}/key.pem";
+        };
+      };
+      muc = [
+        {
+          domain = "muc.xmpp.${cfg.domain}";
+          name = "zaphyra Chat";
+          restrictRoomCreation = "local";
+        }
+      ];
+    };
+  };
+
+}
diff --git a/config/nixos/modules/services/rcloneResticServer.nix b/config/nixos/modules/services/rcloneResticServer.nix
@@ -77,14 +77,13 @@ in
       virtualHosts."${cfg.nginx.domain}" = {
         locations."/" = {
           proxyPass = "http://[::1]:${toString cfg.port}/";
-          extraConfig =
-            ''
-              client_max_body_size 10G;
-            ''
-            + lib.optionalString (cfg.nginx.basicAuthFile != null) ''
-              auth_basic           Auth;
-              auth_basic_user_file ${cfg.nginx.basicAuthFile};
-            '';
+          extraConfig = ''
+            client_max_body_size 10G;
+          ''
+          + lib.optionalString (cfg.nginx.basicAuthFile != null) ''
+            auth_basic           Auth;
+            auth_basic_user_file ${cfg.nginx.basicAuthFile};
+          '';
         };
       };
     };
diff --git a/config/nixos/modules/services/resticBackup.nix b/config/nixos/modules/services/resticBackup.nix
@@ -89,110 +89,98 @@ in
 
   config = lib.mkIf (cfg.paths != { }) {
 
-    systemd.services = (
-      cfg.paths
-      |> lib.attrsToList
-      |> lib.map (
+    systemd.services = lib.pipe cfg.paths [
+      lib.attrsToList
+      (lib.map (
         element:
         (
           if element.value.enable then
-            (
-              element.value.targets
-              |> lib.map (
-                target:
-                lib.nameValuePair "restic-backups-${element.name}-${target}" {
-                  serviceConfig.EnvironmentFile =
-                    [
-                      cfg.targets."${target}".environmentFile
-                    ]
-                    ++ (lib.optionals (element.value.environmentFile != null) [
-                      element.value.environmentFile
-                    ]);
-                }
-              )
-            )
+            (lib.map (
+              target:
+              lib.nameValuePair "restic-backups-${element.name}-${target}" {
+                serviceConfig.EnvironmentFile = [
+                  cfg.targets."${target}".environmentFile
+                ]
+                ++ (lib.optionals (element.value.environmentFile != null) [
+                  element.value.environmentFile
+                ]);
+              }
+            ) element.value.targets)
           else
             [ ]
         )
-      )
-      |> lib.flatten
-      |> lib.listToAttrs
-    );
+      ))
+      lib.flatten
+      lib.listToAttrs
+    ];
 
-    services.restic.backups = (
-      cfg.paths
-      |> lib.attrsToList
-      |> lib.map (
+    services.restic.backups = lib.pipe cfg.paths [
+      lib.attrsToList
+      (lib.map (
         element:
         (
           if element.value.enable then
-            (
-              element.value.targets
-              |> lib.map (
-                target:
-                lib.nameValuePair "${element.name}-${target}" {
-                  initialize = true;
-                  user = element.value.user;
-                  passwordFile = element.value.passwordFile;
-                  timerConfig = element.value.timerConfig;
-                  repository = cfg.targets."${target}".repository + "/${config.networking.hostName}-${element.name}";
-                  paths = lib.mkMerge [
-                    element.value.paths
-                    (lib.mkIf (element.value.postgresDatabases != [ ]) (
-                      lib.map (element: "/tmp/postgresDatabases/${element}.sql.zst") element.value.postgresDatabases
+            (lib.map (
+              target:
+              lib.nameValuePair "${element.name}-${target}" {
+                initialize = true;
+                inherit (element.value) user passwordFile timerConfig;
+                repository = cfg.targets."${target}".repository + "/${config.networking.hostName}-${element.name}";
+                paths = lib.mkMerge [
+                  element.value.paths
+                  (lib.mkIf (element.value.postgresDatabases != [ ]) (
+                    lib.map (element: "/tmp/postgresDatabases/${element}.sql.zst") element.value.postgresDatabases
+                  ))
+                  (lib.mkIf (element.value.sqliteDatabases != [ ]) (
+                    lib.map (
+                      element: "/tmp/sqliteDatabases/${builtins.baseNameOf element}.sqlite"
+                    ) element.value.sqliteDatabases
+                  ))
+                  (lib.mkIf (element.value.influxBuckets != [ ]) (
+                    lib.map (element: "/tmp/influxBuckets/${element}") element.value.influxBuckets
+                  ))
+                ];
+                backupPrepareCommand =
+                  element.value.runBeforeBackup
+                  +
+                    #dump postgresql databases
+                    (lib.optionalString (element.value.postgresDatabases != [ ]) (
+                      lib.concatMapStringsSep "\n" (db: ''
+                        echo "Dumping Postgres-database: ${db}"
+                        mkdir -p /tmp/postgresDatabases
+                        pg_dump ${db} | zstd --rsyncable > /tmp/postgresDatabases/${db}.sql.zst
+                        [ $(du -b /tmp/postgresDatabases/${db}.sql.zst | cut -f1) -gt "50" ] || exit 1
+                      '') element.value.postgresDatabases
                     ))
-                    (lib.mkIf (element.value.sqliteDatabases != [ ]) (
-                      lib.map (
-                        element: "/tmp/sqliteDatabases/${builtins.baseNameOf element}.sqlite"
-                      ) element.value.sqliteDatabases
+                  +
+                    #dump sqlite databases
+                    (lib.optionalString (element.value.sqliteDatabases != [ ]) (
+                      lib.concatMapStringsSep "\n" (db: ''
+                        echo "Dumping sqlite-database: ${db}"
+                        mkdir -p /tmp/sqliteDatabases
+                        ${pkgs.sqlite}/bin/sqlite3 ${db} ".backup '/tmp/sqliteDatabases/${builtins.baseNameOf db}.sqlite'"
+                        [ $(du -b /tmp/sqliteDatabases/${builtins.baseNameOf db}.sqlite | cut -f1) -gt "50" ] || exit 1
+                      '') element.value.sqliteDatabases
                     ))
-                    (lib.mkIf (element.value.influxBuckets != [ ]) (
-                      lib.map (element: "/tmp/influxBuckets/${element}") element.value.influxBuckets
-                    ))
-                  ];
-                  backupPrepareCommand = (
-                    element.value.runBeforeBackup
-                    +
-                      #dump postgresql databases
-                      (lib.optionalString (element.value.postgresDatabases != [ ]) (
-                        lib.concatMapStringsSep "\n" (db: ''
-                          echo "Dumping Postgres-database: ${db}"
-                          mkdir -p /tmp/postgresDatabases
-                          pg_dump ${db} | zstd --rsyncable > /tmp/postgresDatabases/${db}.sql.zst
-                          [ $(du -b /tmp/postgresDatabases/${db}.sql.zst | cut -f1) -gt "50" ] || exit 1
-                        '') element.value.postgresDatabases
-                      ))
-                    +
-                      #dump sqlite databases
-                      (lib.optionalString (element.value.sqliteDatabases != [ ]) (
-                        lib.concatMapStringsSep "\n" (db: ''
-                          echo "Dumping sqlite-database: ${db}"
-                          mkdir -p /tmp/sqliteDatabases
-                          ${pkgs.sqlite}/bin/sqlite3 ${db} ".backup '/tmp/sqliteDatabases/${builtins.baseNameOf db}.sqlite'"
-                          [ $(du -b /tmp/sqliteDatabases/${builtins.baseNameOf db}.sqlite-backup | cut -f1) -gt "50" ] || exit 1
-                        '') element.value.sqliteDatabases
-                      ))
-                    +
-                      #dump influx buckets
-                      (lib.optionalString (element.value.influxBuckets != [ ]) (
-                        lib.concatMapStringsSep "\n" (db: ''
-                          echo "Dumping influx-bucket: ${db}"
-                          mkdir -p /tmp/influxBuckets
-                          ${pkgs.influxdb2}/bin/influx backup --compression=none --bucket=${db} /tmp/influxBuckets/${db}
-                          [ $(du -b /tmp/influxBuckets/${db} | cut -f1) -gt "50" ] || exit 1
-                        '') element.value.influxBuckets
-                      ))
-                  );
-                }
-              )
-            )
+                  +
+                    #dump influx buckets
+                    (lib.optionalString (element.value.influxBuckets != [ ]) (
+                      lib.concatMapStringsSep "\n" (db: ''
+                        echo "Dumping influx-bucket: ${db}"
+                        mkdir -p /tmp/influxBuckets
+                        ${pkgs.influxdb2}/bin/influx backup --compression=none --bucket=${db} /tmp/influxBuckets/${db}
+                        [ $(du -b /tmp/influxBuckets/${db} | cut -f1) -gt "50" ] || exit 1
+                      '') element.value.influxBuckets
+                    ));
+              }
+            ) element.value.targets)
           else
             [ ]
         )
-      )
-      |> lib.flatten
-      |> lib.listToAttrs
-    );
+      ))
+      lib.flatten
+      lib.listToAttrs
+    ];
   };
 
 }
diff --git a/config/nixos/modules/services/swaylock.nix b/config/nixos/modules/services/swaylock.nix
@@ -0,0 +1,47 @@
+{
+  povSelf,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    security.pam.services.swaylock = { };
+    security.pam.services.swaylock-plugin.fprintAuth = false;
+
+    services.systemd-lock-handler.enable = true;
+
+    home-manager.sharedModules = [
+      {
+        systemd.user.services = {
+          swaylock = lib.mkDefault {
+            Unit = {
+              OnSuccess = [ "unlock.target" ];
+              PartOf = [ "lock.target" ];
+              After = [ "lock.target" ];
+            };
+            Install.WantedBy = [ "lock.target" ];
+            Service = {
+              ExecStart = lib.getExe pkgs.swaylock;
+              Restart = "on-failure";
+              RestartSec = 0;
+            };
+          };
+        };
+      }
+    ];
+  };
+
+}
diff --git a/config/nixos/modules/services/udisks2.nix b/config/nixos/modules/services/udisks2.nix
@@ -0,0 +1,23 @@
+{
+  povSelf,
+  config,
+  lib,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    services.udisks2.enable = true;
+  };
+
+}
diff --git a/config/nixos/modules/services/upower.nix b/config/nixos/modules/services/upower.nix
@@ -0,0 +1,27 @@
+{
+  povSelf,
+  config,
+  lib,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    modules.filesystem.impermanence.system.dirs = [
+      "/var/lib/upower"
+    ];
+
+    services.upower.enable = true;
+  };
+
+}
diff --git a/config/nixos/modules/services/vnstat.nix b/config/nixos/modules/services/vnstat.nix
@@ -1,5 +1,4 @@
 {
-  inputs,
   povSelf,
   config,
   lib,
diff --git a/config/nixos/modules/sops.nix b/config/nixos/modules/sops.nix
@@ -3,7 +3,6 @@
   povSelf,
   config,
   lib,
-  pkgs,
   ...
 }:
 
diff --git a/config/nixos/modules/users/void.nix b/config/nixos/modules/users/void.nix
@@ -1,5 +1,4 @@
 {
-  inputs,
   povSelf,
   config,
   lib,

@@ -23,7 +22,7 @@ in
       {
         sops.secrets.voidPassword = {
           neededForUsers = true;
-          sopsFile = inputs.self.sopsSecrets.common;
+          #sopsFile = inputs.self.sopsSecrets.common;
         };
 
         users.users.void = {

@@ -37,6 +36,7 @@ in
             "docker"
             "input"
             "networkmanager"
+            "seat"
             "ssh"
             "tss"
             "video"

@@ -49,15 +49,18 @@ in
       }
 
       (lib.mkIf config.modules.homeManager.enable {
-        home-manager.users.void.imports = lib.concatLists [
-          [
-            homeManagerModules.void.home
-          ]
+        home-manager.users.void.imports =
+          with homeManagerModules.void;
+          lib.concatLists [
+            [
+              home
+              impermanence # FIXME
+            ]
 
-          (lib.optionals config.modules.filesystem.impermanence.home.enable [
-            #homeManagerModules.void.impermanence # FIXME: implement impermanence
-          ])
-        ];
+            (lib.optionals config.modules.filesystem.impermanence.home.enable [
+              homeManagerModules.void.impermanence # FIXME: implement impermanence
+            ])
+          ];
       })
     ]
   );
diff --git a/config/nixos/modules/users/zaphyra.nix b/config/nixos/modules/users/zaphyra.nix
@@ -32,12 +32,11 @@ in
           description = "Katja";
           hashedPasswordFile = config.sops.secrets.zaphyraPassword.path;
           isNormalUser = true;
-          extraGroups =
-            [
-              "ssh"
-              "wheel"
-              "networkmanager"
-            ];
+          extraGroups = [
+            "ssh"
+            "wheel"
+            "networkmanager"
+          ];
           openssh.authorizedKeys.keys = [
             (builtins.readFile "${pkgs.zaphyra-website}/ssh_pubkey.asc")
             "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPnNyOCX+PopTHuNrfBwEmPM7FC6oM7nFgW/2tvW7ddT"

@@ -48,6 +47,7 @@ in
       (lib.mkIf config.modules.homeManager.enable {
         home-manager.users.zaphyra.imports = lib.concatLists [
           [
+            homeManagerModules.common.home
             homeManagerModules.zaphyra.home
           ]
 

@@ -60,24 +60,38 @@ in
             [
               configure.xdg
 
+              services.owntone
+
               programs.ghostty
               programs.ssh
               programs.git
               programs.gpg
               homeManagerModules.common.programs.gpg
 
+              programs.languages.nix
+              programs.languages.nimlang
+              programs.languages.golang
+              programs.languages.javascript
+
               programs.yt-dlp
-              programs.phockup
               programs.bitwarden-cli
+              programs.chaosctl
 
-              programs.nautilus
+              programs.pipewire
 
               programs.firefox
               programs.thunderbird
+
               programs.errands
+              programs.gnome-calendar
 
               programs.fractal
+              programs.dino
+              programs.gajim
               programs.tuba
+              programs.profanity
+
+              programs.nautilus
 
               programs.typst
               programs.ocrmypdf

@@ -85,10 +99,12 @@ in
               programs.pdfarranger
               programs.libreoffice
               programs.apostrophe
+              programs.gnome-text-editor
 
+              programs.plattenalbum
               programs.celluloid
-
-              programs.javascript
+              programs.loupe
+              programs.gnome-obfuscate
             ]
           ))
 

@@ -106,6 +122,13 @@ in
               gnomeExtensions.bluetoothBatteryMeter
             ]
           ))
+
+          (lib.optionals (config.modules.presets.graphical.type == "niri") (
+            with homeManagerModules.zaphyra;
+            [
+              configure.niri
+            ]
+          ))
         ];
       })
     ]
diff --git a/config/nixos/modules/websites/bikemap.zaphyra.eu.nix b/config/nixos/modules/websites/bikemap.zaphyra.eu.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,

@@ -40,7 +39,7 @@ in
     {
       assertions = [
         {
-          assertion = config.modules.services.gitolite.enable == true;
+          assertion = config.modules.services.gitolite.enable;
           message = "The option 'modules.services.gitolite.enable' must be enabled in order to use this module.";
         }
       ];

@@ -52,13 +51,13 @@ in
           directory = "/var/lib/bikemap";
           mode = "0755";
           user = "bikemap";
-          group = config.modules.services.gitolite.group;
+          inherit (config.modules.services.gitolite) group;
         }
       ];
 
       users.users."bikemap" = {
         isSystemUser = true;
-        group = config.modules.services.gitolite.group;
+        inherit (config.modules.services.gitolite) group;
         createHome = true;
         homeMode = "755";
         home = "/var/lib/bikemap";
diff --git a/config/nixos/modules/websites/dav.zaphyra.eu.nix b/config/nixos/modules/websites/dav.zaphyra.eu.nix
@@ -1,8 +1,6 @@
 {
   povSelf,
-  hostConfig,
   config,
-  pkgs,
   lib,
   ...
 }:

@@ -32,6 +30,11 @@ in
   config = lib.mkIf cfg.enable {
     dns.zones."${cfg.domain}".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ];
 
+    users = {
+      users.radicale.uid = 234;
+      groups.radicale.gid = 234;
+    };
+
     modules.filesystem.impermanence.system.dirs = [
       {
         directory = "/var/lib/radicale";

@@ -67,9 +70,11 @@ in
           web.type = "internal";
           storage.filesystem_folder = "/var/lib/radicale";
           headers.Access-Control-Allow-Origin = "*";
-          auth.type = "htpasswd";
-          auth.htpasswd_filename = config.sops.secrets.radicaleUsers.path;
-          auth.htpasswd_encryption = "plain";
+          auth = {
+            type = "htpasswd";
+            htpasswd_filename = config.sops.secrets.radicaleUsers.path;
+            htpasswd_encryption = "plain";
+          };
         };
       };
       nginx = {
diff --git a/config/nixos/modules/websites/fedi.ctu.cx.nix b/config/nixos/modules/websites/fedi.ctu.cx.nix
@@ -1,7 +1,6 @@
 {
   name,
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,

@@ -21,25 +20,17 @@ in
       type = types.bool;
       default = false;
     };
-    domain = {
-      type = types.str;
-      default = "ctu.cx";
-    };
-    subdomain = {
-      type = types.str;
-      default = "fedi";
-    };
   };
 
   config = lib.mkIf cfg.enable {
     assertions = [
       {
-        assertion = cfgWebsites."${cfg.domain}".enable == true;
-        message = "The option 'modules.websites.\"${cfg.domain}\"' must be enabled in order to use this module.";
+        assertion = cfgWebsites."ctu.cx".enable;
+        message = "The option 'modules.websites.\"ctu.cx\"' must be enabled in order to use this module.";
       }
     ];
 
-    dns.zones."${cfg.domain}".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ];
+    dns.zones."ctu.cx".subdomains."fedi".CNAME = [ "${config.networking.fqdn}." ];
 
     systemd.services.gotosocial.after = [ "sops-install-secrets.service" ];
     sops.secrets = {

@@ -51,77 +42,88 @@ in
 
     systemd.tmpfiles.settings.gotosocial = {
       "/var/lib/gotosocial/storage".d = {
-        user = config.modules.services.gotosocial.user;
-        group = config.modules.services.gotosocial.group;
+        inherit (config.tgc.services.gotosocial) user;
+        inherit (config.tgc.services.gotosocial) group;
         mode = "750";
         age = "-";
       };
     };
 
-    modules.services = {
-      resticBackup.paths = {
+    modules = {
+      filesystem.impermanence.system.dirs = [
+        {
+          directory = config.tgc.services.gotosocial.stateDir;
+          mode = "0755";
+          inherit (config.tgc.services.gotosocial) user;
+          inherit (config.tgc.services.gotosocial) group;
+        }
+      ];
+
+      services.resticBackup.paths = {
         gotosocial = {
           enable = true;
-          user = config.modules.services.gotosocial.user;
+          inherit (config.tgc.services.gotosocial) user;
           passwordFile = config.sops.secrets."resticPasswords/gotosocial".path;
           sqliteDatabases = [
             (lib.mkIf (
-              config.modules.services.gotosocial.settings.db-type == "sqlite"
-            ) config.modules.services.gotosocial.settings.db-address)
+              config.tgc.services.gotosocial.settings.db-type == "sqlite"
+            ) config.tgc.services.gotosocial.settings.db-address)
           ];
           paths = [
             (lib.mkIf (
-              config.modules.services.gotosocial.settings.storage-backend == "local"
-            ) config.modules.services.gotosocial.settings.storage-local-base-path)
-            "${config.modules.services.gotosocial.stateDir}/backup.json"
+              config.tgc.services.gotosocial.settings.storage-backend == "local"
+            ) config.tgc.services.gotosocial.settings.storage-local-base-path)
+            "${config.tgc.services.gotosocial.stateDir}/backup.json"
           ];
-          runBeforeBackup = ''${pkgs.gotosocial}/bin/gotosocial --config-path /etc/gotosocial.yaml admin export --path ${config.modules.services.gotosocial.stateDir}/backup.json'';
+          runBeforeBackup = ''${config.tgc.services.gotosocial.package}/bin/gotosocial --config-path /etc/gotosocial.yaml admin export --path ${config.tgc.services.gotosocial.stateDir}/backup.json'';
         };
       };
-      gotosocial = {
-        enable = true;
-        group = config.services.nginx.group;
-        environmentFile = config.sops.secrets."environments/gotosocial".path;
-        settings = {
-          protocol = lib.mkDefault "https";
-
-          bind-address = lib.mkDefault "[::1]";
-          port = lib.mkDefault 8085;
-
-          trusted-proxies = lib.mkDefault [
-            "::1/128"
-            "172.17.0.0/24"
-          ];
+    };
 
-          db-type = lib.mkDefault "sqlite";
-          db-address = lib.mkDefault "${config.modules.services.gotosocial.stateDir}/db.sqlite";
+    tgc.services.gotosocial = {
+      enable = true;
+      package = pkgs.tgc.gotosocial-unstable;
+      inherit (config.services.nginx) group;
+      environmentFile = config.sops.secrets."environments/gotosocial".path;
+      settings = {
+        protocol = "https";
 
-          storage-backend = lib.mkDefault "local";
-          storage-local-base-path = "${config.modules.services.gotosocial.stateDir}/storage";
+        bind-address = "::1";
+        port = 8085;
 
-          host = "${cfg.subdomain}.${cfg.domain}";
-          account-domain = cfg.domain;
+        trusted-proxies = [
+          "::1/128"
+          "172.17.0.0/24"
+        ];
 
-          landing-page-user = "katja";
+        db-type = "sqlite";
+        db-address = "${config.tgc.services.gotosocial.stateDir}/db.sqlite";
 
-          accounts-allow-custom-css = true;
-          accounts-registration-open = false;
+        storage-backend = "local";
+        storage-local-base-path = "${config.tgc.services.gotosocial.stateDir}/storage";
 
-          instance-expose-peers = true;
-          instance-expose-suspended = true;
-          instance-expose-suspended-web = true;
+        host = "fedi.ctu.cx";
+        account-domain = "ctu.cx";
 
-          instance-languages = [
-            "de"
-            "en-us"
-          ];
+        landing-page-user = "katja";
 
-          media-local-max-size = "50MiB";
-          media-remote-max-size = "50MiB";
+        accounts-allow-custom-css = true;
+        accounts-registration-open = false;
 
-          media-remote-cache-days = 3;
-          media-cleanup-from = "01:00";
-        };
+        instance-expose-peers = true;
+        instance-expose-suspended = true;
+        instance-expose-suspended-web = true;
+
+        instance-languages = [
+          "de"
+          "en-us"
+        ];
+
+        media-local-max-size = "50MiB";
+        media-remote-max-size = "50MiB";
+
+        media-remote-cache-days = 3;
+        media-cleanup-from = "01:00";
       };
     };
 

@@ -129,76 +131,75 @@ in
       appendHttpConfig = ''
         proxy_cache_path /var/cache/nginx keys_zone=gotosocial_ap_public_responses:10m inactive=1w;
       '';
-      virtualHosts =
-        {
-          "${config.modules.services.gotosocial.settings.host}" = {
-            useACMEHost = lib.mkDefault "${config.networking.fqdn}";
-            forceSSL = lib.mkDefault true;
-            kTLS = lib.mkDefault true;
-            locations = {
-              "/" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                proxyWebsockets = true;
-              };
-
-              "~ /.well-known/(webfinger|host-meta)$" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                extraConfig = ''
-                  proxy_cache gotosocial_ap_public_responses;
-                  proxy_cache_background_update on;
-                  proxy_cache_key $scheme://$host$uri$is_args$query_string;
-                  proxy_cache_valid 200 10m;
-                  proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
-                  proxy_cache_lock on;
-                  add_header X-Cache-Status $upstream_cache_status;
-                '';
-              };
+      virtualHosts = {
+        "${config.tgc.services.gotosocial.settings.host}" = {
+          useACMEHost = lib.mkDefault "${config.networking.fqdn}";
+          forceSSL = lib.mkDefault true;
+          kTLS = lib.mkDefault true;
+          locations = {
+            "/" = {
+              proxyPass = "http://[${toString config.tgc.services.gotosocial.settings.bind-address}]:${toString config.tgc.services.gotosocial.settings.port}";
+              proxyWebsockets = true;
+            };
 
-              "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                extraConfig = ''
-                  proxy_cache gotosocial_ap_public_responses;
-                  proxy_cache_background_update on;
-                  proxy_cache_key $scheme://$host$uri;
-                  proxy_cache_valid 200 604800s;
-                  proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
-                  proxy_cache_lock on;
-
-                  add_header X-Cache-Status $upstream_cache_status;
-                '';
-              };
+            "~ /.well-known/(webfinger|host-meta)$" = {
+              proxyPass = "http://[${toString config.tgc.services.gotosocial.settings.bind-address}]:${toString config.tgc.services.gotosocial.settings.port}";
+              extraConfig = ''
+                proxy_cache gotosocial_ap_public_responses;
+                proxy_cache_background_update on;
+                proxy_cache_key $scheme://$host$uri$is_args$query_string;
+                proxy_cache_valid 200 10m;
+                proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
+                proxy_cache_lock on;
+                add_header X-Cache-Status $upstream_cache_status;
+              '';
+            };
 
-              "/assets/".extraConfig = ''
-                alias ${config.modules.services.gotosocial.package}/share/web/assets/;
-                autoindex off;
-                expires max;
-                add_header Cache-Control "public, immutable";
+            "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$" = {
+              proxyPass = "http://[${toString config.tgc.services.gotosocial.settings.bind-address}]:${toString config.tgc.services.gotosocial.settings.port}";
+              extraConfig = ''
+                proxy_cache gotosocial_ap_public_responses;
+                proxy_cache_background_update on;
+                proxy_cache_key $scheme://$host$uri;
+                proxy_cache_valid 200 604800s;
+                proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
+                proxy_cache_lock on;
+
+                add_header X-Cache-Status $upstream_cache_status;
               '';
             };
+
+            "/assets/".extraConfig = ''
+              alias ${config.tgc.services.gotosocial.package}/share/web/assets/;
+              autoindex off;
+              expires max;
+              add_header Cache-Control "public, immutable";
+            '';
           };
-        }
-        // (
-          if
-            (
-              config.modules.services.gotosocial.settings.account-domain
-              != config.modules.services.gotosocial.settings.host
-            )
-          then
-            {
-              "${config.modules.services.gotosocial.settings.account-domain}" = {
-                locations = {
-                  "= /.well-known/host-meta".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                  "= /.well-known/webfinger".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                  "= /.well-known/nodeinfo".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                };
+        };
+      }
+      // (
+        if
+          (
+            config.tgc.services.gotosocial.settings.account-domain
+            != config.tgc.services.gotosocial.settings.host
+          )
+        then
+          {
+            "${config.tgc.services.gotosocial.settings.account-domain}" = {
+              locations = {
+                "= /.well-known/host-meta".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
+                "= /.well-known/webfinger".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
+                "= /.well-known/nodeinfo".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
               };
-            }
-          else
-            { }
-        );
+            };
+          }
+        else
+          { }
+      );
     };
   };
 
diff --git a/config/nixos/modules/websites/fedi.home.ctu.cx.nix b/config/nixos/modules/websites/fedi.home.ctu.cx.nix
@@ -1,7 +1,5 @@
 {
-  name,
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,

@@ -11,7 +9,6 @@
 let
   inherit (lib) types;
   cfg = lib.getAttrFromPath povSelf config;
-  cfgWebsites = lib.getAttrFromPath (lib.remove name povSelf) config;
 
 in
 {

@@ -21,18 +18,10 @@ in
       type = types.bool;
       default = false;
     };
-    domain = {
-      type = types.str;
-      default = "ctu.cx";
-    };
-    subdomain = {
-      type = types.str;
-      default = "fedi.home";
-    };
   };
 
   config = lib.mkIf cfg.enable {
-    dns.zones."${cfg.domain}".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ];
+    dns.zones."ctu.cx".subdomains."fedi.home".CNAME = [ "${config.networking.fqdn}." ];
 
     sops.secrets = {
       "resticPasswords/gotosocial" = { };

@@ -40,76 +29,87 @@ in
 
     systemd.tmpfiles.settings.gotosocial = {
       "/var/lib/gotosocial/storage".d = {
-        user = config.modules.services.gotosocial.user;
-        group = config.modules.services.gotosocial.group;
+        inherit (config.tgc.services.gotosocial) user;
+        inherit (config.tgc.services.gotosocial) group;
         mode = "750";
         age = "-";
       };
     };
 
-    modules.services = {
-      resticBackup.paths = {
+    modules = {
+      filesystem.impermanence.system.dirs = [
+        {
+          directory = config.tgc.services.gotosocial.stateDir;
+          mode = "0755";
+          inherit (config.tgc.services.gotosocial) user;
+          inherit (config.tgc.services.gotosocial) group;
+        }
+      ];
+
+      services.resticBackup.paths = {
         gotosocial = {
           enable = true;
-          user = config.modules.services.gotosocial.user;
+          package = pkgs.tgc.gotosocial-unstable;
+          inherit (config.tgc.services.gotosocial) user;
           passwordFile = config.sops.secrets."resticPasswords/gotosocial".path;
           sqliteDatabases = [
             (lib.mkIf (
-              config.modules.services.gotosocial.settings.db-type == "sqlite"
-            ) config.modules.services.gotosocial.settings.db-address)
+              config.tgc.services.gotosocial.settings.db-type == "sqlite"
+            ) config.tgc.services.gotosocial.settings.db-address)
           ];
           paths = [
             (lib.mkIf (
-              config.modules.services.gotosocial.settings.storage-backend == "local"
-            ) config.modules.services.gotosocial.settings.storage-local-base-path)
-            "${config.modules.services.gotosocial.stateDir}/backup.json"
+              config.tgc.services.gotosocial.settings.storage-backend == "local"
+            ) config.tgc.services.gotosocial.settings.storage-local-base-path)
+            "${config.tgc.services.gotosocial.stateDir}/backup.json"
           ];
-          runBeforeBackup = ''${pkgs.gotosocial}/bin/gotosocial --config-path /etc/gotosocial.yaml admin export --path ${config.modules.services.gotosocial.stateDir}/backup.json'';
+          runBeforeBackup = ''${config.tgc.services.gotosocial.package}/bin/gotosocial --config-path /etc/gotosocial.yaml admin export --path ${config.tgc.services.gotosocial.stateDir}/backup.json'';
         };
       };
-      gotosocial = {
-        enable = true;
-        group = config.services.nginx.group;
-        settings = {
-          protocol = lib.mkDefault "https";
-
-          bind-address = lib.mkDefault "[::1]";
-          port = lib.mkDefault 8085;
-
-          trusted-proxies = lib.mkDefault [
-            "::1/128"
-            "172.17.0.0/24"
-          ];
+    };
 
-          db-type = lib.mkDefault "sqlite";
-          db-address = lib.mkDefault "${config.modules.services.gotosocial.stateDir}/db.sqlite";
+    tgc.services.gotosocial = {
+      enable = true;
+      inherit (config.services.nginx) group;
+      settings = {
+        protocol = "https";
 
-          storage-backend = lib.mkDefault "local";
-          storage-local-base-path = "${config.modules.services.gotosocial.stateDir}/storage";
+        bind-address = "[::1]";
+        port = 8085;
 
-          host = "${cfg.subdomain}.${cfg.domain}";
-          account-domain = cfg.domain;
+        trusted-proxies = [
+          "::1/128"
+          "172.17.0.0/24"
+        ];
 
-          landing-page-user = "leah";
+        db-type = lib.mkDefault "sqlite";
+        db-address = lib.mkDefault "${config.tgc.services.gotosocial.stateDir}/db.sqlite";
 
-          accounts-allow-custom-css = true;
-          accounts-registration-open = false;
+        storage-backend = lib.mkDefault "local";
+        storage-local-base-path = "${config.tgc.services.gotosocial.stateDir}/storage";
 
-          instance-expose-peers = true;
-          instance-expose-suspended = true;
-          instance-expose-suspended-web = true;
+        host = "fedi.home.ctu.cx";
+        account-domain = "fedi.home.ctu.cx";
 
-          instance-languages = [
-            "de"
-            "en-us"
-          ];
+        landing-page-user = "leah";
 
-          media-local-max-size = "50MiB";
-          media-remote-max-size = "50MiB";
+        accounts-allow-custom-css = true;
+        accounts-registration-open = false;
 
-          media-remote-cache-days = 3;
-          media-cleanup-from = "01:00";
-        };
+        instance-expose-peers = true;
+        instance-expose-suspended = true;
+        instance-expose-suspended-web = true;
+
+        instance-languages = [
+          "de"
+          "en-us"
+        ];
+
+        media-local-max-size = "50MiB";
+        media-remote-max-size = "50MiB";
+
+        media-remote-cache-days = 3;
+        media-cleanup-from = "01:00";
       };
     };
 

@@ -117,76 +117,75 @@ in
       appendHttpConfig = ''
         proxy_cache_path /var/cache/nginx keys_zone=gotosocial_ap_public_responses:10m inactive=1w;
       '';
-      virtualHosts =
-        {
-          "${config.modules.services.gotosocial.settings.host}" = {
-            useACMEHost = lib.mkDefault "${config.networking.fqdn}";
-            forceSSL = lib.mkDefault true;
-            kTLS = lib.mkDefault true;
-            locations = {
-              "/" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                proxyWebsockets = true;
-              };
-
-              "~ /.well-known/(webfinger|host-meta)$" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                extraConfig = ''
-                  proxy_cache gotosocial_ap_public_responses;
-                  proxy_cache_background_update on;
-                  proxy_cache_key $scheme://$host$uri$is_args$query_string;
-                  proxy_cache_valid 200 10m;
-                  proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
-                  proxy_cache_lock on;
-                  add_header X-Cache-Status $upstream_cache_status;
-                '';
-              };
+      virtualHosts = {
+        "${config.tgc.services.gotosocial.settings.host}" = {
+          useACMEHost = lib.mkDefault "${config.networking.fqdn}";
+          forceSSL = lib.mkDefault true;
+          kTLS = lib.mkDefault true;
+          locations = {
+            "/" = {
+              proxyPass = "http://${toString config.tgc.services.gotosocial.settings.bind-address}:${toString config.tgc.services.gotosocial.settings.port}";
+              proxyWebsockets = true;
+            };
 
-              "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                extraConfig = ''
-                  proxy_cache gotosocial_ap_public_responses;
-                  proxy_cache_background_update on;
-                  proxy_cache_key $scheme://$host$uri;
-                  proxy_cache_valid 200 604800s;
-                  proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
-                  proxy_cache_lock on;
-
-                  add_header X-Cache-Status $upstream_cache_status;
-                '';
-              };
+            "~ /.well-known/(webfinger|host-meta)$" = {
+              proxyPass = "http://${toString config.tgc.services.gotosocial.settings.bind-address}:${toString config.tgc.services.gotosocial.settings.port}";
+              extraConfig = ''
+                proxy_cache gotosocial_ap_public_responses;
+                proxy_cache_background_update on;
+                proxy_cache_key $scheme://$host$uri$is_args$query_string;
+                proxy_cache_valid 200 10m;
+                proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
+                proxy_cache_lock on;
+                add_header X-Cache-Status $upstream_cache_status;
+              '';
+            };
 
-              "/assets/".extraConfig = ''
-                alias ${config.modules.services.gotosocial.package}/share/web/assets/;
-                autoindex off;
-                expires max;
-                add_header Cache-Control "public, immutable";
+            "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$" = {
+              proxyPass = "http://${toString config.tgc.services.gotosocial.settings.bind-address}:${toString config.tgc.services.gotosocial.settings.port}";
+              extraConfig = ''
+                proxy_cache gotosocial_ap_public_responses;
+                proxy_cache_background_update on;
+                proxy_cache_key $scheme://$host$uri;
+                proxy_cache_valid 200 604800s;
+                proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
+                proxy_cache_lock on;
+
+                add_header X-Cache-Status $upstream_cache_status;
               '';
             };
+
+            "/assets/".extraConfig = ''
+              alias ${config.tgc.services.gotosocial.package}/share/web/assets/;
+              autoindex off;
+              expires max;
+              add_header Cache-Control "public, immutable";
+            '';
           };
-        }
-        // (
-          if
-            (
-              config.modules.services.gotosocial.settings.account-domain
-              != config.modules.services.gotosocial.settings.host
-            )
-          then
-            {
-              "${config.modules.services.gotosocial.settings.account-domain}" = {
-                locations = {
-                  "= /.well-known/host-meta".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                  "= /.well-known/webfinger".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                  "= /.well-known/nodeinfo".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                };
+        };
+      }
+      // (
+        if
+          (
+            config.tgc.services.gotosocial.settings.account-domain
+            != config.tgc.services.gotosocial.settings.host
+          )
+        then
+          {
+            "${config.tgc.services.gotosocial.settings.account-domain}" = {
+              locations = {
+                "= /.well-known/host-meta".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
+                "= /.well-known/webfinger".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
+                "= /.well-known/nodeinfo".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
               };
-            }
-          else
-            { }
-        );
+            };
+          }
+        else
+          { }
+      );
     };
   };
 
diff --git a/config/nixos/modules/websites/flauschehorn.zaphyra.eu.nix b/config/nixos/modules/websites/flauschehorn.zaphyra.eu.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,
diff --git a/config/nixos/modules/websites/git.zaphyra.eu.nix b/config/nixos/modules/websites/git.zaphyra.eu.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  hostConfig,
   config,
   lib,
   pkgs,

@@ -41,6 +40,7 @@ in
         "nix"
         "etc"
         "javascript"
+        "golang"
         "nimlang"
         "nimlang libraries"
         "archive"

@@ -204,7 +204,7 @@ in
           enable = true;
           user = "git";
           group = "git";
-          adminPubkey = cfg.adminPubkey;
+          inherit (cfg) adminPubkey;
 
           extraGitoliteRc = ''
             $RC{GIT_CONFIG_KEYS} = ".*";
diff --git a/config/nixos/modules/websites/gomuks.zaphyra.eu.nix b/config/nixos/modules/websites/gomuks.zaphyra.eu.nix
@@ -0,0 +1,104 @@
+{
+  povSelf,
+  inputs,
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options = {
+    enable = {
+      type = types.bool;
+      default = false;
+    };
+    domain = {
+      type = types.str;
+      default = "zaphyra.eu";
+    };
+    subdomain = {
+      type = types.str;
+      default = "gomuks";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    dns.zones."${cfg.domain}".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ];
+
+    modules.filesystem.impermanence.system.dirs = [ "/var/lib/private/gomuks-web" ];
+
+    systemd.services.gomuks-web = {
+      description = "gomuks-web";
+
+      environment.GOMUKS_ROOT = "/var/lib/gomuks-web";
+
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "network-online.target" ];
+      after = [ "network-online.target" ];
+
+      path = [ pkgs.ffmpeg-headless ];
+
+      serviceConfig = {
+        Type = "simple";
+        ExecStart = lib.getExe (
+          pkgs.tgc.gomuks-web.override {
+            extraPatches = [
+              inputs.self.resources.patches.gomuks-web-css
+            ];
+          }
+        );
+
+        DynamicUser = true;
+        User = "gomuks-web";
+        Group = "gomuks-web";
+
+        StateDirectory = "gomuks-web";
+
+        Restart = "on-failure";
+        RestartSec = "30s";
+
+        LockPersonality = true;
+        NoNewPrivileges = true;
+
+        PrivateDevices = true;
+        PrivateTmp = true;
+        PrivateUsers = true;
+
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectSystem = "strict";
+
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+
+        SystemCallArchitectures = "native";
+        SystemCallErrorNumber = "EPERM";
+        SystemCallFilter = [ "@system-service" ];
+      };
+    };
+
+    services.nginx.virtualHosts."${cfg.subdomain}.${cfg.domain}" = {
+      useACMEHost = lib.mkDefault "${config.networking.fqdn}";
+      forceSSL = lib.mkDefault true;
+      kTLS = lib.mkDefault true;
+      locations."/" = {
+        proxyPass = "http://[::1]:29325";
+        proxyWebsockets = true;
+      };
+    };
+  };
+
+}
diff --git a/config/nixos/modules/websites/grafana.infra.zaphyra.eu.nix b/config/nixos/modules/websites/grafana.infra.zaphyra.eu.nix
@@ -1,9 +1,7 @@
 {
-  inputs,
   povSelf,
   config,
   lib,
-  pkgs,
   ...
 }:
 
diff --git a/config/nixos/modules/websites/grapevine.zaphyra.eu.nix b/config/nixos/modules/websites/grapevine.zaphyra.eu.nix
@@ -1,7 +1,6 @@
 {
   name,
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,

@@ -32,9 +31,10 @@ in
   };
 
   config = lib.mkIf cfg.enable {
+
     assertions = [
       {
-        assertion = cfgWebsites."zaphyra.eu".enable == true;
+        assertion = cfgWebsites."zaphyra.eu".enable;
         message = "The option 'modules.websites.\"zaphyra.eu\"' must be enabled in order to use this module.";
       }
     ];

@@ -132,7 +132,7 @@ in
             kTLS = true;
             locations = {
               "/_matrix" = {
-                proxyPass = "http://[${grapevineListen.address}]:${toString (grapevineListen.port)}";
+                proxyPass = "http://[${grapevineListen.address}]:${toString grapevineListen.port}";
                 proxyWebsockets = true;
               };
               "/".root = pkgs.cinny.override {
diff --git a/config/nixos/modules/websites/gts.zaphyra.eu.nix b/config/nixos/modules/websites/gts.zaphyra.eu.nix
@@ -1,7 +1,6 @@
 {
   name,
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,

@@ -21,29 +20,24 @@ in
       type = types.bool;
       default = false;
     };
-    domain = {
-      type = types.str;
-      default = "zaphyra.eu";
-    };
-    subdomain = {
-      type = types.str;
-      default = "gts";
-    };
   };
 
   config = lib.mkIf cfg.enable {
     assertions = [
       {
-        assertion = cfgWebsites."zaphyra.eu".enable == true;
+        assertion = cfgWebsites."zaphyra.eu".enable;
         message = "The option 'modules.websites.\"zaphyra.eu\"' must be enabled in order to use this module.";
       }
     ];
 
-    dns.zones."${cfg.domain}".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ];
+    dns.zones."zaphyra.eu".subdomains."gts".CNAME = [ "${config.networking.fqdn}." ];
 
     systemd.services.gotosocial.after = [ "sops-install-secrets.service" ];
+
     sops.secrets = {
-      "resticPasswords/gotosocial" = { };
+      "resticPasswords/gotosocial" = {
+        owner = "gotosocial";
+      };
       gotosocialEnv = {
         restartUnits = [ "gotosocial.service" ];
       };

@@ -51,82 +45,97 @@ in
 
     systemd.tmpfiles.settings.gotosocial = {
       "/var/lib/gotosocial/storage".d = {
-        user = config.modules.services.gotosocial.user;
-        group = config.modules.services.gotosocial.group;
+        inherit (config.tgc.services.gotosocial) user;
+        inherit (config.tgc.services.gotosocial) group;
         mode = "750";
         age = "-";
       };
     };
 
-    modules.services = {
-      resticBackup.paths = {
+    modules = {
+      filesystem.impermanence.system.dirs = [
+        {
+          directory = config.tgc.services.gotosocial.stateDir;
+          mode = "0755";
+          inherit (config.tgc.services.gotosocial) user;
+          inherit (config.tgc.services.gotosocial) group;
+        }
+      ];
+
+      services.resticBackup.paths = {
         gotosocial = {
           enable = true;
-          user = config.modules.services.gotosocial.user;
+          inherit (config.tgc.services.gotosocial) user;
           passwordFile = config.sops.secrets."resticPasswords/gotosocial".path;
           sqliteDatabases = [
             (lib.mkIf (
-              config.modules.services.gotosocial.settings.db-type == "sqlite"
-            ) config.modules.services.gotosocial.settings.db-address)
+              config.tgc.services.gotosocial.settings.db-type == "sqlite"
+            ) config.tgc.services.gotosocial.settings.db-address)
           ];
           paths = [
             (lib.mkIf (
-              config.modules.services.gotosocial.settings.storage-backend == "local"
-            ) config.modules.services.gotosocial.settings.storage-local-base-path)
-            "${config.modules.services.gotosocial.stateDir}/backup.json"
+              config.tgc.services.gotosocial.settings.storage-backend == "local"
+            ) config.tgc.services.gotosocial.settings.storage-local-base-path)
+            "${config.tgc.services.gotosocial.stateDir}/backup.json"
           ];
-          runBeforeBackup = ''${pkgs.gotosocial}/bin/gotosocial --config-path /etc/gotosocial.yaml admin export --path ${config.modules.services.gotosocial.stateDir}/backup.json'';
+          runBeforeBackup = ''${config.tgc.services.gotosocial.package}/bin/gotosocial --config-path /etc/gotosocial.yaml admin export --path ${config.tgc.services.gotosocial.stateDir}/backup.json'';
         };
       };
-      gotosocial = {
-        enable = true;
-        group = config.services.nginx.group;
-        environmentFile = config.sops.secrets.gotosocialEnv.path;
-        settings = {
-          protocol = lib.mkDefault "https";
-
-          bind-address = lib.mkDefault "[::1]";
-          port = lib.mkDefault 8085;
-
-          trusted-proxies = lib.mkDefault [
-            "::1/128"
-            "172.17.0.0/24"
-          ];
+    };
 
-          db-type = lib.mkDefault "sqlite";
-          db-address = lib.mkDefault "${config.modules.services.gotosocial.stateDir}/db.sqlite";
+    tgc.services.gotosocial = {
+      enable = true;
+      package = pkgs.tgc.gotosocial-unstable;
+      inherit (config.services.nginx) group;
+      environmentFile = config.sops.secrets.gotosocialEnv.path;
+      settings = {
+        protocol = "https";
 
-          storage-backend = lib.mkDefault "local";
-          storage-local-base-path = "${config.modules.services.gotosocial.stateDir}/storage";
+        bind-address = "::1";
+        port = 8085;
 
-          host = "${cfg.subdomain}.${cfg.domain}";
-          account-domain = cfg.domain;
+        trusted-proxies = [
+          "::1/128"
+          "172.17.0.0/24"
+        ];
 
-          landing-page-user = "katja";
+        db-type = "sqlite";
+        db-address = "${config.tgc.services.gotosocial.stateDir}/db.sqlite";
 
-          accounts-allow-custom-css = true;
-          accounts-registration-open = false;
+        storage-backend = "local";
+        storage-local-base-path = "${config.tgc.services.gotosocial.stateDir}/storage";
 
-          instance-expose-peers = true;
-          instance-expose-suspended = true;
-          instance-expose-suspended-web = true;
+        host = "gts.zaphyra.eu";
+        account-domain = "zaphyra.eu";
 
-          instance-languages = [
-            "de"
-            "en-us"
-          ];
+        landing-page-user = "katja";
 
-          media-local-max-size = "50MiB";
-          media-remote-max-size = "50MiB";
+        accounts-allow-custom-css = true;
+        accounts-registration-open = false;
 
-          media-remote-cache-days = 3;
-          media-cleanup-from = "01:00";
+        instance-expose-peers = true;
+        instance-expose-suspended = true;
+        instance-expose-suspended-web = true;
 
-          smtp-host = "morio.infra.zaphyra.eu";
-          smtp-port = 587;
-          smtp-username = "gts@zaphyra.eu";
-          smtp-from = "gts@zaphyra.eu";
-        };
+        instance-languages = [
+          "en"
+          "de"
+        ];
+
+        media-emoji-local-max-size = "100KiB";
+
+        media-local-max-size = "50MiB";
+        media-remote-max-size = "50MiB";
+
+        media-remote-cache-days = 3;
+        media-cleanup-from = "01:00";
+
+        smtp-host = "morio.infra.zaphyra.eu";
+        smtp-port = 587;
+        smtp-username = "gts@zaphyra.eu";
+        smtp-from = "gts@zaphyra.eu";
+
+        advanced-rate-limit-requests = 3000;
       };
     };
 

@@ -134,86 +143,85 @@ in
       appendHttpConfig = ''
         proxy_cache_path /var/cache/nginx keys_zone=gotosocial_ap_public_responses:10m inactive=1w;
       '';
-      virtualHosts =
-        {
-          "${config.modules.services.gotosocial.settings.host}" = {
-            useACMEHost = lib.mkDefault "${config.networking.fqdn}";
-            forceSSL = lib.mkDefault true;
-            kTLS = lib.mkDefault true;
-            locations = {
-              "/" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                proxyWebsockets = true;
-              };
-
-              "/client/" = {
-                index = "index.html";
-                alias = "${
-                  pkgs.phanpy.override {
-                    clientName = "zaphyra's fedi";
-                    website = "https://gts.zaphyra.eu/client/";
-                    defaultInstance = "gts.zaphyra.eu";
-                  }
-                }/";
-              };
-              "~ /.well-known/(webfinger|host-meta)$" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                extraConfig = ''
-                  proxy_cache gotosocial_ap_public_responses;
-                  proxy_cache_background_update on;
-                  proxy_cache_key $scheme://$host$uri$is_args$query_string;
-                  proxy_cache_valid 200 10m;
-                  proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
-                  proxy_cache_lock on;
-                  add_header X-Cache-Status $upstream_cache_status;
-                '';
-              };
+      virtualHosts = {
+        "${config.tgc.services.gotosocial.settings.host}" = {
+          useACMEHost = lib.mkDefault "${config.networking.fqdn}";
+          forceSSL = lib.mkDefault true;
+          kTLS = lib.mkDefault true;
+          locations = {
+            "/" = {
+              proxyPass = "http://[${toString config.tgc.services.gotosocial.settings.bind-address}]:${toString config.tgc.services.gotosocial.settings.port}";
+              proxyWebsockets = true;
+            };
 
-              "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$" = {
-                proxyPass = "http://${toString config.modules.services.gotosocial.settings.bind-address}:${toString config.modules.services.gotosocial.settings.port}";
-                extraConfig = ''
-                  proxy_cache gotosocial_ap_public_responses;
-                  proxy_cache_background_update on;
-                  proxy_cache_key $scheme://$host$uri;
-                  proxy_cache_valid 200 604800s;
-                  proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
-                  proxy_cache_lock on;
-
-                  add_header X-Cache-Status $upstream_cache_status;
-                '';
-              };
+            "/client/" = {
+              index = "index.html";
+              alias = "${
+                pkgs.tgc.phanpy.override {
+                  clientName = "zaphyra's fedi";
+                  website = "https://gts.zaphyra.eu/client/";
+                  defaultInstance = "gts.zaphyra.eu";
+                }
+              }/";
+            };
+            "~ /.well-known/(webfinger|host-meta)$" = {
+              proxyPass = "http://[${toString config.tgc.services.gotosocial.settings.bind-address}]:${toString config.tgc.services.gotosocial.settings.port}";
+              extraConfig = ''
+                proxy_cache gotosocial_ap_public_responses;
+                proxy_cache_background_update on;
+                proxy_cache_key $scheme://$host$uri$is_args$query_string;
+                proxy_cache_valid 200 10m;
+                proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
+                proxy_cache_lock on;
+                add_header X-Cache-Status $upstream_cache_status;
+              '';
+            };
 
-              "/assets/".extraConfig = ''
-                alias ${config.modules.services.gotosocial.package}/share/web/assets/;
-                autoindex off;
-                expires max;
-                add_header Cache-Control "public, immutable";
+            "~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$" = {
+              proxyPass = "http://[${toString config.tgc.services.gotosocial.settings.bind-address}]:${toString config.tgc.services.gotosocial.settings.port}";
+              extraConfig = ''
+                proxy_cache gotosocial_ap_public_responses;
+                proxy_cache_background_update on;
+                proxy_cache_key $scheme://$host$uri;
+                proxy_cache_valid 200 604800s;
+                proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
+                proxy_cache_lock on;
+
+                add_header X-Cache-Status $upstream_cache_status;
               '';
             };
+
+            "/assets/".extraConfig = ''
+              alias ${config.tgc.services.gotosocial.package}/share/gotosocial/web/assets/;
+              autoindex off;
+              expires max;
+              add_header Cache-Control "public, immutable";
+            '';
           };
-        }
-        // (
-          if
-            (
-              config.modules.services.gotosocial.settings.account-domain
-              != config.modules.services.gotosocial.settings.host
-            )
-          then
-            {
-              "${config.modules.services.gotosocial.settings.account-domain}" = {
-                locations = {
-                  "= /.well-known/host-meta".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                  "= /.well-known/webfinger".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                  "= /.well-known/nodeinfo".extraConfig =
-                    "return 301 https://${config.modules.services.gotosocial.settings.host}$request_uri;";
-                };
+        };
+      }
+      // (
+        if
+          (
+            config.tgc.services.gotosocial.settings.account-domain
+            != config.tgc.services.gotosocial.settings.host
+          )
+        then
+          {
+            "${config.tgc.services.gotosocial.settings.account-domain}" = {
+              locations = {
+                "= /.well-known/host-meta".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
+                "= /.well-known/webfinger".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
+                "= /.well-known/nodeinfo".extraConfig =
+                  "return 301 https://${config.tgc.services.gotosocial.settings.host}$request_uri;";
               };
-            }
-          else
-            { }
-        );
+            };
+          }
+        else
+          { }
+      );
     };
   };
 
diff --git a/config/nixos/modules/websites/ip.zaphyra.eu.nix b/config/nixos/modules/websites/ip.zaphyra.eu.nix
@@ -28,79 +28,81 @@ in
   config = lib.mkIf cfg.enable {
 
     dns.zones."${cfg.domain}".subdomains = {
-      "ip" = (dnsNix.combinators.host hostConfig.networking.ip4Address hostConfig.networking.ip6Address);
+      "ip" = dnsNix.combinators.host hostConfig.networking.ip4Address hostConfig.networking.ip6Address;
       "ip4".A = [ hostConfig.networking.ip4Address ];
       "ip6".AAAA = [ hostConfig.networking.ip6Address ];
     };
 
-    services.nginx.virtualHosts."ip.${cfg.domain}" = {
-      useACMEHost = "${config.networking.fqdn}";
-      forceSSL = true;
-      kTLS = true;
-      locations."/" = {
-        extraConfig = "types { } default_type 'text/html; charset=utf-8';";
-        return = ''
-          200 '
-            <!DOCTYPE html>
-            <html>
-              <head>
-                <title>ip.${cfg.domain}</title>
-              </head>
-              <body>
-                <h1>ip.${cfg.domain}</h1>
-                <ul>
-                  <li><span style="user-select: none;"><b>IPv6:</b> </span><span id="ip6">Loading...</span></li>
-                  <li><span style="user-select: none;"><b>IPv4:</b> </span><span id="ip4">Loading...</span></li>
-                </ul>
-                <p>Use bash and curl: <code>curl ip{4,6}.${cfg.domain}</code></p>
-                <p><small>Because any other "Whats my IP?"-tool sucks. <a href="https://git.clerie.de/clerie/ip.clerie.de">Host yourself :3</a></small></p>
+    services.nginx.virtualHosts = {
+      "ip.${cfg.domain}" = {
+        useACMEHost = "${config.networking.fqdn}";
+        forceSSL = true;
+        kTLS = true;
+        locations."/" = {
+          extraConfig = "types { } default_type 'text/html; charset=utf-8';";
+          return = ''
+            200 '
+              <!DOCTYPE html>
+              <html>
+                <head>
+                  <title>ip.${cfg.domain}</title>
+                </head>
+                <body>
+                  <h1>ip.${cfg.domain}</h1>
+                  <ul>
+                    <li><span style="user-select: none;"><b>IPv6:</b> </span><span id="ip6">Loading...</span></li>
+                    <li><span style="user-select: none;"><b>IPv4:</b> </span><span id="ip4">Loading...</span></li>
+                  </ul>
+                  <p>Use bash and curl: <code>curl ip{4,6}.${cfg.domain}</code></p>
+                  <p><small>Because any other "Whats my IP?"-tool sucks. <a href="https://git.clerie.de/clerie/ip.clerie.de">Host yourself :3</a></small></p>
 
-                <script>
-                  window.addEventListener("DOMContentLoaded", (event) => {
-                    [ "ip6", "ip4" ].forEach(async (ipVersion) => {
-                      try {
-                        const url      = "https://" + ipVersion + ".${cfg.domain}/";
-                        const response = await fetch(url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime());
-                        if(response.status != 200) {
+                  <script>
+                    window.addEventListener("DOMContentLoaded", (event) => {
+                      [ "ip6", "ip4" ].forEach(async (ipVersion) => {
+                        try {
+                          const url      = "https://" + ipVersion + ".${cfg.domain}/";
+                          const response = await fetch(url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime());
+                          if(response.status != 200) {
+                            document.getElementById(ipVersion).innerText = "Error!";
+                          } else {
+                            document.getElementById(ipVersion).innerText = await response.text();
+                          }
+                        } catch {
                           document.getElementById(ipVersion).innerText = "Error!";
-                        } else {
-                          document.getElementById(ipVersion).innerText = await response.text();
                         }
-                      } catch {
-                        document.getElementById(ipVersion).innerText = "Error!";
-                      }
+                      });
                     });
-                  });
-                </script>
-              </body>
-            </html>'
-        '';
+                  </script>
+                </body>
+              </html>'
+          '';
+        };
       };
-    };
 
-    services.nginx.virtualHosts."ip4.${cfg.domain}" = {
-      useACMEHost = "${config.networking.fqdn}";
-      forceSSL = true;
-      kTLS = true;
-      locations."/" = {
-        return = "200 '$remote_addr\n'";
-        extraConfig = ''
-          types { } default_type "text/plain; charset=utf-8";
-          add_header Access-Control-Allow-Origin *;
-        '';
+      "ip4.${cfg.domain}" = {
+        useACMEHost = "${config.networking.fqdn}";
+        forceSSL = true;
+        kTLS = true;
+        locations."/" = {
+          return = "200 '$remote_addr\n'";
+          extraConfig = ''
+            types { } default_type "text/plain; charset=utf-8";
+            add_header Access-Control-Allow-Origin *;
+          '';
+        };
       };
-    };
 
-    services.nginx.virtualHosts."ip6.${cfg.domain}" = {
-      useACMEHost = "${config.networking.fqdn}";
-      forceSSL = true;
-      kTLS = true;
-      locations."/" = {
-        return = "200 '$remote_addr\n'";
-        extraConfig = ''
-          types { } default_type "text/plain; charset=utf-8";
-          add_header Access-Control-Allow-Origin *;
-        '';
+      "ip6.${cfg.domain}" = {
+        useACMEHost = "${config.networking.fqdn}";
+        forceSSL = true;
+        kTLS = true;
+        locations."/" = {
+          return = "200 '$remote_addr\n'";
+          extraConfig = ''
+            types { } default_type "text/plain; charset=utf-8";
+            add_header Access-Control-Allow-Origin *;
+          '';
+        };
       };
     };
   };
diff --git a/config/nixos/modules/websites/katja.wtf.nix b/config/nixos/modules/websites/katja.wtf.nix
@@ -2,7 +2,6 @@
   povSelf,
   hostConfig,
   config,
-  pkgs,
   lib,
   dnsNix,
   ...
diff --git a/config/nixos/modules/websites/oeffi.zaphyra.eu.nix b/config/nixos/modules/websites/oeffi.zaphyra.eu.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,

@@ -78,47 +77,49 @@ in
           large_client_header_buffers 4 16k;
         '';
 
-        locations."/db/vehicle-sequence".extraConfig = ''
-          proxy_ssl_server_name on;
-          proxy_ssl_name        www.bahn.de;
-          proxy_set_header      Host www.bahn.de;
-          proxy_hide_header    'set-cookie';
-          proxy_pass            https://www.bahn.de/web/api/reisebegleitung/wagenreihung/vehicle-sequence$is_args$args;
-        '';
-
-        locations."~ ^/db/vendo/(?<vendotarget>[a-z]+)(/([^\\r\\n].*))?$".extraConfig = ''
-          if ($vendopath = no) {
-            return 400;
-          }
-
-          if ($vendotarget = 'trip') {
-            set $vendopath '$vendopath$2';
-          }
-
-          if ($vendotarget = 'location') {
-            set $vendopath '$vendopath$2';
-          }
-
-          set $vendodomain 'app.vendo.noncd.db.de';
-
-          proxy_ssl_server_name on;
-          proxy_ssl_name        $vendodomain;
-          proxy_set_header      Host $vendodomain;
-          proxy_hide_header    'set-cookie';
-          proxy_pass            https://$vendodomain$vendopath;
-        '';
-
-        locations."~ ^/hafas/(?<hafastarget>.*)$".extraConfig = ''
-          if ($hafasurl = no) {
-            return 400;
-          }
-
-          proxy_ssl_server_name on;
-          proxy_ssl_name        $hafasurl;
-          proxy_set_header      Host $hafasurl;
-          proxy_hide_header    'set-cookie';
-          proxy_pass            https://$hafasurl$hafaspath;
-        '';
+        locations = {
+          "/db/vehicle-sequence".extraConfig = ''
+            proxy_ssl_server_name on;
+            proxy_ssl_name        www.bahn.de;
+            proxy_set_header      Host www.bahn.de;
+            proxy_hide_header    'set-cookie';
+            proxy_pass            https://www.bahn.de/web/api/reisebegleitung/wagenreihung/vehicle-sequence$is_args$args;
+          '';
+
+          "~ ^/db/vendo/(?<vendotarget>[a-z]+)(/([^\\r\\n].*))?$".extraConfig = ''
+            if ($vendopath = no) {
+              return 400;
+            }
+
+            if ($vendotarget = 'trip') {
+              set $vendopath '$vendopath$2';
+            }
+
+            if ($vendotarget = 'location') {
+              set $vendopath '$vendopath$2';
+            }
+
+            set $vendodomain 'app.vendo.noncd.db.de';
+
+            proxy_ssl_server_name on;
+            proxy_ssl_name        $vendodomain;
+            proxy_set_header      Host $vendodomain;
+            proxy_hide_header    'set-cookie';
+            proxy_pass            https://$vendodomain$vendopath;
+          '';
+
+          "~ ^/hafas/(?<hafastarget>.*)$".extraConfig = ''
+            if ($hafasurl = no) {
+              return 400;
+            }
+
+            proxy_ssl_server_name on;
+            proxy_ssl_name        $hafasurl;
+            proxy_set_header      Host $hafasurl;
+            proxy_hide_header    'set-cookie';
+            proxy_pass            https://$hafasurl$hafaspath;
+          '';
+        };
       };
     };
   };
diff --git a/config/nixos/modules/websites/prometheus.infra.zaphyra.eu.nix b/config/nixos/modules/websites/prometheus.infra.zaphyra.eu.nix
@@ -1,10 +1,8 @@
 {
   inputs,
   povSelf,
-  hostConfig,
   config,
   lib,
-  dnsNix,
   ...
 }:
 

@@ -55,12 +53,10 @@ in
           metrics_path = "/node-exporter";
           static_configs = [
             {
-              targets = (
-                lib.mapAttrsToList (
-                  name: host:
-                  lib.mkIf host.config.modules.services.prometheusExporters.enable host.config.modules.services.prometheusExporters.domain
-                ) inputs.self.zaphyraHosts
-              );
+              targets = lib.mapAttrsToList (
+                _name: host:
+                lib.mkIf host.config.modules.services.prometheusExporters.enable host.config.modules.services.prometheusExporters.domain
+              ) inputs.self.zaphyraHosts;
             }
           ];
         }

@@ -71,12 +67,10 @@ in
           metrics_path = "/systemd-exporter";
           static_configs = [
             {
-              targets = (
-                lib.mapAttrsToList (
-                  name: host:
-                  lib.mkIf host.config.modules.services.prometheusExporters.enable host.config.modules.services.prometheusExporters.domain
-                ) inputs.self.zaphyraHosts
-              );
+              targets = lib.mapAttrsToList (
+                _name: host:
+                lib.mkIf host.config.modules.services.prometheusExporters.enable host.config.modules.services.prometheusExporters.domain
+              ) inputs.self.zaphyraHosts;
             }
           ];
         }
diff --git a/config/nixos/modules/websites/restic.novus.infra.zaphyra.eu.nix b/config/nixos/modules/websites/restic.novus.infra.zaphyra.eu.nix
@@ -1,9 +1,7 @@
 {
   povSelf,
-  hostConfig,
   config,
   lib,
-  dnsNix,
   ...
 }:
 
diff --git a/config/nixos/modules/websites/things.zaphyra.eu.nix b/config/nixos/modules/websites/things.zaphyra.eu.nix
@@ -1,8 +1,6 @@
 {
   povSelf,
-  hostConfig,
   config,
-  pkgs,
   lib,
   ...
 }:

@@ -34,6 +32,11 @@ in
 
     sops.secrets."resticPasswords/things" = { };
 
+    users = {
+      users.things.uid = 512;
+      groups.things.gid = 512;
+    };
+
     modules.filesystem.impermanence.system.dirs = [
       {
         directory = "/var/lib/things";
diff --git a/config/nixos/modules/websites/vault.zaphyra.eu.nix b/config/nixos/modules/websites/vault.zaphyra.eu.nix
@@ -1,6 +1,5 @@
 {
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,

@@ -32,6 +31,11 @@ in
   config = lib.mkIf cfg.enable {
     dns.zones."${cfg.domain}".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ];
 
+    users = {
+      users.vaultwarden.uid = 523;
+      groups.vaultwarden.gid = 523;
+    };
+
     modules.filesystem.impermanence.system.dirs = [
       {
         directory = "/var/lib/vaultwarden";
diff --git a/config/nixos/modules/websites/zaphyra.dn42.nix b/config/nixos/modules/websites/zaphyra.dn42.nix
@@ -1,10 +1,8 @@
 {
   povSelf,
-  hostConfig,
   config,
   pkgs,
   lib,
-  dnsNix,
   ...
 }:
 
diff --git a/config/nixosModules.nix b/config/nixosModules.nix
@@ -17,7 +17,7 @@ let
       (
         _:
         lib.mapAttrs (
-          name: value:
+          _name: value:
           (
             if value ? option then
               (

@@ -30,15 +30,13 @@ let
               (
                 (lib.removeAttrs value [ "options" ])
                 // {
-                  nixosOptions = (
-                    lib.mapAttrsRecursiveCond (element: !(element ? type)) (
-                      path: value: lib.mkOption value
-                    ) value.options
-                  );
+                  nixosOptions = lib.mapAttrsRecursiveCond (element: !(element ? type)) (
+                    _path: value: lib.mkOption value
+                  ) value.options;
                 }
               )
             else
-              (value)
+              value
           )
         )
       )

@@ -61,13 +59,13 @@ let
 in
 {
 
-  options = modules.options;
+  inherit (modules) options;
 
   config = lib.mkMerge (
-    modules
-    |> lib.filterAttrs (name: value: name != "options")
-    |> lib.collect (element: element ? config)
-    |> lib.map (element: element.config)
+    lib.pipe (lib.removeAttrs modules [ "options" ]) [
+      (lib.collect (element: element ? config))
+      (lib.map (element: element.config))
+    ]
   );
 
 }
diff --git a/flake.lock b/flake.lock
@@ -1,5 +1,25 @@
 {
   "nodes": {
+    "airpodsctl": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1755107314,
+        "narHash": "sha256-jms1UdiI2acoi488wKevmiGJp47us+KKIU0EO/CyqmY=",
+        "ref": "refs/heads/main",
+        "rev": "434af35e4bcf926824b333e71c4abd59cfef701c",
+        "revCount": 3,
+        "type": "git",
+        "url": "https://git.zaphyra.eu/airpodsctl"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://git.zaphyra.eu/airpodsctl"
+      }
+    },
     "attic": {
       "inputs": {
         "crane": "crane",

@@ -10,11 +30,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1738524606,
-        "narHash": "sha256-hPYEJ4juK3ph7kbjbvv7PlU1D9pAkkhl+pwx8fZY53U=",
+        "lastModified": 1752217044,
+        "narHash": "sha256-5TomR72rn4q+5poQcN6EnanxeXKqJSqWVAoDAFN0lUc=",
         "owner": "zhaofengli",
         "repo": "attic",
-        "rev": "ff8a897d1f4408ebbf4d45fa9049c06b3e1e3f4e",
+        "rev": "24fad0622fc9404c69e83bab7738359c5be4988e",
         "type": "github"
       },
       "original": {

@@ -24,6 +44,142 @@
         "type": "github"
       }
     },
+    "base16": {
+      "inputs": {
+        "fromYaml": "fromYaml"
+      },
+      "locked": {
+        "lastModified": 1746562888,
+        "narHash": "sha256-YgNJQyB5dQiwavdDFBMNKk1wyS77AtdgDk/VtU6wEaI=",
+        "owner": "SenchoPens",
+        "repo": "base16.nix",
+        "rev": "806a1777a5db2a1ef9d5d6f493ef2381047f2b89",
+        "type": "github"
+      },
+      "original": {
+        "owner": "SenchoPens",
+        "repo": "base16.nix",
+        "type": "github"
+      }
+    },
+    "base16-fish": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1754405784,
+        "narHash": "sha256-l9xHIy+85FN+bEo6yquq2IjD1rSg9fjfjpyGP1W8YXo=",
+        "owner": "tomyun",
+        "repo": "base16-fish",
+        "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tomyun",
+        "repo": "base16-fish",
+        "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561",
+        "type": "github"
+      }
+    },
+    "base16-fish_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1754405784,
+        "narHash": "sha256-l9xHIy+85FN+bEo6yquq2IjD1rSg9fjfjpyGP1W8YXo=",
+        "owner": "tomyun",
+        "repo": "base16-fish",
+        "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tomyun",
+        "repo": "base16-fish",
+        "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561",
+        "type": "github"
+      }
+    },
+    "base16-helix": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1748408240,
+        "narHash": "sha256-9M2b1rMyMzJK0eusea0x3lyh3mu5nMeEDSc4RZkGm+g=",
+        "owner": "tinted-theming",
+        "repo": "base16-helix",
+        "rev": "6c711ab1a9db6f51e2f6887cc3345530b33e152e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "base16-helix",
+        "type": "github"
+      }
+    },
+    "base16-helix_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1752979451,
+        "narHash": "sha256-0CQM+FkYy0fOO/sMGhOoNL80ftsAzYCg9VhIrodqusM=",
+        "owner": "tinted-theming",
+        "repo": "base16-helix",
+        "rev": "27cf1e66e50abc622fb76a3019012dc07c678fac",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "base16-helix",
+        "type": "github"
+      }
+    },
+    "base16-vim": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1732806396,
+        "narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=",
+        "owner": "tinted-theming",
+        "repo": "base16-vim",
+        "rev": "577fe8125d74ff456cf942c733a85d769afe58b7",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "base16-vim",
+        "rev": "577fe8125d74ff456cf942c733a85d769afe58b7",
+        "type": "github"
+      }
+    },
+    "base16-vim_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1732806396,
+        "narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=",
+        "owner": "tinted-theming",
+        "repo": "base16-vim",
+        "rev": "577fe8125d74ff456cf942c733a85d769afe58b7",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "base16-vim",
+        "rev": "577fe8125d74ff456cf942c733a85d769afe58b7",
+        "type": "github"
+      }
+    },
+    "base16_2": {
+      "inputs": {
+        "fromYaml": "fromYaml_2"
+      },
+      "locked": {
+        "lastModified": 1755819240,
+        "narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=",
+        "owner": "SenchoPens",
+        "repo": "base16.nix",
+        "rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "SenchoPens",
+        "repo": "base16.nix",
+        "type": "github"
+      }
+    },
     "blobs": {
       "flake": false,
       "locked": {

@@ -40,20 +196,29 @@
         "type": "gitlab"
       }
     },
-    "crane": {
-      "inputs": {
-        "nixpkgs": [
-          "grapevine",
-          "attic",
-          "nixpkgs"
-        ]
+    "blobs_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1604995301,
+        "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=",
+        "owner": "simple-nixos-mailserver",
+        "repo": "blobs",
+        "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265",
+        "type": "gitlab"
       },
+      "original": {
+        "owner": "simple-nixos-mailserver",
+        "repo": "blobs",
+        "type": "gitlab"
+      }
+    },
+    "crane": {
       "locked": {
-        "lastModified": 1722960479,
-        "narHash": "sha256-NhCkJJQhD5GUib8zN9JrmYGMwt4lCRp6ZVNzIiYCl0Y=",
+        "lastModified": 1751562746,
+        "narHash": "sha256-smpugNIkmDeicNz301Ll1bD7nFOty97T79m4GUMUczA=",
         "owner": "ipetkov",
         "repo": "crane",
-        "rev": "4c6c77920b8d44cd6660c1621dea6b3fc4b4c4f4",
+        "rev": "aed2020fd3dc26e1e857d4107a5a67a33ab6c1fd",
         "type": "github"
       },
       "original": {

@@ -64,11 +229,11 @@
     },
     "crane_2": {
       "locked": {
-        "lastModified": 1742394900,
-        "narHash": "sha256-vVOAp9ahvnU+fQoKd4SEXB2JG2wbENkpqcwlkIXgUC0=",
+        "lastModified": 1752946753,
+        "narHash": "sha256-g5uP3jIj+STUcfTJDKYopxnSijs2agRg13H0SGL5iE4=",
         "owner": "ipetkov",
         "repo": "crane",
-        "rev": "70947c1908108c0c551ddfd73d4f750ff2ea67cd",
+        "rev": "544d09fecc8c2338542c57f3f742f1a0c8c71e13",
         "type": "github"
       },
       "original": {

@@ -93,6 +258,21 @@
         "type": "github"
       }
     },
+    "crane_4": {
+      "locked": {
+        "lastModified": 1754269165,
+        "narHash": "sha256-0tcS8FHd4QjbCVoxN9jI+PjHgA4vc/IjkUSp+N3zy0U=",
+        "owner": "ipetkov",
+        "repo": "crane",
+        "rev": "444e81206df3f7d92780680e45858e31d2f07a08",
+        "type": "github"
+      },
+      "original": {
+        "owner": "ipetkov",
+        "repo": "crane",
+        "type": "github"
+      }
+    },
     "deploy-rs": {
       "inputs": {
         "flake-compat": [

@@ -106,11 +286,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749105467,
-        "narHash": "sha256-hXh76y/wDl15almBcqvjryB50B0BaiXJKk20f314RoE=",
+        "lastModified": 1762286984,
+        "narHash": "sha256-9I2H9x5We6Pl+DBYHjR1s3UT8wgwcpAH03kn9CqtdQc=",
         "owner": "serokell",
         "repo": "deploy-rs",
-        "rev": "6bc76b872374845ba9d645a2f012b764fecd765f",
+        "rev": "9c870f63e28ec1e83305f7f6cb73c941e699f74f",
         "type": "github"
       },
       "original": {

@@ -126,11 +306,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749436314,
-        "narHash": "sha256-CqmqU5FRg5AadtIkxwu8ulDSOSoIisUMZRLlcED3Q5w=",
+        "lastModified": 1762276996,
+        "narHash": "sha256-TtcPgPmp2f0FAnc+DMEw4ardEgv1SGNR3/WFGH0N19M=",
         "owner": "nix-community",
         "repo": "disko",
-        "rev": "dfa4d1b9c39c0342ef133795127a3af14598017a",
+        "rev": "af087d076d3860760b3323f6b583f4d828c1ac17",
         "type": "github"
       },
       "original": {

@@ -146,11 +326,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749436314,
-        "narHash": "sha256-CqmqU5FRg5AadtIkxwu8ulDSOSoIisUMZRLlcED3Q5w=",
+        "lastModified": 1762276996,
+        "narHash": "sha256-TtcPgPmp2f0FAnc+DMEw4ardEgv1SGNR3/WFGH0N19M=",
         "owner": "nix-community",
         "repo": "disko",
-        "rev": "dfa4d1b9c39c0342ef133795127a3af14598017a",
+        "rev": "af087d076d3860760b3323f6b583f4d828c1ac17",
         "type": "github"
       },
       "original": {

@@ -179,6 +359,28 @@
         "url": "https://git.zaphyra.eu/dns.nix"
       }
     },
+    "emacs-overlay": {
+      "inputs": {
+        "nixpkgs": [
+          "tgcNUR",
+          "nixpkgs"
+        ],
+        "nixpkgs-stable": "nixpkgs-stable_3"
+      },
+      "locked": {
+        "lastModified": 1754361940,
+        "narHash": "sha256-2KROQdENN8Ix5kiBZRM8FQP1KiJDikKPTiaaExYdVAY=",
+        "owner": "nix-community",
+        "repo": "emacs-overlay",
+        "rev": "a9a667084c0cf89081842d3002aef7b4829980aa",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "emacs-overlay",
+        "type": "github"
+      }
+    },
     "fenix": {
       "inputs": {
         "nixpkgs": [

@@ -188,11 +390,11 @@
         "rust-analyzer-src": "rust-analyzer-src"
       },
       "locked": {
-        "lastModified": 1742452566,
-        "narHash": "sha256-sVuLDQ2UIWfXUBbctzrZrXM2X05YjX08K7XHMztt36E=",
+        "lastModified": 1752993983,
+        "narHash": "sha256-3YKCySMNhFDdHbFiRS4QbEwk0U5l42NMD1scDtniESY=",
         "owner": "nix-community",
         "repo": "fenix",
-        "rev": "7d9ba794daf5e8cc7ee728859bc688d8e26d5f06",
+        "rev": "62105e0745d7450976b26dbd1497b8cbe15eb9ff",
         "type": "github"
       },
       "original": {

@@ -202,19 +404,51 @@
         "type": "github"
       }
     },
+    "firefox-gnome-theme": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1748383148,
+        "narHash": "sha256-pGvD/RGuuPf/4oogsfeRaeMm6ipUIznI2QSILKjKzeA=",
+        "owner": "rafaelmardojai",
+        "repo": "firefox-gnome-theme",
+        "rev": "4eb2714fbed2b80e234312611a947d6cb7d70caf",
+        "type": "github"
+      },
+      "original": {
+        "owner": "rafaelmardojai",
+        "repo": "firefox-gnome-theme",
+        "type": "github"
+      }
+    },
+    "firefox-gnome-theme_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1758112371,
+        "narHash": "sha256-lizRM2pj6PHrR25yimjyFn04OS4wcdbc38DCdBVa2rk=",
+        "owner": "rafaelmardojai",
+        "repo": "firefox-gnome-theme",
+        "rev": "0909cfe4a2af8d358ad13b20246a350e14c2473d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "rafaelmardojai",
+        "repo": "firefox-gnome-theme",
+        "type": "github"
+      }
+    },
     "firefoxGnomeTheme": {
       "flake": false,
       "locked": {
-        "lastModified": 1743774811,
-        "narHash": "sha256-oiHLDHXq7ymsMVYSg92dD1OLnKLQoU/Gf2F1GoONLCE=",
+        "lastModified": 1752607306,
+        "narHash": "sha256-/pTDAny47X1og2pSAoMY/GfJ9teSOEQZAENhszPJMKo=",
         "owner": "rafaelmardojai",
         "repo": "firefox-gnome-theme",
-        "rev": "df53a7a31872faf5ca53dd0730038a62ec63ca9e",
+        "rev": "0382100f9e50633ee832535b25b3bd022245a255",
         "type": "github"
       },
       "original": {
         "owner": "rafaelmardojai",
-        "ref": "v137",
+        "ref": "v140",
         "repo": "firefox-gnome-theme",
         "type": "github"
       }

@@ -222,11 +456,11 @@
     "flake-compat": {
       "flake": false,
       "locked": {
-        "lastModified": 1696426674,
-        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "lastModified": 1747046372,
+        "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
         "owner": "edolstra",
         "repo": "flake-compat",
-        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
         "type": "github"
       },
       "original": {

@@ -244,11 +478,53 @@
         ]
       },
       "locked": {
-        "lastModified": 1722555600,
-        "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
+        "lastModified": 1751413152,
+        "narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "77826244401ea9de6e3bac47c2db46005e1f30b5",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "type": "github"
+      }
+    },
+    "flake-parts_2": {
+      "inputs": {
+        "nixpkgs-lib": [
+          "stylix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1749398372,
+        "narHash": "sha256-tYBdgS56eXYaWVW3fsnPQ/nFlgWi/Z2Ymhyu21zVM98=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "9305fe4e5c2a6fcf5ba6a3ff155720fbe4076569",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "type": "github"
+      }
+    },
+    "flake-parts_3": {
+      "inputs": {
+        "nixpkgs-lib": [
+          "stylixUnstable",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1756770412,
+        "narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
+        "rev": "4524271976b625a4a605beefd893f270620fd751",
         "type": "github"
       },
       "original": {

@@ -259,11 +535,11 @@
     },
     "flakeCompat": {
       "locked": {
-        "lastModified": 1747046372,
-        "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
+        "lastModified": 1761588595,
+        "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
         "owner": "edolstra",
         "repo": "flake-compat",
-        "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
+        "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
         "type": "github"
       },
       "original": {

@@ -279,11 +555,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749398372,
-        "narHash": "sha256-tYBdgS56eXYaWVW3fsnPQ/nFlgWi/Z2Ymhyu21zVM98=",
+        "lastModified": 1762440070,
+        "narHash": "sha256-xxdepIcb39UJ94+YydGP221rjnpkDZUlykKuF54PsqI=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "9305fe4e5c2a6fcf5ba6a3ff155720fbe4076569",
+        "rev": "26d05891e14c88eb4a5d5bee659c0db5afb609d8",
         "type": "github"
       },
       "original": {

@@ -347,6 +623,38 @@
         "url": "https://git.zaphyra.eu/flauschehorn.sexy"
       }
     },
+    "fromYaml": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1731966426,
+        "narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=",
+        "owner": "SenchoPens",
+        "repo": "fromYaml",
+        "rev": "106af9e2f715e2d828df706c386a685698f3223b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "SenchoPens",
+        "repo": "fromYaml",
+        "type": "github"
+      }
+    },
+    "fromYaml_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1731966426,
+        "narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=",
+        "owner": "SenchoPens",
+        "repo": "fromYaml",
+        "rev": "106af9e2f715e2d828df706c386a685698f3223b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "SenchoPens",
+        "repo": "fromYaml",
+        "type": "github"
+      }
+    },
     "git-hooks": {
       "inputs": {
         "flake-compat": [

@@ -373,6 +681,32 @@
         "type": "github"
       }
     },
+    "git-hooks_2": {
+      "inputs": {
+        "flake-compat": [
+          "simpleNixosMailserverUnstable",
+          "flake-compat"
+        ],
+        "gitignore": "gitignore_3",
+        "nixpkgs": [
+          "simpleNixosMailserverUnstable",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1760663237,
+        "narHash": "sha256-BflA6U4AM1bzuRMR8QqzPXqh8sWVCNDzOdsxXEguJIc=",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "type": "github"
+      }
+    },
     "gitignore": {
       "inputs": {
         "nixpkgs": [

@@ -417,33 +751,89 @@
         "type": "github"
       }
     },
-    "gpxMap": {
+    "gitignore_3": {
       "inputs": {
         "nixpkgs": [
+          "simpleNixosMailserverUnstable",
+          "git-hooks",
           "nixpkgs"
         ]
       },
       "locked": {
-        "lastModified": 1741208528,
-        "narHash": "sha256-HDgOvxva+fOZ8fmtJpwG64oRQSXVlGRTmH6LtEknXJc=",
-        "ref": "refs/heads/master",
-        "rev": "368358b4facb8bc55311250926eef78b0328b9a0",
-        "revCount": 6,
-        "type": "git",
-        "url": "https://git.zaphyra.eu/gpx-map"
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+        "type": "github"
       },
       "original": {
-        "type": "git",
-        "url": "https://git.zaphyra.eu/gpx-map"
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "type": "github"
       }
     },
-    "grapevine": {
-      "inputs": {
-        "attic": "attic",
-        "crane": "crane_2",
-        "fenix": "fenix",
-        "flake-compat": [
-          "flakeCompat"
+    "gnome-shell": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1744584021,
+        "narHash": "sha256-0RJ4mJzf+klKF4Fuoc8VN8dpQQtZnKksFmR2jhWE1Ew=",
+        "owner": "GNOME",
+        "repo": "gnome-shell",
+        "rev": "52c517c8f6c199a1d6f5118fae500ef69ea845ae",
+        "type": "github"
+      },
+      "original": {
+        "owner": "GNOME",
+        "ref": "48.1",
+        "repo": "gnome-shell",
+        "type": "github"
+      }
+    },
+    "gnome-shell_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1748186689,
+        "narHash": "sha256-UaD7Y9f8iuLBMGHXeJlRu6U1Ggw5B9JnkFs3enZlap0=",
+        "owner": "GNOME",
+        "repo": "gnome-shell",
+        "rev": "8c88f917db0f1f0d80fa55206c863d3746fa18d0",
+        "type": "github"
+      },
+      "original": {
+        "owner": "GNOME",
+        "ref": "48.2",
+        "repo": "gnome-shell",
+        "type": "github"
+      }
+    },
+    "gpxMap": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1741208528,
+        "narHash": "sha256-HDgOvxva+fOZ8fmtJpwG64oRQSXVlGRTmH6LtEknXJc=",
+        "ref": "refs/heads/master",
+        "rev": "368358b4facb8bc55311250926eef78b0328b9a0",
+        "revCount": 6,
+        "type": "git",
+        "url": "https://git.zaphyra.eu/gpx-map"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://git.zaphyra.eu/gpx-map"
+      }
+    },
+    "grapevine": {
+      "inputs": {
+        "attic": "attic",
+        "crane": "crane_2",
+        "fenix": "fenix",
+        "flake-compat": [
+          "flakeCompat"
         ],
         "flake-utils": [
           "flakeUtils"

@@ -456,17 +846,16 @@
       },
       "locked": {
         "host": "gitlab.computer.surgery",
-        "lastModified": 1748889509,
-        "narHash": "sha256-B63X60UQljp8s5TKwPZaGt7AY5FKJJeAyNvLgQ1M87M=",
+        "lastModified": 1756571888,
+        "narHash": "sha256-NnbMYflrTddWEaD2Wm5dpFIaWG1e0KN0322WeyAmyTI=",
         "owner": "matrix",
         "repo": "grapevine",
-        "rev": "5125c32edb8baac3fa269c08cc6f4858fe39c330",
+        "rev": "c4abca1eb554e1a1edb9b6adb8f968db5f9d53c2",
         "type": "gitlab"
       },
       "original": {
         "host": "gitlab.computer.surgery",
         "owner": "matrix",
-        "ref": "lambda/sss",
         "repo": "grapevine",
         "type": "gitlab"
       }

@@ -491,6 +880,27 @@
         "url": "https://git.zaphyra.eu/haumea"
       }
     },
+    "home-manager": {
+      "inputs": {
+        "nixpkgs": [
+          "sherlock",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1754842705,
+        "narHash": "sha256-2vvncPLsBWV6dRM5LfGHMGYZ+vzqRDqSPBzxPAS0R/A=",
+        "owner": "nix-community",
+        "repo": "home-manager",
+        "rev": "91586008a23c01cc32894ee187dca8c0a7bd20a4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "home-manager",
+        "type": "github"
+      }
+    },
     "homeManager": {
       "inputs": {
         "nixpkgs": [

@@ -498,11 +908,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749154018,
-        "narHash": "sha256-gjN3j7joRvT3a8Zgcylnd4NFsnXeDBumqiu4HmY1RIg=",
+        "lastModified": 1758463745,
+        "narHash": "sha256-uhzsV0Q0I9j2y/rfweWeGif5AWe0MGrgZ/3TjpDYdGA=",
         "owner": "nix-community",
         "repo": "home-manager",
-        "rev": "7aae0ee71a17b19708b93b3ed448a1a0952bf111",
+        "rev": "3b955f5f0a942f9f60cdc9cacb7844335d0f21c3",
         "type": "github"
       },
       "original": {

@@ -519,11 +929,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749944797,
-        "narHash": "sha256-1l6ZW+2+LDQhYgE4fo2KsM2Ms3lY3ZXv0n6uKka2yMk=",
+        "lastModified": 1762463325,
+        "narHash": "sha256-33YUsWpPyeBZEWrKQ2a1gkRZ7i0XCC/2MYpU6BVeQSU=",
         "owner": "nix-community",
         "repo": "home-manager",
-        "rev": "c5f345153397f62170c18ded1ae1f0875201d49a",
+        "rev": "0562fef070a1027325dd4ea10813d64d2c967b39",
         "type": "github"
       },
       "original": {

@@ -581,11 +991,11 @@
     "lix": {
       "flake": false,
       "locked": {
-        "lastModified": 1748977700,
-        "narHash": "sha256-ODiHqMVHYjRageIqfiZB8snzLb1kxo1E4/49YqC2hvQ=",
-        "rev": "2387104452d97a027a75db011a3e104a941d0c77",
+        "lastModified": 1753306924,
+        "narHash": "sha256-jLCEW0FvjFhC+c4RHzH+xbkSOxrnpFHnhjOw6sudhx0=",
+        "rev": "1a4393d0aac31aba21f5737ede1b171e11336d77",
         "type": "tarball",
-        "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/2387104452d97a027a75db011a3e104a941d0c77.tar.gz?rev=2387104452d97a027a75db011a3e104a941d0c77"
+        "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/1a4393d0aac31aba21f5737ede1b171e11336d77.tar.gz?rev=1a4393d0aac31aba21f5737ede1b171e11336d77"
       },
       "original": {
         "type": "tarball",

@@ -606,11 +1016,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1748803223,
-        "narHash": "sha256-FXndw1CihZcqQu49DziuMQuc0fG8L0nvGkm0JHZKimo=",
+        "lastModified": 1756125859,
+        "narHash": "sha256-6a+PWILmqHCs9B5eIBLg6HSZ8jYweZpgOWO8FlyVwYI=",
         "ref": "release-2.93",
-        "rev": "2226eb3b97f0f89fdcd5bf2d0a2c7723cf771a62",
-        "revCount": 145,
+        "rev": "d3292125035b04df00d01549a26e948631fabe1e",
+        "revCount": 156,
         "type": "git",
         "url": "https://git.lix.systems/lix-project/nixos-module"
       },

@@ -640,6 +1050,66 @@
         "url": "https://git.zaphyra.eu/mqtt-webui"
       }
     },
+    "niri-stable": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1756556321,
+        "narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=",
+        "owner": "YaLTeR",
+        "repo": "niri",
+        "rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294",
+        "type": "github"
+      },
+      "original": {
+        "owner": "YaLTeR",
+        "ref": "v25.08",
+        "repo": "niri",
+        "type": "github"
+      }
+    },
+    "niri-unstable": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1762492604,
+        "narHash": "sha256-cjXYF5+gGaapr6d1Jz70GZQVzK4qzwDUwU86p9+H2mM=",
+        "owner": "YaLTeR",
+        "repo": "niri",
+        "rev": "2144f9a6ae7b675213f9bd86d0989c334baa1c00",
+        "type": "github"
+      },
+      "original": {
+        "owner": "YaLTeR",
+        "repo": "niri",
+        "type": "github"
+      }
+    },
+    "niriFlake": {
+      "inputs": {
+        "niri-stable": "niri-stable",
+        "niri-unstable": "niri-unstable",
+        "nixpkgs": [
+          "nixpkgsUnstable"
+        ],
+        "nixpkgs-stable": [
+          "nixpkgs"
+        ],
+        "xwayland-satellite-stable": "xwayland-satellite-stable",
+        "xwayland-satellite-unstable": "xwayland-satellite-unstable"
+      },
+      "locked": {
+        "lastModified": 1762540449,
+        "narHash": "sha256-AZ/xrJ5JXvpRQYyiVf8Hx4lzFBQAaH9l0utOfvAA28I=",
+        "owner": "sodiboo",
+        "repo": "niri-flake",
+        "rev": "75bacb66302bca38fa6e0c180f1e5369a8115454",
+        "type": "github"
+      },
+      "original": {
+        "owner": "sodiboo",
+        "repo": "niri-flake",
+        "type": "github"
+      }
+    },
     "nix-filter": {
       "locked": {
         "lastModified": 1731533336,

@@ -665,11 +1135,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1729742964,
-        "narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
+        "lastModified": 1737420293,
+        "narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=",
         "owner": "nix-community",
         "repo": "nix-github-actions",
-        "rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
+        "rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9",
         "type": "github"
       },
       "original": {

@@ -708,13 +1178,28 @@
         "type": "github"
       }
     },
+    "nixos-hardware": {
+      "locked": {
+        "lastModified": 1762463231,
+        "narHash": "sha256-hv1mG5j5PTbnWbtHHomzTus77pIxsc4x8VrMjc7+/YE=",
+        "owner": "NixOS",
+        "repo": "nixos-hardware",
+        "rev": "52113c4f5cfd1e823001310e56d9c8d0699a6226",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "repo": "nixos-hardware",
+        "type": "github"
+      }
+    },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1726042813,
-        "narHash": "sha256-LnNKCCxnwgF+575y0pxUdlGZBO/ru1CtGHIqQVfvjlA=",
+        "lastModified": 1751949589,
+        "narHash": "sha256-mgFxAPLWw0Kq+C8P3dRrZrOYEQXOtKuYVlo9xvPntt8=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "159be5db480d1df880a0135ca0bfed84c2f88353",
+        "rev": "9b008d60392981ad674e04016d25619281550a9d",
         "type": "github"
       },
       "original": {

@@ -726,16 +1211,16 @@
     },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1724316499,
-        "narHash": "sha256-Qb9MhKBUTCfWg/wqqaxt89Xfi6qTD3XpTzQ9eXi3JmE=",
+        "lastModified": 1751741127,
+        "narHash": "sha256-t75Shs76NgxjZSgvvZZ9qOmz5zuBE8buUaYD28BMTxg=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "797f7dc49e0bc7fab4b57c021cdf68f595e47841",
+        "rev": "29e290002bfff26af1db6f64d070698019460302",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-24.05",
+        "ref": "nixos-25.05",
         "repo": "nixpkgs",
         "type": "github"
       }

@@ -756,13 +1241,29 @@
         "type": "github"
       }
     },
+    "nixpkgs-stable_3": {
+      "locked": {
+        "lastModified": 1751274312,
+        "narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-24.11",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
     "nixpkgsUnstable": {
       "locked": {
-        "lastModified": 1749903597,
-        "narHash": "sha256-jp0D4vzBcRKwNZwfY4BcWHemLGUs4JrS3X9w5k/JYDA=",
+        "lastModified": 1762361079,
+        "narHash": "sha256-lz718rr1BDpZBYk7+G8cE6wee3PiBUpn8aomG/vLLiY=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "41da1e3ea8e23e094e5e3eeb1e6b830468a7399e",
+        "rev": "ffcdcf99d65c61956d882df249a9be53e5902ea5",
         "type": "github"
       },
       "original": {

@@ -774,11 +1275,11 @@
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1749857119,
-        "narHash": "sha256-tG5xUn3hFaPpAHYIvr2F88b+ovcIO5k1HqajFy7ZFPM=",
+        "lastModified": 1762498405,
+        "narHash": "sha256-Zg/SCgCaAioc0/SVZQJxuECGPJy+OAeBcGeA5okdYDc=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "5f4f306bea96741f1588ea4f450b2a2e29f42b98",
+        "rev": "6faeb062ee4cf4f105989d490831713cc5a43ee1",
         "type": "github"
       },
       "original": {

@@ -788,6 +1289,57 @@
         "type": "github"
       }
     },
+    "nur": {
+      "inputs": {
+        "flake-parts": [
+          "stylix",
+          "flake-parts"
+        ],
+        "nixpkgs": [
+          "stylix",
+          "nixpkgs"
+        ],
+        "treefmt-nix": "treefmt-nix"
+      },
+      "locked": {
+        "lastModified": 1751320053,
+        "narHash": "sha256-3m6RMw0FbbaUUa01PNaMLoO7D99aBClmY5ed9V3vz+0=",
+        "owner": "nix-community",
+        "repo": "NUR",
+        "rev": "cbde1735782f9c2bb2c63d5e05fba171a14a4670",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "NUR",
+        "type": "github"
+      }
+    },
+    "nur_2": {
+      "inputs": {
+        "flake-parts": [
+          "stylixUnstable",
+          "flake-parts"
+        ],
+        "nixpkgs": [
+          "stylixUnstable",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1758998580,
+        "narHash": "sha256-VLx0z396gDCGSiowLMFz5XRO/XuNV+4EnDYjdJhHvUk=",
+        "owner": "nix-community",
+        "repo": "NUR",
+        "rev": "ba8d9c98f5f4630bcb0e815ab456afd90c930728",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "NUR",
+        "type": "github"
+      }
+    },
     "oeffisearch": {
       "inputs": {
         "nixpkgs": [

@@ -795,11 +1347,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1748350477,
-        "narHash": "sha256-wI2yOnwxFeaL2QjmFidbbWnavGlgSMU/RYq5bIBkCno=",
+        "lastModified": 1762373864,
+        "narHash": "sha256-SXKWGfZJVkR9DTiy/QTm4D4OjlMZKV1Rfj0F44iFsZ0=",
         "ref": "refs/heads/main",
-        "rev": "ee710b35cfc6a07a7f8d8a7c64def9c833f0ba66",
-        "revCount": 294,
+        "rev": "f8cec391709adfd94f66342412318a047b75ebd1",
+        "revCount": 301,
         "type": "git",
         "url": "https://git.zaphyra.eu/oeffisearch"
       },

@@ -838,22 +1390,23 @@
     "rocksdb": {
       "flake": false,
       "locked": {
-        "lastModified": 1734381914,
-        "narHash": "sha256-G+DlQwEUyd7JOCjS1Hg1cKWmA/qAiK8UpUIKcP+riGQ=",
+        "lastModified": 1752084860,
+        "narHash": "sha256-mKh6zsmxsiUix4LX+npiytmKvLbo6WNA9y4Ns/EY+bE=",
         "owner": "facebook",
         "repo": "rocksdb",
-        "rev": "ae8fb3e5000e46d8d4c9dbf3a36019c0aaceebff",
+        "rev": "410c5623195ecbe4699b9b5a5f622c7325cec6fe",
         "type": "github"
       },
       "original": {
         "owner": "facebook",
-        "ref": "v9.10.0",
+        "ref": "v10.4.2",
         "repo": "rocksdb",
         "type": "github"
       }
     },
     "root": {
       "inputs": {
+        "airpodsctl": "airpodsctl",
         "deploy-rs": "deploy-rs",
         "disko": "disko",
         "diskoUnstable": "diskoUnstable",

@@ -873,14 +1426,21 @@
         "lanzaboote": "lanzaboote",
         "lixModule": "lixModule",
         "mqttWebUI": "mqttWebUI",
+        "niriFlake": "niriFlake",
         "nixStd": "nixStd",
         "nixSystemsDefault": "nixSystemsDefault",
+        "nixos-hardware": "nixos-hardware",
         "nixpkgs": "nixpkgs_2",
         "nixpkgsUnstable": "nixpkgsUnstable",
         "oeffisearch": "oeffisearch",
+        "sherlock": "sherlock",
         "simpleNixosMailserver": "simpleNixosMailserver",
+        "simpleNixosMailserverUnstable": "simpleNixosMailserverUnstable",
         "sopsNix": "sopsNix",
         "stagit": "stagit",
+        "stylix": "stylix",
+        "stylixUnstable": "stylixUnstable",
+        "tgcNUR": "tgcNUR",
         "things": "things",
         "zaphyraWebsite": "zaphyraWebsite"
       }

@@ -888,11 +1448,11 @@
     "rust-analyzer-src": {
       "flake": false,
       "locked": {
-        "lastModified": 1742296961,
-        "narHash": "sha256-gCpvEQOrugHWLimD1wTFOJHagnSEP6VYBDspq96Idu0=",
+        "lastModified": 1752913824,
+        "narHash": "sha256-kRpDlijAr4p5VmcPSRw2mfhaBZ4cE3EDWzqLDIbASgA=",
         "owner": "rust-lang",
         "repo": "rust-analyzer",
-        "rev": "15d87419f1a123d8f888d608129c3ce3ff8f13d4",
+        "rev": "ed193af36937d2fd4bb14a815ec589875c5c7304",
         "type": "github"
       },
       "original": {

@@ -923,6 +1483,54 @@
         "type": "github"
       }
     },
+    "rust-overlay_2": {
+      "inputs": {
+        "nixpkgs": [
+          "sherlock",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1754794262,
+        "narHash": "sha256-5SEz135CaJ0LfHILi+CzWMXQmcvD2QeIf4FKwXAxtxA=",
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "rev": "d754da7c068c6e122f84d84c3e6bcd353ee48635",
+        "type": "github"
+      },
+      "original": {
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "type": "github"
+      }
+    },
+    "sherlock": {
+      "inputs": {
+        "crane": "crane_4",
+        "flake-parts": [
+          "flakeParts"
+        ],
+        "home-manager": "home-manager",
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "rust-overlay": "rust-overlay_2"
+      },
+      "locked": {
+        "lastModified": 1755178334,
+        "narHash": "sha256-vW6/4NUnhq9L5VeYRz1DeEF/srFP5mIRV3yIHcCLuX8=",
+        "owner": "Skxxtz",
+        "repo": "sherlock",
+        "rev": "8485f8720352c8ba48a4d74d3d33c882f9c0b35b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "Skxxtz",
+        "repo": "sherlock",
+        "rev": "8485f8720352c8ba48a4d74d3d33c882f9c0b35b",
+        "type": "github"
+      }
+    },
     "simpleNixosMailserver": {
       "inputs": {
         "blobs": "blobs",

@@ -931,18 +1539,18 @@
         ],
         "git-hooks": "git-hooks",
         "nixpkgs": [
-          "nixpkgs"
+          "nixpkgsUnstable"
         ],
         "nixpkgs-25_05": [
           "nixpkgs"
         ]
       },
       "locked": {
-        "lastModified": 1747965231,
-        "narHash": "sha256-BW3ktviEhfCN/z3+kEyzpDKAI8qFTwO7+S0NVA0C90o=",
+        "lastModified": 1755110674,
+        "narHash": "sha256-PigqTAGkdBYXVFWsJnqcirrLeFqRFN4PFigLA8FzxeI=",
         "owner": "simple-nixos-mailserver",
         "repo": "nixos-mailserver",
-        "rev": "53007af63fade28853408370c4c600a63dd97f41",
+        "rev": "f5936247dbdb8501221978562ab0b302dd75456c",
         "type": "gitlab"
       },
       "original": {

@@ -952,6 +1560,31 @@
         "type": "gitlab"
       }
     },
+    "simpleNixosMailserverUnstable": {
+      "inputs": {
+        "blobs": "blobs_2",
+        "flake-compat": [
+          "flakeCompat"
+        ],
+        "git-hooks": "git-hooks_2",
+        "nixpkgs": [
+          "nixpkgsUnstable"
+        ]
+      },
+      "locked": {
+        "lastModified": 1762606669,
+        "narHash": "sha256-torEIZ/MRcvpxbZuw04T6EkpjcZck9Q92tN9MdelbsY=",
+        "owner": "simple-nixos-mailserver",
+        "repo": "nixos-mailserver",
+        "rev": "ed771e37f79329f8840007067c23550b4bb6f823",
+        "type": "gitlab"
+      },
+      "original": {
+        "owner": "simple-nixos-mailserver",
+        "repo": "nixos-mailserver",
+        "type": "gitlab"
+      }
+    },
     "sopsNix": {
       "inputs": {
         "nixpkgs": [

@@ -959,11 +1592,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749592509,
-        "narHash": "sha256-VunQzfZFA+Y6x3wYi2UE4DEQ8qKoAZZCnZPUlSoqC+A=",
+        "lastModified": 1760998189,
+        "narHash": "sha256-ee2e1/AeGL5X8oy/HXsZQvZnae6XfEVdstGopKucYLY=",
         "owner": "Mic92",
         "repo": "sops-nix",
-        "rev": "50754dfaa0e24e313c626900d44ef431f3210138",
+        "rev": "5a7d18b5c55642df5c432aadb757140edfeb70b3",
         "type": "github"
       },
       "original": {

@@ -992,6 +1625,129 @@
         "url": "https://git.zaphyra.eu/stagit"
       }
     },
+    "stylix": {
+      "inputs": {
+        "base16": "base16",
+        "base16-fish": "base16-fish",
+        "base16-helix": "base16-helix",
+        "base16-vim": "base16-vim",
+        "firefox-gnome-theme": "firefox-gnome-theme",
+        "flake-parts": "flake-parts_2",
+        "gnome-shell": "gnome-shell",
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "nur": "nur",
+        "systems": "systems",
+        "tinted-foot": "tinted-foot",
+        "tinted-kitty": "tinted-kitty",
+        "tinted-schemes": "tinted-schemes",
+        "tinted-tmux": "tinted-tmux",
+        "tinted-zed": "tinted-zed"
+      },
+      "locked": {
+        "lastModified": 1762295027,
+        "narHash": "sha256-5z5cGrp9F8g8iyQrM8WkB6pAwP4AaicljKZ15gx+X9Y=",
+        "owner": "nix-community",
+        "repo": "stylix",
+        "rev": "91b9a270523361268ba6a8772152fde31103869f",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "ref": "release-25.05",
+        "repo": "stylix",
+        "type": "github"
+      }
+    },
+    "stylixUnstable": {
+      "inputs": {
+        "base16": "base16_2",
+        "base16-fish": "base16-fish_2",
+        "base16-helix": "base16-helix_2",
+        "base16-vim": "base16-vim_2",
+        "firefox-gnome-theme": "firefox-gnome-theme_2",
+        "flake-parts": "flake-parts_3",
+        "gnome-shell": "gnome-shell_2",
+        "nixpkgs": [
+          "nixpkgsUnstable"
+        ],
+        "nur": "nur_2",
+        "systems": "systems_2",
+        "tinted-foot": "tinted-foot_2",
+        "tinted-kitty": "tinted-kitty_2",
+        "tinted-schemes": "tinted-schemes_2",
+        "tinted-tmux": "tinted-tmux_2",
+        "tinted-zed": "tinted-zed_2"
+      },
+      "locked": {
+        "lastModified": 1762264356,
+        "narHash": "sha256-QVfC53Ri+8n3e7Ujx9kq6all3+TLBRRPRnc6No5qY5w=",
+        "owner": "nix-community",
+        "repo": "stylix",
+        "rev": "647bb8dd96a206a1b79c4fd714affc88b409e10b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "stylix",
+        "type": "github"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "systems_2": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "tgcNUR": {
+      "inputs": {
+        "emacs-overlay": "emacs-overlay",
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "nixpkgsUnstable": [
+          "nixpkgsUnstable"
+        ]
+      },
+      "locked": {
+        "lastModified": 1761148374,
+        "narHash": "sha256-7kcjri4H6o8NPt2NDUkZ7rqi5qCQ2H0gpX+spn+xQtA=",
+        "ref": "refs/heads/main",
+        "rev": "eef9ad6e18a4259866ac293944a6ca00234f9725",
+        "revCount": 70,
+        "type": "git",
+        "url": "https://git.transgirl.cafe/zaphyra/tgc-nix-user-repository"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://git.transgirl.cafe/zaphyra/tgc-nix-user-repository"
+      }
+    },
     "things": {
       "inputs": {
         "nixpkgs": [

@@ -1012,6 +1768,223 @@
         "url": "https://git.zaphyra.eu/things"
       }
     },
+    "tinted-foot": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1726913040,
+        "narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=",
+        "owner": "tinted-theming",
+        "repo": "tinted-foot",
+        "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "tinted-foot",
+        "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
+        "type": "github"
+      }
+    },
+    "tinted-foot_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1726913040,
+        "narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=",
+        "owner": "tinted-theming",
+        "repo": "tinted-foot",
+        "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "tinted-foot",
+        "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
+        "type": "github"
+      }
+    },
+    "tinted-kitty": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1735730497,
+        "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=",
+        "owner": "tinted-theming",
+        "repo": "tinted-kitty",
+        "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "tinted-kitty",
+        "type": "github"
+      }
+    },
+    "tinted-kitty_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1735730497,
+        "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=",
+        "owner": "tinted-theming",
+        "repo": "tinted-kitty",
+        "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "tinted-kitty",
+        "type": "github"
+      }
+    },
+    "tinted-schemes": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1750770351,
+        "narHash": "sha256-LI+BnRoFNRa2ffbe3dcuIRYAUcGklBx0+EcFxlHj0SY=",
+        "owner": "tinted-theming",
+        "repo": "schemes",
+        "rev": "5a775c6ffd6e6125947b393872cde95867d85a2a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "schemes",
+        "type": "github"
+      }
+    },
+    "tinted-schemes_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1757716333,
+        "narHash": "sha256-d4km8W7w2zCUEmPAPUoLk1NlYrGODuVa3P7St+UrqkM=",
+        "owner": "tinted-theming",
+        "repo": "schemes",
+        "rev": "317a5e10c35825a6c905d912e480dfe8e71c7559",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "schemes",
+        "type": "github"
+      }
+    },
+    "tinted-tmux": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1751159871,
+        "narHash": "sha256-UOHBN1fgHIEzvPmdNMHaDvdRMgLmEJh2hNmDrp3d3LE=",
+        "owner": "tinted-theming",
+        "repo": "tinted-tmux",
+        "rev": "bded5e24407cec9d01bd47a317d15b9223a1546c",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "tinted-tmux",
+        "type": "github"
+      }
+    },
+    "tinted-tmux_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1757811970,
+        "narHash": "sha256-n5ZJgmzGZXOD9pZdAl1OnBu3PIqD+X3vEBUGbTi4JiI=",
+        "owner": "tinted-theming",
+        "repo": "tinted-tmux",
+        "rev": "d217ba31c846006e9e0ae70775b0ee0f00aa6b1e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "tinted-tmux",
+        "type": "github"
+      }
+    },
+    "tinted-zed": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1751158968,
+        "narHash": "sha256-ksOyv7D3SRRtebpXxgpG4TK8gZSKFc4TIZpR+C98jX8=",
+        "owner": "tinted-theming",
+        "repo": "base16-zed",
+        "rev": "86a470d94204f7652b906ab0d378e4231a5b3384",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "base16-zed",
+        "type": "github"
+      }
+    },
+    "tinted-zed_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1757811247,
+        "narHash": "sha256-4EFOUyLj85NRL3OacHoLGEo0wjiRJzfsXtR4CZWAn6w=",
+        "owner": "tinted-theming",
+        "repo": "base16-zed",
+        "rev": "824fe0aacf82b3c26690d14e8d2cedd56e18404e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "tinted-theming",
+        "repo": "base16-zed",
+        "type": "github"
+      }
+    },
+    "treefmt-nix": {
+      "inputs": {
+        "nixpkgs": [
+          "stylix",
+          "nur",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1733222881,
+        "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=",
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "rev": "49717b5af6f80172275d47a418c9719a31a78b53",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "type": "github"
+      }
+    },
+    "xwayland-satellite-stable": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1755491097,
+        "narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=",
+        "owner": "Supreeeme",
+        "repo": "xwayland-satellite",
+        "rev": "388d291e82ffbc73be18169d39470f340707edaa",
+        "type": "github"
+      },
+      "original": {
+        "owner": "Supreeeme",
+        "ref": "v0.7",
+        "repo": "xwayland-satellite",
+        "type": "github"
+      }
+    },
+    "xwayland-satellite-unstable": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1762488100,
+        "narHash": "sha256-pD8YqwP0/irHWzJtVElnVljR+OaJPAVbJBwqix+uB5A=",
+        "owner": "Supreeeme",
+        "repo": "xwayland-satellite",
+        "rev": "3cd3edffe1be197326e9314816b16bb4e3d685b1",
+        "type": "github"
+      },
+      "original": {
+        "owner": "Supreeeme",
+        "repo": "xwayland-satellite",
+        "type": "github"
+      }
+    },
     "zaphyraWebsite": {
       "inputs": {
         "nixpkgs": [

@@ -1019,11 +1992,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1750367058,
-        "narHash": "sha256-XG3q7HH9k4JKxhpEm4Znc7kmk0pixOCLVNAYFoTp2nY=",
+        "lastModified": 1756558652,
+        "narHash": "sha256-XnEygmYK/qq8lCWurDai5ys5YMw8SZ8kn33B1LCjogQ=",
         "ref": "refs/heads/main",
-        "rev": "184a9358d76b7e2d967be346652ec895a775a171",
-        "revCount": 23,
+        "rev": "e1f101563113a3b1cf412566edc890c652e92ebd",
+        "revCount": 28,
         "type": "git",
         "url": "https://git.zaphyra.eu/website"
       },
diff --git a/flake.nix b/flake.nix
@@ -2,30 +2,21 @@
 
   description = "A flake for building our infra";
 
-  nixConfig = {
-    # override the default substituters
-    substituters = [
-      "https://cache.nixos.org"
-      "http://lucorum.int.eukaryote.eu:5000"
-    ];
-    trusted-public-keys = [
-      "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
-      "1.hydra.neverstable.net:WgtNg0z0FB7wuWp9nU4gKZpbkW0ug59NlhNp81X7GX0="
-    ];
-  };
+  # nixConfig = {
+  #   extra-substituters = [
+  #     "http://lucorum.int.eukaryote.eu:5000"
+  #   ];
+  #   extra-trusted-public-keys = [
+  #     "1.hydra.neverstable.net:WgtNg0z0FB7wuWp9nU4gKZpbkW0ug59NlhNp81X7GX0="
+  #   ];
+  # };
 
   outputs =
     inputs:
     let
       nixpkgsLib = inputs.nixpkgs.lib;
       unstableNixpkgsLib = inputs.nixpkgsUnstable.lib;
-
-      forAllSystems =
-        function:
-        (nixpkgsLib.genAttrs [
-          "x86_64-linux"
-          "aarch64-linux"
-        ] (system: function inputs.nixpkgs.legacyPackages."${system}"));
+      tgcLib = inputs.tgcNUR.lib;
 
       transformer =
         name: value:

@@ -35,18 +26,17 @@
 
       pathLoader = inputs.haumea.lib.loaders.path;
       importLoader = inputs.haumea.lib.loaders.verbatim;
-      pkgsLoader = pkgs: (path: path: pkgs.callPackage path { });
 
       loadDir = loader: src: inputs.haumea.lib.load { inherit src loader transformer; };
 
     in
     {
 
-      checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks inputs.self.deploy) (
-        nixpkgsLib.filterAttrs (key: value: nixpkgsLib.hasSuffix "linux" key) inputs.deploy-rs.lib
-      );
+      formatter = tgcLib.forAllSystems { body = pkgs: pkgs.nixfmt-rfc-style; };
 
-      formatter = forAllSystems (pkgs: pkgs.nixfmt-rfc-style);
+      checks = builtins.mapAttrs (_system: deployLib: deployLib.deployChecks inputs.self.deploy) (
+        nixpkgsLib.filterAttrs (key: _value: nixpkgsLib.hasSuffix "linux" key) inputs.deploy-rs.lib
+      );
 
       resources = loadDir [
         (inputs.haumea.lib.matchers.always pathLoader)

@@ -56,22 +46,11 @@
         (inputs.haumea.lib.matchers.always pathLoader)
       ] ./secrets;
 
-      packages = forAllSystems (pkgs: (loadDir (pkgsLoader pkgs) ./packages));
-
       nixosModules.default = ./config/nixosModules.nix;
 
       homeManagerModules = loadDir pathLoader ./config/home;
 
-      lib = loadDir (path: path: import path inputs) ./lib;
-
-      overlays = {
-        nixpkgsUnstable = final: prev: { unstable = inputs.nixpkgsUnstable.legacyPackages.${prev.system}; };
-        packages = final: prev: loadDir (path: path: final.callPackage path { }) ./packages;
-      };
-
       nixpkgsOverlays = [
-        inputs.self.overlays.packages
-        inputs.self.overlays.nixpkgsUnstable
         inputs.zaphyraWebsite.overlays.default
         inputs.stagit.overlays.default
         inputs.flauschehornSexy.overlays.default

@@ -79,6 +58,12 @@
         inputs.oeffisearch.overlays.default
         inputs.things.overlays.default
         inputs.mqttWebUI.overlays.default
+        inputs.airpodsctl.overlays.default
+        inputs.tgcNUR.overlays.default
+        inputs.tgcNUR.overlays.nixpkgsUnstable
+        inputs.tgcNUR.overlays.tuigreet
+        inputs.tgcNUR.overlays.swaylock-plugin-fprintd
+        (_final: prev: { sherlock-launcher = inputs.sherlock.packages.${prev.system}.default; })
       ];
 
       hosts = loadDir importLoader ./hosts;

@@ -86,7 +71,7 @@
       nixosConfigurations = builtins.mapAttrs (
         hostName: hostConfig:
         (if !hostConfig.nixpkgsStable then unstableNixpkgsLib.nixosSystem else nixpkgsLib.nixosSystem) {
-          system = hostConfig.system;
+          inherit (hostConfig) system;
 
           specialArgs = {
             inherit inputs;

@@ -100,18 +85,32 @@
           modules = nixpkgsLib.flatten [
             {
               nixpkgs.overlays = inputs.self.nixpkgsOverlays;
+
+              disabledModules = [
+                "security/pam.nix"
+                "services/security/fprintd.nix"
+              ];
+
+              imports = [
+                inputs.self.resources.patchedNixpkgsModules.pam
+                inputs.self.resources.patchedNixpkgsModules.fprintd
+              ];
             }
 
             (
-              if !hostConfig.nixpkgsStable then
+              if hostConfig.nixpkgsStable then
                 [
-                  inputs.homeManagerUnstable.nixosModules.default
-                  inputs.diskoUnstable.nixosModules.default
+                  inputs.homeManager.nixosModules.default
+                  inputs.disko.nixosModules.default
+                  inputs.simpleNixosMailserver.nixosModules.default
+                  inputs.stylix.nixosModules.stylix
                 ]
               else
                 [
-                  inputs.homeManager.nixosModules.default
-                  inputs.disko.nixosModules.default
+                  inputs.homeManagerUnstable.nixosModules.default
+                  inputs.diskoUnstable.nixosModules.default
+                  inputs.simpleNixosMailserverUnstable.nixosModules.default
+                  inputs.stylixUnstable.nixosModules.stylix
                 ]
             )
 

@@ -120,8 +119,9 @@
             inputs.lixModule.nixosModules.default
             inputs.lanzaboote.nixosModules.lanzaboote
             inputs.sopsNix.nixosModules.sops
-            inputs.simpleNixosMailserver.nixosModules.default
             inputs.grapevine.nixosModules.default
+
+            inputs.tgcNUR.nixosModules.default
             inputs.things.nixosModules.default
 
             inputs.self.nixosModules.default

@@ -130,49 +130,53 @@
         }
       ) inputs.self.hosts;
 
-      zaphyraHosts = (
-        inputs.self.nixosConfigurations
-        |> nixpkgsLib.filterAttrs (
-          name: value:
-          if (builtins.isNull value.config.networking.domain) then
-            false
-          else
-            nixpkgsLib.hasSuffix "zaphyra.eu" value.config.networking.domain
-        )
-      );
+      zaphyraHosts = nixpkgsLib.filterAttrs (
+        _name: value:
+        if (builtins.isNull value.config.networking.domain) then
+          false
+        else
+          nixpkgsLib.hasSuffix "zaphyra.eu" value.config.networking.domain
+      ) inputs.self.nixosConfigurations;
 
       homeConfigurations = builtins.listToAttrs (
-        builtins.map (
-          name:
-          (nixpkgsLib.nameValuePair name (
-            inputs.homeManager.lib.homeManagerConfiguration {
-              pkgs = import inputs.nixpkgs {
-                system = "x86_64-linux";
-                overlays = inputs.self.nixpkgsOverlays;
-                config = {
-                  allowUnfree = true;
-                };
-              };
-
-              modules = [
-                inputs.self.homeManagerModules."${name}".home
-                inputs.self.homeManagerModules.common.home
-                {
-                  home = {
-                    username = nixpkgsLib.mkDefault name;
-                    homeDirectory = nixpkgsLib.mkDefault "/home/${name}";
+        builtins.map
+          (
+            name:
+            (nixpkgsLib.nameValuePair name (
+              inputs.homeManager.lib.homeManagerConfiguration {
+                pkgs = import inputs.nixpkgs {
+                  system = "x86_64-linux";
+                  overlays = inputs.self.nixpkgsOverlays;
+                  config = {
+                    allowUnfree = true;
                   };
-                  programs.home-manager.enable = true;
-                }
-              ];
+                };
 
-              extraSpecialArgs = {
-                inherit inputs;
-                inherit (inputs.self) homeManagerModules;
-              };
-            }
-          ))
-        ) (inputs.self.homeManagerModules |> nixpkgsLib.attrNames |> nixpkgsLib.remove "common")
+                modules = [
+                  inputs.self.homeManagerModules."${name}".home
+                  inputs.self.homeManagerModules.common.home
+                  {
+                    home = {
+                      username = nixpkgsLib.mkDefault name;
+                      homeDirectory = nixpkgsLib.mkDefault "/home/${name}";
+                    };
+                    programs.home-manager.enable = true;
+                  }
+                ];
+
+                extraSpecialArgs = {
+                  inherit inputs;
+                  inherit (inputs.self) homeManagerModules;
+                };
+              }
+            ))
+          )
+          (
+            nixpkgsLib.pipe inputs.self.homeManagerModules [
+              nixpkgsLib.attrNames
+              (nixpkgsLib.remove "common")
+            ]
+          )
       );
 
       hydraJobs = builtins.listToAttrs (

@@ -189,14 +193,13 @@
             "huntii"
             "novus"
             "morio"
-            "polaris"
           ]
       );
 
       deploy = {
         activationTimeout = 600;
         confirmTimeout = 240;
-        nodes = builtins.mapAttrs (nodeName: node: {
+        nodes = builtins.mapAttrs (_nodeName: node: {
           hostname = node.config.networking.fqdn;
           sshUser = "root";
           sshOpts = [

@@ -225,6 +228,8 @@
     nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
     nixpkgsUnstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
 
+    nixos-hardware.url = "github:NixOS/nixos-hardware";
+
     impermanence.url = "github:nix-community/impermanence";
     nixStd.url = "github:chessai/nix-std";
 

@@ -237,6 +242,12 @@
     sopsNix.url = "github:Mic92/sops-nix";
     sopsNix.inputs.nixpkgs.follows = "nixpkgs";
 
+    stylix.url = "github:nix-community/stylix/release-25.05";
+    stylix.inputs.nixpkgs.follows = "nixpkgs";
+
+    stylixUnstable.url = "github:nix-community/stylix";
+    stylixUnstable.inputs.nixpkgs.follows = "nixpkgsUnstable";
+
     disko.url = "github:nix-community/disko";
     disko.inputs.nixpkgs.follows = "nixpkgs";
 

@@ -244,9 +255,18 @@
     diskoUnstable.inputs.nixpkgs.follows = "nixpkgsUnstable";
 
     simpleNixosMailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-25.05";
-    simpleNixosMailserver.inputs.nixpkgs.follows = "nixpkgs";
-    simpleNixosMailserver.inputs.nixpkgs-25_05.follows = "nixpkgs";
-    simpleNixosMailserver.inputs.flake-compat.follows = "flakeCompat";
+    simpleNixosMailserver.inputs = {
+      nixpkgs.follows = "nixpkgsUnstable";
+      nixpkgs-25_05.follows = "nixpkgs";
+      flake-compat.follows = "flakeCompat";
+    };
+
+    simpleNixosMailserverUnstable.url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
+    simpleNixosMailserverUnstable.inputs = {
+      nixpkgs.follows = "nixpkgsUnstable";
+      nixpkgs-25_05.follows = "nixpkgs";
+      flake-compat.follows = "flakeCompat";
+    };
 
     homeManager.url = "github:nix-community/home-manager/release-25.05";
     homeManager.inputs.nixpkgs.follows = "nixpkgs";

@@ -269,13 +289,31 @@
     deploy-rs.inputs.utils.follows = "flakeUtils";
     deploy-rs.inputs.flake-compat.follows = "flakeCompat";
 
-    grapevine.url = "gitlab:matrix/grapevine?host=gitlab.computer.surgery&ref=lambda/sss";
+    grapevine.url = "gitlab:matrix/grapevine?host=gitlab.computer.surgery";
     grapevine.inputs = {
       nixpkgs.follows = "nixpkgs";
       flake-compat.follows = "flakeCompat";
       flake-utils.follows = "flakeUtils";
     };
 
+    niriFlake.url = "github:sodiboo/niri-flake";
+    niriFlake.inputs = {
+      nixpkgs.follows = "nixpkgsUnstable";
+      nixpkgs-stable.follows = "nixpkgs";
+    };
+
+    sherlock.url = "github:Skxxtz/sherlock/8485f8720352c8ba48a4d74d3d33c882f9c0b35b";
+    sherlock.inputs = {
+      nixpkgs.follows = "nixpkgs";
+      flake-parts.follows = "flakeParts";
+    };
+
+    tgcNUR.url = "git+https://git.transgirl.cafe/zaphyra/tgc-nix-user-repository";
+    tgcNUR.inputs = {
+      nixpkgs.follows = "nixpkgs";
+      nixpkgsUnstable.follows = "nixpkgsUnstable";
+    };
+
     zaphyraWebsite.url = "git+https://git.zaphyra.eu/website";
     zaphyraWebsite.inputs.nixpkgs.follows = "nixpkgs";
 

@@ -297,8 +335,11 @@
     mqttWebUI.url = "git+https://git.zaphyra.eu/mqtt-webui";
     mqttWebUI.inputs.nixpkgs.follows = "nixpkgs";
 
+    airpodsctl.url = "git+https://git.zaphyra.eu/airpodsctl";
+    airpodsctl.inputs.nixpkgs.follows = "nixpkgs";
+
     firefoxGnomeTheme.flake = false;
-    firefoxGnomeTheme.url = "github:rafaelmardojai/firefox-gnome-theme/v137";
+    firefoxGnomeTheme.url = "github:rafaelmardojai/firefox-gnome-theme/v140";
   };
 
 }
diff --git a/hosts/empty/default.nix b/hosts/empty/default.nix
@@ -12,11 +12,15 @@
     {
       config = {
         # Minimal options to pass assertions.
-        boot.enableContainers = false;
-        boot.loader.grub.enable = false;
-        boot.initrd.includeDefaultModules = false;
-        boot.initrd.kernelModules = lib.mkOverride 0 [ ];
-        boot.initrd.systemd.enable = true;
+        boot = {
+          enableContainers = false;
+          loader.grub.enable = false;
+          initrd = {
+            includeDefaultModules = false;
+            kernelModules = lib.mkOverride 0 [ ];
+            systemd.enable = true;
+          };
+        };
         documentation = {
           doc.enable = false;
           info.enable = false;

@@ -24,7 +28,7 @@
           nixos.enable = false;
         };
         nixpkgs.overlays = [
-          (final: prev: {
+          (_final: prev: {
             systemd = prev.systemd.override {
               withAcl = false;
               withAnalyze = false;

@@ -60,9 +64,11 @@
         security.sudo.enable = false;
         services.userborn.enable = true;
         nix.channel.enable = false;
-        system.disableInstallerTools = true;
-        system.forbiddenDependenciesRegexes = [ "perl" ];
-        system.etc.overlay.enable = true;
+        system = {
+          disableInstallerTools = true;
+          forbiddenDependenciesRegexes = [ "perl" ];
+          etc.overlay.enable = true;
+        };
         systemd.coredump.enable = false;
         environment.defaultPackages = lib.mkOverride 0 [ ];
         fileSystems."/" = {
diff --git a/hosts/eximius/configuration.nix b/hosts/eximius/configuration.nix
@@ -0,0 +1,89 @@
+# Edit this configuration file to define what should be installed on
+# your system. Help is available in the configuration.nix(5) man page, on
+# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
+
+{
+  pkgs,
+  ...
+}:
+
+{
+  # Use latest kernel.
+  boot.kernelPackages = pkgs.linuxPackages_latest;
+
+  hardware.bluetooth = {
+    enable = true;
+    powerOnBoot = false;
+  };
+
+  #networking.hostName = "eximius"; # Define your hostname.
+  # Pick only one of the below networking options.
+  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.
+  networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
+
+  # Set your time zone.
+  #time.timeZone = "Europe/Berlin";
+
+  # Configure network proxy if necessary
+  # networking.proxy.default = "http://user:password@proxy:port/";
+  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
+
+  # Select internationalisation properties.
+  #i18n.defaultLocale = "en_GB.UTF-8";
+  console = {
+    #   font = "Lat2-Terminus16";
+    keyMap = "mod-dh-iso-uk";
+    #   useXkbConfig = true; # use xkb.options in tty.
+  };
+
+  powerManagement.powertop.enable = true;
+
+  virtualisation.podman.enable = true;
+
+  services = {
+    blueman.enable = true;
+    upower.enable = true;
+    power-profiles-daemon.enable = true;
+    seatd.enable = true;
+    mullvad-vpn = {
+      enable = true;
+      package = pkgs.mullvad-vpn;
+    };
+    syncthing = {
+      enable = false;
+      user = "void";
+      group = "users";
+      dataDir = "/home/void";
+      openDefaultPorts = true;
+    };
+  };
+
+  users.defaultUserShell = pkgs.fish;
+
+  # Define a user account. Don't forget to set a password with ‘passwd’.
+  users.users.void = {
+    isNormalUser = true;
+    extraGroups = [
+      "networkmanager"
+      "wheel"
+    ]; # Enable ‘sudo’ for the user.
+    packages = with pkgs; [
+      comma
+      kitty
+      librewolf
+      keepassxc
+      monero-cli
+      monero-gui
+      element-desktop
+    ];
+  };
+
+  programs.fish.enable = true;
+  programs.sway = {
+    enable = true;
+    extraPackages = [ ];
+    wrapperFeatures.gtk = true;
+  };
+
+  #environment.systemPackages = [pkgs.swaylock];
+}
diff --git a/hosts/eximius/default.nix b/hosts/eximius/default.nix
@@ -0,0 +1,180 @@
+{
+
+  system = "x86_64-linux";
+  nixpkgsStable = false;
+
+  domain = "eukaryote.eu";
+
+  #sshPubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBGgd/59d8wyU9kE6iRSMvTmev8z5dq4YtjeBlEoAI4S";
+
+  hardware = {
+    cpuVendor = "intel";
+    allowHibernation = true;
+  };
+
+  networking = {
+    #hasDN42 = true;
+    dn42Address = "fd49:7a7a:6965:c0::6cd4";
+  };
+
+  configuration =
+    {
+      inputs,
+      ...
+    }:
+    {
+
+      imports = [
+        ./configuration.nix
+        ./hardware-configuration.nix
+        inputs.nixos-hardware.nixosModules.framework-intel-core-ultra-series1
+      ];
+
+      home-manager.sharedModules = [
+        {
+          wayland.windowManager.sway.config = {
+            seat."*".xcursor_theme = "Adwaita 20";
+            output."eDP-1".scale = "1.5";
+          };
+        }
+      ];
+
+      boot.initrd.systemd.emergencyAccess = true;
+      boot.kernelParams = [
+        "resume=/dev/eximius/swap"
+      ];
+
+      #sops.secrets."environments/networkManagerProfiles/cccdaWifi" = { };
+
+      sops.age.keyFile = "/var/lib/sops-nix/age/keys.txt";
+
+      modules = {
+
+        filesystem = {
+          #impermanence.system.enable = true;
+          #impermanence.home.enable = true;
+          rootDisk = {
+            #enable = true;
+            encrypt = true;
+            type = "btrfs";
+            path = "/dev/disk/by-id/nvme-CT1000P3PSSD8_2342444001E2";
+            #reservedSpace = "3G";
+            parts = {
+              nix = true;
+            };
+            swap = {
+              enable = true;
+              size = "24G";
+            };
+          };
+        };
+
+        hardware = {
+          bluetooth.enable = true;
+          cpu.updateMicrocode = true;
+          fprint.enable = true;
+          fprint.disableOnLidClose = true;
+          thunderbolt.enable = true;
+          #quirks.thinkpad.enable = true;
+          video.intel.enable = true;
+        };
+
+        presets = {
+          base.enable = true;
+          graphical.enable = true;
+          graphical.type = "sway";
+          void.enable = true;
+
+          #networkManagerProfiles = {
+          #  voidPhoneWifi.enable = true;
+          #  voidHomeWifi.enable = true;
+          #  zaphyraPhoneWifi.enable = true;
+          #  zaphyraHomeWifi.enable = true;
+          #  grogHomeWifi.enable = true;
+          #  cccdaWifi = {
+          #    enable = true;
+          #    username = "zaphyra";
+          #    envFile = config.sops.secrets."environments/networkManagerProfiles/cccdaWifi".path;
+          #  };
+          #};
+        };
+
+        services = {
+          earlyoom.enable = true;
+          greetd.autoLogin = {
+            enable = true;
+            user = "void";
+          };
+          systemd-oomd.enable = true;
+        };
+
+        programs = {
+          #AusweisApp.enable = true;
+          steam.enable = true;
+          yubikey.enable = true;
+        };
+
+        users.void.enable = true;
+      };
+
+      networking = {
+        useNetworkd = false;
+        #hosts."127.0.0.1" = [ config.networking.fqdn ];
+      };
+
+      #      nixpkgs.overlays = [
+      #        (self: super: { mesa = pkgs.callPackage inputs.self.resources.mesa {}; })
+      #      ];
+
+      programs.steam = {
+        enable = true;
+        remotePlay.openFirewall = true;
+        localNetworkGameTransfers.openFirewall = true;
+        gamescopeSession.enable = true;
+        protontricks.enable = true;
+      };
+
+      services = {
+        hardware.bolt.enable = true;
+        resolved.enable = true;
+        logind.settings.Login.HandlePowerKey = "hibernate";
+        keyd = {
+          enable = true;
+          keyboards.builtin = {
+            ids = [ "0001:0001" ];
+            settings = {
+              main = {
+                capslock = "layer(shift)";
+                leftshift = "capslock";
+                rightcontrol = "layer(rightcontrol)";
+              };
+              rightcontrol = {
+                q = "!";
+                w = "@";
+                e = "#";
+                r = "$";
+                t = "%";
+
+                y = "^";
+                u = "&";
+                i = "*";
+                o = "(";
+                p = ")";
+              };
+            };
+          };
+        };
+        printing.enable = true;
+        avahi = {
+          enable = true;
+          nssmdns4 = true;
+          publish.enable = true;
+          publish.userServices = true;
+        };
+      };
+
+      system.stateVersion = "25.11";
+      home-manager.users.void.home.stateVersion = "25.11";
+    };
+
+}
diff --git a/hosts/eximius/hardware-configuration.nix b/hosts/eximius/hardware-configuration.nix
@@ -0,0 +1,96 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{
+  config,
+  lib,
+  modulesPath,
+  ...
+}:
+
+{
+  imports = [
+    (modulesPath + "/installer/scan/not-detected.nix")
+  ];
+
+  boot = {
+    initrd.availableKernelModules = [
+      "xhci_pci"
+      "nvme"
+    ];
+    kernelModules = [ "kvm-intel" ];
+    extraModulePackages = [ ];
+
+    initrd = {
+      kernelModules = [ "dm-snapshot" ];
+      luks.devices.cryptroot = {
+        device = "/dev/disk/by-partlabel/disk-eximius-root";
+      };
+    };
+  };
+
+  fileSystems = {
+    "/" = {
+      device = "/dev/eximius/root";
+      fsType = "btrfs";
+      options = [ "subvol=nixos" ];
+    };
+
+    "/nix" = {
+      device = "/dev/eximius/nix";
+      fsType = "xfs";
+    };
+
+    "/data" = {
+      device = "/dev/eximius/persist";
+      fsType = "btrfs";
+    };
+
+    "/home" = {
+      device = "/dev/eximius/home";
+      fsType = "btrfs";
+      options = [
+        "acl"
+        "nofail"
+      ];
+    };
+
+    "/boot" = {
+      device = "/dev/disk/by-partlabel/disk-eximius-boot";
+      fsType = "vfat";
+      options = [
+        "fmask=0077"
+        "dmask=0077"
+      ];
+    };
+
+    "/etc/nixos" = {
+      device = "/dev/eximius/persist";
+      fsType = "btrfs";
+      options = [ "subvol=etc/nixos" ];
+    };
+
+    "/var/lib/sbctl" = {
+      device = "/dev/eximius/persist";
+      fsType = "btrfs";
+      options = [ "subvol=var/lib/sbctl" ];
+    };
+  };
+
+  swapDevices = [
+    {
+      device = "/dev/eximius/swap";
+      options = [ "nofail" ];
+    }
+  ];
+
+  # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+  # (the default) this is the recommended approach. When using systemd-networkd it's
+  # still possible to use this option, but it's recommended to use it in conjunction
+  # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+  networking.useDHCP = lib.mkDefault true;
+  # networking.interfaces.wlp170s0.useDHCP = lib.mkDefault true;
+
+  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+  hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
+}
diff --git a/hosts/huntii/default.nix b/hosts/huntii/default.nix
@@ -19,7 +19,6 @@
 
   configuration =
     {
-      modulesPath,
       config,
       pkgs,
       lib,

@@ -27,11 +26,12 @@
     }:
     {
 
-      imports = [
-        (modulesPath + "/profiles/minimal.nix")
-      ];
+      specialisation.gnome.configuration = {
+        modules.presets.graphical.type = lib.mkForce "gnomeMinimal";
+      };
 
       boot.initrd.systemd.emergencyAccess = true;
+      boot.kernel.sysctl."power.pm_async" = false;
 
       sops.secrets."environments/networkManagerProfiles/cccdaWifi" = { };
 

@@ -42,7 +42,7 @@
           rootDisk = {
             enable = true;
             encrypt = true;
-            type = "zfs";
+            type = "btrfs";
             path = "/dev/disk/by-id/nvme-SKHynix_HFS512GDE9X081N_FYB8N034411508M5G";
             reservedSpace = "3G";
             parts = {

@@ -59,6 +59,7 @@
           video.intel.enable = true;
           cpu.updateMicrocode = true;
           fprint.enable = true;
+          fprint.disableOnLidClose = true;
 
           quirks.thinkpad.enable = true;
         };

@@ -73,13 +74,14 @@
           };
 
           graphical.enable = true;
-          graphical.type = "gnomeMinimal";
+          graphical.type = "niri";
 
           networkManagerProfiles = {
             voidPhoneWifi.enable = true;
             voidHomeWifi.enable = true;
             zaphyraPhoneWifi.enable = true;
             zaphyraHomeWifi.enable = true;
+            grogHomeWifi.enable = true;
             cccdaWifi = {
               enable = true;
               username = "zaphyra";

@@ -91,6 +93,10 @@
         services = {
           earlyoom.enable = true;
           systemd-oomd.enable = true;
+          greetd.autoLogin = {
+            enable = true;
+            user = "zaphyra";
+          };
         };
 
         programs = {

@@ -110,6 +116,11 @@
             path = "${pkgs.modemmanager}/share/ModemManager/fcc-unlock.available.d/2c7c";
           }
         ];
+        #required for owntone airplay foo
+        firewall.allowedUDPPorts = [
+          7200
+          7201
+        ];
       };
 
       hardware.bluetooth.settings = {

@@ -119,11 +130,14 @@
       services = {
         resolved.enable = true;
         printing.enable = true;
+        avahi = {
+          enable = true;
+          nssmdns4 = true;
+          publish.enable = true;
+          publish.userServices = true;
+        };
         gnome.at-spi2-core.enable = false;
-
-        #required for gnome-calendar
-        gnome.evolution-data-server.enable = true;
-        gnome.gnome-online-accounts.enable = true;
+        pipewire.raopOpenFirewall = true;
       };
 
       system.stateVersion = "25.05";
diff --git a/hosts/morio/default.nix b/hosts/morio/default.nix
@@ -29,16 +29,13 @@
 
   configuration =
     {
-      modulesPath,
       inputs,
       config,
-      pkgs,
       ...
     }:
     {
 
       imports = [
-        (modulesPath + "/profiles/minimal.nix")
         ./dn42.nix
       ];
 

@@ -78,9 +75,11 @@
             syncthing.enable = false;
             dnsServer.enable = true;
             mailServer.enable = true;
-            mautrixBridges.signal.enable = true;
-            mautrixBridges.whatsapp.enable = true;
-            mautrixBridges.telegram.enable = true;
+            mautrixBridges = {
+              signal.enable = true;
+              whatsapp.enable = true;
+              telegram.enable = true;
+            };
           };
         };
 

@@ -91,6 +90,12 @@
               environmentFile = config.sops.secrets."resticEnv/novus".path;
             };
           };
+
+          prosody = {
+            enable = true;
+            domain = "zaphyra.eu";
+            adminUsers = [ "katja@zaphyra.eu" ];
+          };
         };
 
         websites = {

@@ -105,6 +110,7 @@
           "dav.zaphyra.eu".enable = true;
           "gts.zaphyra.eu".enable = true;
           "grapevine.zaphyra.eu".enable = true;
+          "gomuks.zaphyra.eu".enable = true;
           "vault.zaphyra.eu".enable = true;
           "oeffi.zaphyra.eu".enable = true;
           "things.zaphyra.eu".enable = true;
diff --git a/hosts/morio/dn42.nix b/hosts/morio/dn42.nix
@@ -13,7 +13,6 @@
     "fd6b:6174:6a61:53::2"
   ];
 
-
   systemd.network = {
     netdevs."20-dn42" = {
       netdevConfig = {

@@ -41,22 +40,10 @@
     networks."20-dn42" = {
       matchConfig.Name = "dn42";
       linkConfig.RequiredForOnline = false;
-      routes = [ { Destination = "fd00::/8"; } ];
       address = [
         "fd6b:6174:6a61::2/128"
         "fd6b:6174:6a61:53::2/128"
       ];
-      networkConfig = {
-        DNSDefaultRoute = false;
-        DNS = [
-          "fd42:d42:d42:54::1"
-          "fd42:d42:d42:53::1"
-        ];
-        Domains = [
-          "~dn42"
-          "d.f.ip6.arpa"
-        ];
-      };
     };
   };
 
diff --git a/hosts/novus/default.nix b/hosts/novus/default.nix
@@ -29,17 +29,13 @@
 
   configuration =
     {
-      modulesPath,
       inputs,
       config,
-      lib,
-      pkgs,
       ...
     }:
     {
 
       imports = [
-        (modulesPath + "/profiles/minimal.nix")
         ./dn42.nix
       ];
 
diff --git a/hosts/novus/dn42.nix b/hosts/novus/dn42.nix
@@ -4,10 +4,6 @@
 
   dns.zones."zaphyra.eu".subdomains."router-a.dn42".AAAA = [ hostConfig.networking.ip6Address ];
 
-  services.knot.settings.server.listen = [
-    "fd6b:6174:6a61:53::1"
-  ];
-
   sops.secrets."dn42/wgPrivateKey" = {
     owner = "systemd-network";
     group = "systemd-network";

@@ -20,14 +16,6 @@
     address = "fd6b:6174:6a61::1";
     range = "fd6b:6174:6a61::/48";
     peerings = {
-      # void = {
-      #   asn = 4242420575;
-      #   linkLocalAddress = "fe80::497a";
-      #   endpoint = "gw.srv.eukaryote.eu:49508";
-      #   hasPresharedKey = true;
-      #   publicKey = "";
-      #   listenPort = 51821;
-      # };
       kioubit = {
         asn = 4242423914;
         remoteLinkLocalAddress = "fe80::ade0";

@@ -65,7 +53,7 @@
       dahlabandon = {
         asn = 4242420814;
         remoteLinkLocalAddress = "fe80::1718";
-        endpoint = "cargobridge25.iron-bear.de:1718";
+        endpoint = "helios-fallen.iron-bear.de:1718";
         publicKey = "+tg4bDDwfyQZSw0x8x9Ye2tDWPZ/VAf+KTAE1QLaKEI=";
         listenPort = 51828;
       };

@@ -119,31 +107,56 @@
     };
   };
 
+  services.kresd = {
+    enable = true;
+    listenPlain = [ "[fd6b:6174:6a61::1]:53" ];
+    extraConfig = ''
+      modules = {
+        'hints > iterate',  -- Allow loading /etc/hosts or custom root hints
+        'stats',            -- Track internal statistics
+        'predict',          -- Prefetch expiring/frequent records
+      }
+
+      log_level('info')
+
+      -- Cache size
+      cache.size = 100 * MB
+
+      dn42 = {
+        'dn42.',
+        '20.172.in-addr.arpa.',
+        '21.172.in-addr.arpa.',
+        '22.172.in-addr.arpa.',
+        '23.172.in-addr.arpa.',
+        '10.in-addr.arpa.',
+        'd.f.in-addr.arpa.',
+      }
+
+      -- NXDOMAINs that could sometimes happen due to aggressive DNSSEC caching.
+      policy.add(policy.suffix(policy.FLAGS({'NO_EDNS'}), dn42))
+
+      policy.add(policy.suffix(policy.STUB({'fd42:d42:d42:54::1', 'fd42:d42:d42:53::1'}), policy.todnames(dn42)))
+      -- policy.add(policy.FORWARD({'1.1.1.1'}))
+
+      -- trust_anchors.remove('.')
+      trust_anchors.set_insecure(dn42) -- Disable DNSSEC for these domains
+
+      modules.load('nsid')
+      nsid.name(hostname() .. ':' .. os.getenv("SYSTEMD_INSTANCE"))
+    '';
+  };
+
   networking.firewall = {
     checkReversePath = "loose";
     allowedUDPPorts = [
       config.systemd.network.netdevs."20-dn42".wireguardConfig.ListenPort
     ];
     trustedInterfaces = [
-      #      "vlan"
       "dn42"
     ];
-    # filterForward = true;
-    # extraForwardRules = "iifname dn42 accept";
   };
 
   systemd.network = {
-    #     links."10-vlan" = {
-    #       matchConfig.PermanentMACAddress = "56:ca:a0:fa:fa:2b";
-    #       linkConfig.Name = "vlan";
-    #     };
-    #
-    #     networks."10-vlan" = {
-    #       matchConfig.Name = "vlan";
-    #       linkConfig.RequiredForOnline = "no";
-    #       networkConfig.IPv6Forwarding = true;
-    #     };
-
     config.networkConfig = {
       IPv6Forwarding = true;
     };

@@ -206,17 +219,6 @@
         "fd6b:6174:6a61::1/48"
         "fd6b:6174:6a61:53::1/128"
       ];
-      networkConfig = {
-        DNSDefaultRoute = false;
-        DNS = [
-          "fd42:d42:d42:54::1"
-          "fd42:d42:d42:53::1"
-        ];
-        Domains = [
-          "~dn42"
-          "d.f.ip6.arpa"
-        ];
-      };
     };
   };
 
diff --git a/hosts/polaris/default.nix b/hosts/polaris/default.nix
@@ -27,18 +27,12 @@
 
   configuration =
     {
-      modulesPath,
       inputs,
-      hostConfig,
-      config,
-      lib,
-      pkgs,
       ...
     }:
     {
 
       imports = [
-        (modulesPath + "/profiles/minimal.nix")
         ./syncthing.nix
       ];
 
diff --git a/hosts/pratorum/default.nix b/hosts/pratorum/default.nix
@@ -0,0 +1,149 @@
+{
+
+  system = "x86_64-linux";
+  nixpkgsStable = true;
+
+  domain = "infra.zaphyra.eu";
+
+  sshPubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICEMrPGa6PIx0UpVnbVYWR+TTbNyZPd8htTTzjQ5NBI3";
+
+  hardware = {
+    cpuVendor = "amd";
+    allowHibernation = false;
+  };
+
+  networking = {
+    ip4IsPrivate = true;
+    ip4Address = "192.168.2.110";
+    ip4PrefixLength = 24;
+    defaultGateway4 = "192.168.2.1";
+
+    ip6IsPrivate = true;
+    ip6Address = "2a03:4000:4d:5e:acab::3";
+    ip6PrefixLength = 112;
+
+    hasDN42 = true;
+    dn42Address = "fd6b:6174:6a61::10";
+  };
+
+  configuration =
+    {
+      config,
+      lib,
+      hostConfig,
+      ...
+    }:
+    {
+
+      imports = [
+        ./dn42.nix
+      ];
+
+      boot = {
+        initrd = {
+          systemd.emergencyAccess = true;
+          availableKernelModules = [
+            "nvme"
+            "ehci_pci"
+            "xhci_pci"
+            "ahci"
+            "usbhid"
+            "usb_storage"
+            "sd_mod"
+          ];
+          luks.devices."root".device = "/dev/disk/by-uuid/e6ad3c7a-f1a5-4e10-a9f6-53e39297b1a3";
+        };
+        kernelModules = [ "kvm-amd" ];
+        extraModulePackages = [ ];
+      };
+
+      fileSystems."/" = {
+        device = "/dev/disk/by-uuid/d9856f85-c995-4d85-a614-cb2977fea1de";
+        fsType = "btrfs";
+      };
+
+      fileSystems."/boot" = {
+        device = "/dev/disk/by-uuid/2B4A-D88C";
+        fsType = "vfat";
+        options = [
+          "fmask=0022"
+          "dmask=0022"
+        ];
+      };
+
+      nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+      hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
+
+      systemd.network = {
+        netdevs."10-wg-novus" = {
+          netdevConfig = {
+            Kind = "wireguard";
+            Name = "wg-novus";
+          };
+
+          wireguardConfig = {
+            PrivateKeyFile = config.sops.secrets."dn42/wgPrivateKey".path;
+            ListenPort = 51820;
+            FirewallMark = 51820;
+          };
+
+          wireguardPeers = [
+            {
+              Endpoint = "novus.infra.zaphyra.eu:51820";
+              PublicKey = "J+kRRNU65JGc0yk04v6P3tFwHSQOIfq8EkfD2gFupg4=";
+              AllowedIPs = [ "2a03:4000:4d:5e:acab::3/112" ];
+              PersistentKeepalive = 10;
+            }
+          ];
+        };
+
+        networks."10-wg-novus" = {
+          matchConfig.Name = "wg-novus";
+
+          linkConfig = {
+            RequiredForOnline = false;
+          };
+          address = [
+            "${hostConfig.networking.ip6Address}/${toString hostConfig.networking.ip6PrefixLength}"
+          ];
+        };
+
+        networks."5-enp3s0f0" = {
+          enable = true;
+          name = "enp3s0f0";
+          dns = [
+            "1.1.1.1"
+            "8.8.8.8"
+            "9.9.9.9"
+          ];
+          gateway = [
+            hostConfig.networking.defaultGateway4
+          ];
+          address = [
+            "${hostConfig.networking.ip4Address}/${toString hostConfig.networking.ip4PrefixLength}"
+          ];
+          networkConfig.IPv6AcceptRA = true;
+        };
+      };
+
+      modules = {
+        presets = {
+          base.enable = true;
+          zaphyra = {
+            enable = true;
+            syncthing.enable = true;
+          };
+        };
+
+        websites = {
+          "music.zaphyra.dn42".enable = true;
+        };
+
+        users.zaphyra.enable = true;
+      };
+
+      system.stateVersion = "25.05";
+      home-manager.users.zaphyra.home.stateVersion = "25.05";
+    };
+
+}
diff --git a/hosts/pratorum/dn42.nix b/hosts/pratorum/dn42.nix
@@ -0,0 +1,49 @@
+{ config, ... }:
+
+{
+
+  sops.secrets."dn42/wgPrivateKey" = {
+    owner = "systemd-network";
+    group = "systemd-network";
+  };
+
+  systemd.network = {
+    netdevs."20-dn42" = {
+      netdevConfig = {
+        Kind = "wireguard";
+        Name = "dn42";
+        MTUBytes = 1280;
+      };
+
+      wireguardConfig = {
+        PrivateKeyFile = config.sops.secrets."dn42/wgPrivateKey".path;
+        ListenPort = 1718;
+        FirewallMark = 1718;
+      };
+
+      wireguardPeers = [
+        {
+          PublicKey = "MRXPP//j+BDCiUyrYHdXtdULAsCZyfgumas8pxp6oiE=";
+          Endpoint = "router-a.dn42.zaphyra.eu:1718";
+          AllowedIPs = [ "fd00::/8" ];
+          PersistentKeepalive = 10;
+        }
+      ];
+    };
+
+    networks."20-dn42" = {
+      matchConfig.Name = "dn42";
+      linkConfig.RequiredForOnline = false;
+      routes = [
+        {
+          Destination = "::/0";
+          Table = "1234";
+        }
+      ];
+      address = [
+        "fd6b:6174:6a61::10/128"
+      ];
+    };
+  };
+
+}
diff --git a/packages/adwaita-colors-icon-theme.nix b/packages/adwaita-colors-icon-theme.nix
@@ -1,41 +0,0 @@
-{
-  lib,
-  stdenvNoCC,
-  fetchFromGitHub,
-  gtk3,
-  xdg-utils,
-}:
-
-stdenvNoCC.mkDerivation rec {
-  pname = "adwaita-colors-icon-theme";
-  version = "2.3";
-
-  src = fetchFromGitHub {
-    owner = "dpejoh";
-    repo = "Adwaita-colors";
-    rev = "v${version}";
-    hash = "sha256-q7qvE55vtd8K0T+VQKJ0Qa/qIPToRh3xU1wLjyW68nQ=";
-  };
-
-  nativeBuildInputs = [
-    gtk3
-    xdg-utils
-  ];
-
-  installPhase = ''
-    runHook preInstall
-
-    install -d $out/share/icons
-    cp -r Adwaita-* $out/share/icons/
-    gtk-update-icon-cache -f -t $out/share/icons/Adwaita* && xdg-desktop-menu forceupdate
-
-    runHook postInstall
-  '';
-
-  meta = with lib; {
-    description = "Adwaita Colors customizes Adwaita icons to match your GNOME theme's accent color, providing a cohesive, personalized look.";
-    homepage = "https://github.com/dpejoh/Adwaita-colors";
-    license = with licenses; [ gpl3Only ];
-    platforms = platforms.linux;
-  };
-}
diff --git a/packages/chaosctl/chaosctl.fish b/packages/chaosctl/chaosctl.fish
@@ -1,65 +0,0 @@
-# GLOBALS
-set CMD "$argv[1]"
-set CMDS beamer door help tv
-
-function error
-    echo $argv[2..] 1>&2
-    return $argv[1]
-end
-
-set _descr_beamer "Control the beamer in the lounge"
-set _usage_beamer "<on|off>"
-function cmd_beamer
-    switch $argv[1]
-        case on
-            ssh chaos@lounge.cccda.de beamer-on
-        case off
-            ssh chaos@lounge.cccda.de beamer-off
-        case "*"
-            error 1 "$(cmd_help beamer)"
-    end
-end
-
-set _descr_door "Control the door"
-function cmd_door
-    ssh door@door.cccda.de $argv
-end
-
-set _descr_help "Display this message"
-function cmd_help
-    set cmd "$argv[1]"
-    if [ "$cmd" != "" ]
-        echo "\
-$(eval echo \$_descr_$cmd)
-
-Usage:
-    chaosctl $cmd $(eval echo \$_usage_$cmd)"
-    else
-        echo "\
-The chaosctl utility
-
-Usage:
-    chaosctl <command>
-
-COMMANDS"
-        for cmd in $CMDS
-            echo -e "    $cmd\t$(eval echo \$_descr_$cmd)"
-        end
-    end
-end
-
-set _descr_tv "\tControl the TV in the kitchen"
-function cmd_tv
-    ssh chaos@kitchen.cccda.de tv $argv
-end
-
-if [ "cmd_$CMD" = cmd_ ]
-    error 1 "$(cmd_help)"
-    exit $status
-end
-
-if type -q "cmd_$CMD"
-    cmd_$CMD $argv[2..]
-else
-    error 127 "No such subcommand '$CMD'"
-end
diff --git a/packages/chaosctl/default.nix b/packages/chaosctl/default.nix
@@ -1,5 +0,0 @@
-{
-  writers,
-  ...
-}:
-writers.writeFishBin "chaosctl" ./chaosctl.fish
diff --git a/packages/gotosocial/default.nix b/packages/gotosocial/default.nix
@@ -1,99 +0,0 @@
-{
-  applyPatches,
-  fetchgit,
-  mkYarnPackage,
-  buildGo124Module,
-  lib,
-  makeWrapper,
-  installShellFiles,
-  ...
-}:
-
-buildGo124Module rec {
-  pname = "gotosocial";
-  version = "0.20.0-${builtins.substring 0 6 rev}";
-  rev = "b6ff55662e0281c0d6e111f9307625ef695df2fa";
-  hash = "sha256-btdStdOlIWIFzTQYFzinH5N/U71LETkg8phY7p+eDtw=";
-
-  src = applyPatches {
-    src = fetchgit {
-      url = "https://codeberg.org/superseriousbusiness/gotosocial/";
-      inherit rev hash;
-    };
-    patches = [ ];
-  };
-
-  frontend-assets = mkYarnPackage {
-    name = "${pname}_${version}-frontend-assets";
-    inherit src version;
-
-    packageJSON = "${src}/web/source/package.json";
-    yarnLock = "${src}/web/source/yarn.lock";
-
-    configurePhase = ''
-      cp -r $node_modules node_modules
-      chmod +w -R node_modules
-    '';
-
-    buildPhase = ''
-      mkdir -p ./web/source ./web/assets
-
-      cp -r $src/web/source/. ./web/source
-      cp -r $src/web/assets/. ./web/assets
-
-      export NODE_OPTIONS=--openssl-legacy-provider
-      node ./node_modules/ts-patch/bin/ts-patch.js install
-      yarn --offline --cwd ./web/source build
-    '';
-
-    distPhase = "true";
-    installPhase = "cp -r ./web/assets $out";
-
-    meta.license = lib.licenses.agpl3Only;
-  };
-
-  ldflags = [
-    "-s"
-    "-w"
-    "-extldflags '-static'"
-    "-X 'main.Commit=${rev}'"
-    "-X 'main.Version=${version}'"
-  ];
-  tags = [
-    "netgo"
-    "osusergo"
-    "static_build"
-  ];
-
-  vendorHash = null;
-
-  nativeBuildInputs = [ installShellFiles ];
-  buildInputs = [ makeWrapper ];
-
-  doCheck = false;
-
-  installCheckPhase = ''
-    runHook preCheck
-    $out/bin/gotosocial --help
-    runHook postCheck
-  '';
-
-  postInstall = ''
-    mkdir -p $out/share/web/assets
-
-    cp -r  ./web/template                  $out/share/web/
-    cp -rf ${frontend-assets}/. $out/share/web/assets
-
-    installShellCompletion --cmd gotosocial \
-      --bash <($out/bin/gotosocial completion bash) \
-      --fish <($out/bin/gotosocial completion fish) \
-      --zsh <($out/bin/gotosocial completion zsh)
-  '';
-
-  meta = with lib; {
-    description = "An ActivityPub social network server, written in Golang.";
-    homepage = "https://github.com/superseriousbusiness/gotosocial";
-    license = licenses.agpl3Only;
-  };
-
-}
diff --git a/packages/mautrix-telegramgo.nix b/packages/mautrix-telegramgo.nix
@@ -1,48 +0,0 @@
-{
-  lib,
-  stdenv,
-  buildGoModule,
-  fetchFromGitHub,
-  olm,
-  versionCheckHook,
-  # This option enables the use of an experimental pure-Go implementation of
-  # the Olm protocol instead of libolm for end-to-end encryption. Using goolm
-  # is not recommended by the mautrix developers, but they are interested in
-  # people trying it out in non-production-critical environments and reporting
-  # any issues they run into.
-  withGoolm ? true,
-}:
-
-let
-  cppStdLib = if stdenv.hostPlatform.isDarwin then "-lc++" else "-lstdc++";
-
-in
-buildGoModule rec {
-  pname = "mautrix-telegramgo";
-  rev = "ea4626107c56799ad3ca503e63450823a7f36546";
-  version = "0.0.0-${builtins.substring 0 6 rev}";
-  hash = "sha256-wV6wH60+qF+A/KHS9BDQbSG0pD2yRedqbqH1ea0gCKU=";
-
-  src = fetchFromGitHub {
-    owner = "mautrix";
-    repo = "telegramgo";
-    inherit rev hash;
-  };
-
-  buildInputs = (lib.optional (!withGoolm) olm) ++ (lib.optional withGoolm stdenv.cc.cc.lib);
-
-  CGO_LDFLAGS = lib.optional withGoolm [ cppStdLib ];
-
-  tags = lib.optional withGoolm "goolm";
-
-  doCheck = false;
-
-  vendorHash = "sha256-3gJwR4gmkoOKQfiWe3pI04638wgJjyissAND5XbBGHM=";
-
-  meta = with lib; {
-    homepage = "https://github.com/mautrix/telegramgo";
-    description = "Go rewrite of mautrix-telegram";
-    license = licenses.agpl3Plus;
-    mainProgram = "mautrix-telegram";
-  };
-}
diff --git a/packages/phanpy.nix b/packages/phanpy.nix
@@ -1,46 +0,0 @@
-{
-  lib,
-  fetchFromGitHub,
-  buildNpmPackage,
-  clientName ? "Phanpy",
-  website ? "https://phanpy.social",
-  defaultInstance ? "",
-  defaultInstanceRegistrationUrl ? "",
-  defaultLang ? "en",
-  ...
-}:
-
-buildNpmPackage (finalAttrs: {
-  pname = "phanpy";
-  version = "2025.04.28.5849b4d";
-
-  src = fetchFromGitHub {
-    owner = "cheeaun";
-    repo = "phanpy";
-    tag = finalAttrs.version;
-    hash = "sha256-Mp8ckYktjhQwuxirlMntzaA2IbExGaPPEj4IAKibvEQ=";
-  };
-
-  npmDepsHash = "sha256-02comyhYcY7Q71Cx9RCWIeKz1RwNcJPtSR5/EB2v+jU=";
-
-  NODE_OPTIONS = "--openssl-legacy-provider";
-
-  env = {
-    PHANPY_CLIENT_NAME = clientName;
-    PHANPY_WEBSITE = website;
-    PHANPY_DEFAULT_INSTANCE = defaultInstance;
-    PHANPY_DEFAULT_INSTANCE_REGISTRATION_URL = defaultInstanceRegistrationUrl;
-    PHANPY_DEFAULT_LANG = defaultLang;
-  };
-
-  installPhase = ''
-    cp -r ./dist $out
-  '';
-
-  meta = {
-    description = "A minimalistic opinionated Mastodon web client ";
-    homepage = "https://github.com/cheeaun/phanpy";
-    license = lib.licenses.mit;
-    maintainers = with lib.maintainers; [ ctucx ];
-  };
-})
diff --git a/renovate.json b/renovate.json
@@ -1,10 +1,9 @@
 {
   "$schema": "https://docs.renovatebot.com/renovate-schema.json",
-  "timezone": "Europe/Berlin",
   "lockFileMaintenance": {
     "enabled": true,
     "automerge": true,
-    "schedule": ["* 0-4 * * *"]
+    "schedule": ["@daily"]
   },
   "nix": {
     "enabled": true
diff --git a/resources/patchedNixpkgsModules/fprintd.nix b/resources/patchedNixpkgsModules/fprintd.nix
@@ -0,0 +1,82 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+
+  cfg = config.services.fprintd;
+  fprintdPkg = if cfg.tod.enable then pkgs.fprintd-tod else pkgs.fprintd;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.fprintd = {
+
+      enable = lib.mkEnableOption "fprintd daemon and PAM module for fingerprint readers handling";
+
+      package = lib.mkOption {
+        type = lib.types.package;
+        default = fprintdPkg;
+        defaultText = lib.literalExpression "if config.services.fprintd.tod.enable then pkgs.fprintd-tod else pkgs.fprintd";
+        description = ''
+          fprintd package to use.
+        '';
+      };
+
+      tod = {
+
+        enable = lib.mkEnableOption "Touch OEM Drivers library support";
+
+        driver = lib.mkOption {
+          type = lib.types.package;
+          example = lib.literalExpression "pkgs.libfprint-2-tod1-goodix";
+          description = ''
+            Touch OEM Drivers (TOD) package to use.
+          '';
+        };
+      };
+
+      lid = {
+        authSkipLidClose = lib.mkOption {
+          type = lib.types.bool;
+          default = false;
+          description = ''
+            Disable fprint auth when laptop with built-in fingerprint reader has lid closed. Useful for docked laptops.
+          '';
+        };
+        path = lib.mkOption {
+          type = lib.types.str;
+          default = "/proc/acpi/button/lid/LID/state";
+          example = "/proc/acpi/button/lid/LID/state";
+          description = ''
+            Path to lid state file.
+          '';
+        };
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = lib.mkIf cfg.enable {
+
+    services.dbus.packages = [ cfg.package ];
+
+    environment.systemPackages = [ cfg.package ];
+
+    systemd.packages = [ cfg.package ];
+
+    systemd.services.fprintd.environment = lib.mkIf cfg.tod.enable {
+      FP_TOD_DRIVERS_DIR = "${cfg.tod.driver}${cfg.tod.driver.driverPath}";
+    };
+
+  };
+
+}
diff --git a/resources/patchedNixpkgsModules/pam.nix b/resources/patchedNixpkgsModules/pam.nix
@@ -0,0 +1,2406 @@
+# This module provides configuration for the PAM (Pluggable
+# Authentication Modules) system.
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+
+  moduleSettingsType =
+    with lib.types;
+    attrsOf (
+      nullOr (oneOf [
+        bool
+        str
+        int
+        pathInStore
+      ])
+    );
+  moduleSettingsDescription = ''
+    Boolean values render just the key if true, and nothing if false.
+    Null values are ignored.
+    All other values are rendered as key-value pairs.
+  '';
+
+  mkRulesTypeOption =
+    type:
+    lib.mkOption {
+      # These options are experimental and subject to breaking changes without notice.
+      description = ''
+        PAM `${type}` rules for this service.
+
+        Attribute keys are the name of each rule.
+      '';
+      type = lib.types.attrsOf (
+        lib.types.submodule (
+          { name, config, ... }:
+          {
+            options = {
+              name = lib.mkOption {
+                type = lib.types.str;
+                description = ''
+                  Name of this rule.
+                '';
+                internal = true;
+                readOnly = true;
+              };
+              enable = lib.mkOption {
+                type = lib.types.bool;
+                default = true;
+                description = ''
+                  Whether this rule is added to the PAM service config file.
+                '';
+              };
+              order = lib.mkOption {
+                type = lib.types.int;
+                description = ''
+                  Order of this rule in the service file. Rules are arranged in ascending order of this value.
+
+                  ::: {.warning}
+                  The `order` values for the built-in rules are subject to change. If you assign a constant value to this option, a system update could silently reorder your rule. You could be locked out of your system, or your system could be left wide open. When using this option, set it to a relative offset from another rule's `order` value:
+
+                  ```nix
+                  {
+                    security.pam.services.login.rules.auth.foo.order =
+                      config.security.pam.services.login.rules.auth.unix.order + 10;
+                  }
+                  ```
+                  :::
+                '';
+              };
+              control = lib.mkOption {
+                type = lib.types.str;
+                description = ''
+                  Indicates the behavior of the PAM-API should the module fail to succeed in its authentication task. See `control` in {manpage}`pam.conf(5)` for details.
+                '';
+              };
+              modulePath = lib.mkOption {
+                type = lib.types.str;
+                description = ''
+                  Either the full filename of the PAM to be used by the application (it begins with a '/'), or a relative pathname from the default module location. See `module-path` in {manpage}`pam.conf(5)` for details.
+                '';
+              };
+              args = lib.mkOption {
+                type = lib.types.listOf lib.types.str;
+                description = ''
+                  Tokens that can be used to modify the specific behavior of the given PAM. Such arguments will be documented for each individual module. See `module-arguments` in {manpage}`pam.conf(5)` for details.
+
+                  Escaping rules for spaces and square brackets are automatically applied.
+
+                  {option}`settings` are automatically added as {option}`args`. It's recommended to use the {option}`settings` option whenever possible so that arguments can be overridden.
+                '';
+              };
+              settings = lib.mkOption {
+                type = moduleSettingsType;
+                default = { };
+                description = ''
+                  Settings to add as `module-arguments`.
+
+                  ${moduleSettingsDescription}
+                '';
+              };
+            };
+            config = {
+              inherit name;
+              # Formats an attrset of settings as args for use as `module-arguments`.
+              args = lib.concatLists (
+                lib.flip lib.mapAttrsToList config.settings (
+                  name: value:
+                  if lib.isBool value then
+                    lib.optional value name
+                  else
+                    lib.optional (value != null) "${name}=${toString value}"
+                )
+              );
+            };
+          }
+        )
+      );
+    };
+
+  package = config.security.pam.package;
+  parentConfig = config;
+
+  pamOpts =
+    { config, name, ... }:
+    let
+      cfg = config;
+    in
+    let
+      config = parentConfig;
+    in
+    {
+
+      imports = [
+        (lib.mkRenamedOptionModule [ "enableKwallet" ] [ "kwallet" "enable" ])
+      ];
+
+      options = {
+
+        name = lib.mkOption {
+          example = "sshd";
+          type = lib.types.str;
+          description = "Name of the PAM service.";
+        };
+
+        enable = lib.mkEnableOption "this PAM service" // {
+          default = true;
+          example = false;
+        };
+
+        rules = lib.mkOption {
+          # This option is experimental and subject to breaking changes without notice.
+          visible = false;
+
+          description = ''
+            PAM rules for this service.
+
+            ::: {.warning}
+            This option and its suboptions are experimental and subject to breaking changes without notice.
+
+            If you use this option in your system configuration, you will need to manually monitor this module for any changes. Otherwise, failure to adjust your configuration properly could lead to you being locked out of your system, or worse, your system could be left wide open to attackers.
+
+            If you share configuration examples that use this option, you MUST include this warning so that users are informed.
+
+            You may freely use this option within `nixpkgs`, and future changes will account for those use sites.
+            :::
+          '';
+          type = lib.types.submodule {
+            options = lib.genAttrs [ "account" "auth" "password" "session" ] mkRulesTypeOption;
+          };
+        };
+
+        unixAuth = lib.mkOption {
+          default = true;
+          type = lib.types.bool;
+          description = ''
+            Whether users can log in with passwords defined in
+            {file}`/etc/shadow`.
+          '';
+        };
+
+        rootOK = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            If set, root doesn't need to authenticate (e.g. for the
+            {command}`useradd` service).
+          '';
+        };
+
+        p11Auth = lib.mkOption {
+          default = config.security.pam.p11.enable;
+          defaultText = lib.literalExpression "config.security.pam.p11.enable";
+          type = lib.types.bool;
+          description = ''
+            If set, keys listed in
+            {file}`~/.ssh/authorized_keys` and
+            {file}`~/.eid/authorized_certificates`
+            can be used to log in with the associated PKCS#11 tokens.
+          '';
+        };
+
+        u2fAuth = lib.mkOption {
+          default = config.security.pam.u2f.enable;
+          defaultText = lib.literalExpression "config.security.pam.u2f.enable";
+          type = lib.types.bool;
+          description = ''
+            If set, users listed in
+            {file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or
+            {file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is
+            not set) are able to log in with the associated U2F key. Path can be
+            changed using {option}`security.pam.u2f.authFile` option.
+          '';
+        };
+
+        usshAuth = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            If set, users with an SSH certificate containing an authorized principal
+            in their SSH agent are able to log in. Specific options are controlled
+            using the {option}`security.pam.ussh` options.
+
+            Note that the  {option}`security.pam.ussh.enable` must also be
+            set for this option to take effect.
+          '';
+        };
+
+        yubicoAuth = lib.mkOption {
+          default = config.security.pam.yubico.enable;
+          defaultText = lib.literalExpression "config.security.pam.yubico.enable";
+          type = lib.types.bool;
+          description = ''
+            If set, users listed in
+            {file}`~/.yubico/authorized_yubikeys`
+            are able to log in with the associated Yubikey tokens.
+          '';
+        };
+
+        googleAuthenticator = {
+          enable = lib.mkOption {
+            default = false;
+            type = lib.types.bool;
+            description = ''
+              If set, users with enabled Google Authenticator (created
+              {file}`~/.google_authenticator`) will be required
+              to provide Google Authenticator token to log in.
+            '';
+          };
+          allowNullOTP = lib.mkOption {
+            type = lib.types.bool;
+            default = false;
+            description = ''
+              Whether to allow login for accounts that have no OTP set
+              (i.e., accounts with no OTP configured or no existing
+              {file}`~/.google_authenticator`).
+            '';
+          };
+          forwardPass = lib.mkOption {
+            type = lib.types.bool;
+            default = false;
+            description = ''
+              The authentication provides a single field requiring
+              the user's password followed by the one-time password (OTP).
+            '';
+          };
+        };
+
+        otpwAuth = lib.mkOption {
+          default = config.security.pam.enableOTPW;
+          defaultText = lib.literalExpression "config.security.pam.enableOTPW";
+          type = lib.types.bool;
+          description = ''
+            If set, the OTPW system will be used (if
+            {file}`~/.otpw` exists).
+          '';
+        };
+
+        googleOsLoginAccountVerification = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            If set, will use the Google OS Login PAM modules
+            (`pam_oslogin_login`,
+            `pam_oslogin_admin`) to verify possible OS Login
+            users and set sudoers configuration accordingly.
+            This only makes sense to enable for the `sshd` PAM
+            service.
+          '';
+        };
+
+        googleOsLoginAuthentication = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            If set, will use the `pam_oslogin_login`'s user
+            authentication methods to authenticate users using 2FA.
+            This only makes sense to enable for the `sshd` PAM
+            service.
+          '';
+        };
+
+        mysqlAuth = lib.mkOption {
+          default = config.users.mysql.enable;
+          defaultText = lib.literalExpression "config.users.mysql.enable";
+          type = lib.types.bool;
+          description = ''
+            If set, the `pam_mysql` module will be used to
+            authenticate users against a MySQL/MariaDB database.
+          '';
+        };
+
+        fprintAuth = lib.mkOption {
+          default = config.services.fprintd.enable;
+          defaultText = lib.literalExpression "config.services.fprintd.enable";
+          type = lib.types.bool;
+          description = ''
+            If set, fingerprint reader will be used (if exists and
+            your fingerprints are enrolled).
+          '';
+        };
+
+        fprintAuthSkipLidClose = lib.mkOption {
+          default = config.services.fprintd.lid.authSkipLidClose;
+          defaultText = lib.literalExpression "config.services.fprintd.authSkipLidClose";
+          type = lib.types.bool;
+          description = ''
+            If set, fprint will not be used if laptop lid closed.
+          '';
+        };
+
+        oathAuth = lib.mkOption {
+          default = config.security.pam.oath.enable;
+          defaultText = lib.literalExpression "config.security.pam.oath.enable";
+          type = lib.types.bool;
+          description = ''
+            If set, the OATH Toolkit will be used.
+          '';
+        };
+
+        sshAgentAuth = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            If set, the calling user's SSH agent is used to authenticate
+            against the keys in the calling user's
+            {file}`~/.ssh/authorized_keys`.  This is useful
+            for {command}`sudo` on password-less remote systems.
+          '';
+        };
+
+        rssh = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            If set, the calling user's SSH agent is used to authenticate
+            against the configured keys. This module works in a manner
+            similar to pam_ssh_agent_auth, but supports a wider range
+            of SSH key types, including those protected by security
+            keys (FIDO2).
+          '';
+        };
+
+        duoSecurity = {
+          enable = lib.mkOption {
+            default = false;
+            type = lib.types.bool;
+            description = ''
+              If set, use the Duo Security pam module
+              `pam_duo` for authentication.  Requires
+              configuration of {option}`security.duosec` options.
+            '';
+          };
+        };
+
+        startSession = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            If set, the service will register a new session with
+            systemd's login manager.  For local sessions, this will give
+            the user access to audio devices, CD-ROM drives.  In the
+            default PolicyKit configuration, it also allows the user to
+            reboot the system.
+          '';
+        };
+
+        setEnvironment = lib.mkOption {
+          type = lib.types.bool;
+          default = true;
+          description = ''
+            Whether the service should set the environment variables
+            listed in {option}`environment.sessionVariables`
+            using `pam_env.so`.
+          '';
+        };
+
+        setLoginUid = lib.mkOption {
+          type = lib.types.bool;
+          description = ''
+            Set the login uid of the process
+            ({file}`/proc/self/loginuid`) for auditing
+            purposes.  The login uid is only set by ‘entry points’ like
+            {command}`login` and {command}`sshd`, not by
+            commands like {command}`sudo`.
+          '';
+        };
+
+        ttyAudit = {
+          enable = lib.mkOption {
+            type = lib.types.bool;
+            default = false;
+            description = ''
+              Enable or disable TTY auditing for specified users
+            '';
+          };
+
+          enablePattern = lib.mkOption {
+            type = lib.types.nullOr lib.types.str;
+            default = null;
+            description = ''
+              For each user matching one of comma-separated
+              glob patterns, enable TTY auditing
+            '';
+          };
+
+          disablePattern = lib.mkOption {
+            type = lib.types.nullOr lib.types.str;
+            default = null;
+            description = ''
+              For each user matching one of comma-separated
+              glob patterns, disable TTY auditing
+            '';
+          };
+
+          openOnly = lib.mkOption {
+            type = lib.types.bool;
+            default = false;
+            description = ''
+              Set the TTY audit flag when opening the session,
+              but do not restore it when closing the session.
+              Using this option is necessary for some services
+              that don't fork() to run the authenticated session,
+              such as sudo.
+            '';
+          };
+        };
+
+        forwardXAuth = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            Whether X authentication keys should be passed from the
+            calling user to the target user (e.g. for
+            {command}`su`)
+          '';
+        };
+
+        pamMount = lib.mkOption {
+          default = config.security.pam.mount.enable;
+          defaultText = lib.literalExpression "config.security.pam.mount.enable";
+          type = lib.types.bool;
+          description = ''
+            Enable PAM mount (pam_mount) system to mount filesystems on user login.
+          '';
+        };
+
+        allowNullPassword = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            Whether to allow logging into accounts that have no password
+            set (i.e., have an empty password field in
+            {file}`/etc/passwd` or
+            {file}`/etc/group`).  This does not enable
+            logging into disabled accounts (i.e., that have the password
+            field set to `!`).  Note that regardless of
+            what the pam_unix documentation says, accounts with hashed
+            empty passwords are always allowed to log in.
+          '';
+        };
+
+        nodelay = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            Whether the delay after typing a wrong password should be disabled.
+          '';
+        };
+
+        requireWheel = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            Whether to permit root access only to members of group wheel.
+          '';
+        };
+
+        limits = lib.mkOption {
+          default = [ ];
+          type = limitsType;
+          description = ''
+            Attribute set describing resource limits.  Defaults to the
+            value of {option}`security.pam.loginLimits`.
+            The meaning of the values is explained in {manpage}`limits.conf(5)`.
+          '';
+        };
+
+        showMotd = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = "Whether to show the message of the day.";
+        };
+
+        makeHomeDir = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            Whether to try to create home directories for users
+            with `$HOME`s pointing to nonexistent
+            locations on session login.
+          '';
+        };
+
+        updateWtmp = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = "Whether to update {file}`/var/log/wtmp`.";
+        };
+
+        logFailures = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = "Whether to log authentication failures in {file}`/var/log/faillog`.";
+        };
+
+        enableAppArmor = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            Enable support for attaching AppArmor profiles at the
+            user/group level, e.g., as part of a role based access
+            control scheme.
+          '';
+        };
+
+        kwallet = {
+          enable = lib.mkOption {
+            default = false;
+            type = lib.types.bool;
+            description = ''
+              If enabled, pam_wallet will attempt to automatically unlock the
+              user's default KDE wallet upon login. If the user has no wallet named
+              "kdewallet", or the login password does not match their wallet
+              password, KDE will prompt separately after login.
+            '';
+          };
+
+          package = lib.mkPackageOption pkgs.plasma5Packages "kwallet-pam" {
+            pkgsText = "pkgs.plasma5Packages";
+          };
+
+          forceRun = lib.mkEnableOption null // {
+            description = ''
+              The `force_run` option is used to tell the PAM module for KWallet
+              to forcefully run even if no graphical session (such as a GUI
+              display manager) is detected. This is useful for when you are
+              starting an X Session or a Wayland Session from a TTY. If you
+              intend to log-in from a TTY, it is recommended that you enable
+              this option **and** ensure that `plasma-kwallet-pam.service` is
+              started by `graphical-session.target`.
+            '';
+          };
+        };
+
+        sssdStrictAccess = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = "enforce sssd access control";
+        };
+
+        enableGnomeKeyring = lib.mkOption {
+          default = false;
+          type = lib.types.bool;
+          description = ''
+            If enabled, pam_gnome_keyring will attempt to automatically unlock the
+            user's default Gnome keyring upon login. If the user login password does
+            not match their keyring password, Gnome Keyring will prompt separately
+            after login.
+          '';
+        };
+
+        failDelay = {
+          enable = lib.mkOption {
+            type = lib.types.bool;
+            default = false;
+            description = ''
+              If enabled, this will replace the `FAIL_DELAY` setting from `login.defs`.
+              Change the delay on failure per-application.
+            '';
+          };
+
+          delay = lib.mkOption {
+            default = 3000000;
+            type = lib.types.int;
+            example = 1000000;
+            description = "The delay time (in microseconds) on failure.";
+          };
+        };
+
+        gnupg = {
+          enable = lib.mkOption {
+            type = lib.types.bool;
+            default = false;
+            description = ''
+              If enabled, pam_gnupg will attempt to automatically unlock the
+              user's GPG keys with the login password via
+              {command}`gpg-agent`. The keygrips of all keys to be
+              unlocked should be written to {file}`~/.pam-gnupg`,
+              and can be queried with {command}`gpg -K --with-keygrip`.
+              Presetting passphrases must be enabled by adding
+              `allow-preset-passphrase` in
+              {file}`~/.gnupg/gpg-agent.conf`.
+            '';
+          };
+
+          noAutostart = lib.mkOption {
+            type = lib.types.bool;
+            default = false;
+            description = ''
+              Don't start {command}`gpg-agent` if it is not running.
+              Useful in conjunction with starting {command}`gpg-agent` as
+              a systemd user service.
+            '';
+          };
+
+          storeOnly = lib.mkOption {
+            type = lib.types.bool;
+            default = false;
+            description = ''
+              Don't send the password immediately after login, but store for PAM
+              `session`.
+            '';
+          };
+        };
+
+        zfs = lib.mkOption {
+          default = config.security.pam.zfs.enable;
+          defaultText = lib.literalExpression "config.security.pam.zfs.enable";
+          type = lib.types.bool;
+          description = ''
+            Enable unlocking and mounting of encrypted ZFS home dataset at login.
+          '';
+        };
+
+        text = lib.mkOption {
+          type = lib.types.nullOr lib.types.lines;
+          description = "Contents of the PAM service file.";
+        };
+
+      };
+
+      # The resulting /etc/pam.d/* file contents are verified in
+      # nixos/tests/pam/pam-file-contents.nix. Please update tests there when
+      # changing the derivation.
+      config = {
+        name = lib.mkDefault name;
+        setLoginUid = lib.mkDefault cfg.startSession;
+        limits = lib.mkDefault config.security.pam.loginLimits;
+
+        text =
+          let
+            ensureUniqueOrder =
+              type: rules:
+              let
+                checkPair =
+                  a: b:
+                  assert lib.assertMsg (a.order != b.order)
+                    "security.pam.services.${name}.rules.${type}: rules '${a.name}' and '${b.name}' cannot have the same order value (${toString a.order})";
+                  b;
+                checked = lib.zipListsWith checkPair rules (lib.drop 1 rules);
+              in
+              lib.take 1 rules ++ checked;
+            # Formats a string for use in `module-arguments`. See `man pam.conf`.
+            formatModuleArgument =
+              token: if lib.hasInfix " " token then "[${lib.replaceStrings [ "]" ] [ "\\]" ] token}]" else token;
+            formatRules =
+              type:
+              lib.pipe cfg.rules.${type} [
+                lib.attrValues
+                (lib.filter (rule: rule.enable))
+                (lib.sort (a: b: a.order < b.order))
+                (ensureUniqueOrder type)
+                (map (
+                  rule:
+                  lib.concatStringsSep " " (
+                    [
+                      type
+                      rule.control
+                      rule.modulePath
+                    ]
+                    ++ map formatModuleArgument rule.args
+                    ++ [ "# ${rule.name} (order ${toString rule.order})" ]
+                  )
+                ))
+                (lib.concatStringsSep "\n")
+              ];
+          in
+          lib.mkDefault ''
+            # Account management.
+            ${formatRules "account"}
+
+            # Authentication management.
+            ${formatRules "auth"}
+
+            # Password management.
+            ${formatRules "password"}
+
+            # Session management.
+            ${formatRules "session"}
+          '';
+
+        # !!! TODO: move the LDAP stuff to the LDAP module, and the
+        # Samba stuff to the Samba module.  This requires that the PAM
+        # module provides the right hooks.
+        rules =
+          let
+            autoOrderRules = lib.flip lib.pipe [
+              (lib.imap1 (index: rule: rule // { order = lib.mkDefault (10000 + index * 100); }))
+              (map (rule: lib.nameValuePair rule.name (removeAttrs rule [ "name" ])))
+              lib.listToAttrs
+            ];
+          in
+          {
+            account = autoOrderRules [
+              {
+                name = "ldap";
+                enable = use_ldap;
+                control = "sufficient";
+                modulePath = "${pam_ldap}/lib/security/pam_ldap.so";
+              }
+              {
+                name = "mysql";
+                enable = cfg.mysqlAuth;
+                control = "sufficient";
+                modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so";
+                settings = {
+                  config_file = "/etc/security/pam_mysql.conf";
+                };
+              }
+              {
+                name = "kanidm";
+                enable = config.services.kanidm.enablePam;
+                control = "sufficient";
+                modulePath = "${config.services.kanidm.package}/lib/pam_kanidm.so";
+                settings = {
+                  ignore_unknown_user = true;
+                };
+              }
+              {
+                name = "sss";
+                enable = config.services.sssd.enable;
+                control =
+                  if cfg.sssdStrictAccess then "[default=bad success=ok user_unknown=ignore]" else "sufficient";
+                modulePath = "${pkgs.sssd}/lib/security/pam_sss.so";
+              }
+              {
+                name = "krb5";
+                enable = config.security.pam.krb5.enable;
+                control = "sufficient";
+                modulePath = "${pam_krb5}/lib/security/pam_krb5.so";
+              }
+              {
+                name = "oslogin_login";
+                enable = cfg.googleOsLoginAccountVerification;
+                control = "[success=ok ignore=ignore default=die]";
+                modulePath = "${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so";
+              }
+              {
+                name = "oslogin_admin";
+                enable = cfg.googleOsLoginAccountVerification;
+                control = "[success=ok default=ignore]";
+                modulePath = "${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so";
+              }
+              {
+                name = "systemd_home";
+                enable = config.services.homed.enable;
+                control = "sufficient";
+                modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so";
+              }
+              # The required pam_unix.so module has to come after all the sufficient modules
+              # because otherwise, the account lookup will fail if the user does not exist
+              # locally, for example with MySQL- or LDAP-auth.
+              {
+                name = "unix";
+                control = "required";
+                modulePath = "${package}/lib/security/pam_unix.so";
+              }
+            ];
+
+            auth = autoOrderRules (
+              [
+                {
+                  name = "oslogin_login";
+                  enable = cfg.googleOsLoginAuthentication;
+                  control = "[success=done perm_denied=die default=ignore]";
+                  modulePath = "${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so";
+                }
+                {
+                  name = "rootok";
+                  enable = cfg.rootOK;
+                  control = "sufficient";
+                  modulePath = "${package}/lib/security/pam_rootok.so";
+                }
+                {
+                  name = "wheel";
+                  enable = cfg.requireWheel;
+                  control = "required";
+                  modulePath = "${package}/lib/security/pam_wheel.so";
+                  settings = {
+                    use_uid = true;
+                  };
+                }
+                {
+                  name = "faillock";
+                  enable = cfg.logFailures;
+                  control = "required";
+                  modulePath = "${package}/lib/security/pam_faillock.so";
+                }
+                {
+                  name = "mysql";
+                  enable = cfg.mysqlAuth;
+                  control = "sufficient";
+                  modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so";
+                  settings = {
+                    config_file = "/etc/security/pam_mysql.conf";
+                  };
+                }
+                {
+                  name = "ssh_agent_auth";
+                  enable = config.security.pam.sshAgentAuth.enable && cfg.sshAgentAuth;
+                  control = "sufficient";
+                  modulePath = "${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so";
+                  settings = {
+                    file = lib.concatStringsSep ":" config.security.pam.sshAgentAuth.authorizedKeysFiles;
+                  };
+                }
+                (
+                  let
+                    inherit (config.security.pam) rssh;
+                  in
+                  {
+                    name = "rssh";
+                    enable = rssh.enable && cfg.rssh;
+                    control = "sufficient";
+                    modulePath = "${pkgs.pam_rssh}/lib/libpam_rssh.so";
+                    inherit (rssh) settings;
+                  }
+                )
+                (
+                  let
+                    p11 = config.security.pam.p11;
+                  in
+                  {
+                    name = "p11";
+                    enable = cfg.p11Auth;
+                    control = p11.control;
+                    modulePath = "${pkgs.pam_p11}/lib/security/pam_p11.so";
+                    args = [
+                      "${pkgs.opensc}/lib/opensc-pkcs11.so"
+                    ];
+                  }
+                )
+                (
+                  let
+                    u2f = config.security.pam.u2f;
+                  in
+                  {
+                    name = "u2f";
+                    enable = cfg.u2fAuth;
+                    control = u2f.control;
+                    modulePath = "${pkgs.pam_u2f}/lib/security/pam_u2f.so";
+                    inherit (u2f) settings;
+                  }
+                )
+                (
+                  let
+                    ussh = config.security.pam.ussh;
+                  in
+                  {
+                    name = "ussh";
+                    enable = config.security.pam.ussh.enable && cfg.usshAuth;
+                    control = ussh.control;
+                    modulePath = "${pkgs.pam_ussh}/lib/security/pam_ussh.so";
+                    settings = {
+                      ca_file = ussh.caFile;
+                      authorized_principals = ussh.authorizedPrincipals;
+                      authorized_principals_file = ussh.authorizedPrincipalsFile;
+                      inherit (ussh) group;
+                    };
+                  }
+                )
+                (
+                  let
+                    oath = config.security.pam.oath;
+                  in
+                  {
+                    name = "oath";
+                    enable = cfg.oathAuth;
+                    control = "requisite";
+                    modulePath = "${pkgs.oath-toolkit}/lib/security/pam_oath.so";
+                    settings = {
+                      inherit (oath) window digits;
+                      usersfile = oath.usersFile;
+                    };
+                  }
+                )
+                (
+                  let
+                    yubi = config.security.pam.yubico;
+                  in
+                  {
+                    name = "yubico";
+                    enable = cfg.yubicoAuth;
+                    control = yubi.control;
+                    modulePath = "${pkgs.yubico-pam}/lib/security/pam_yubico.so";
+                    settings = {
+                      inherit (yubi) mode debug;
+                      chalresp_path = yubi.challengeResponsePath;
+                      id = lib.mkIf (yubi.mode == "client") yubi.id;
+                    };
+                  }
+                )
+                (
+                  let
+                    dp9ik = config.security.pam.dp9ik;
+                  in
+                  {
+                    name = "p9";
+                    enable = dp9ik.enable;
+                    control = dp9ik.control;
+                    modulePath = "${pkgs.pam_dp9ik}/lib/security/pam_p9.so";
+                    args = [
+                      dp9ik.authserver
+                    ];
+                  }
+                )
+                (
+                  let
+                    lid = pkgs.writeShellScript "lid.sh" "${pkgs.gnugrep}/bin/grep -q closed ${config.services.fprintd.lid.path} && exit 1; true";
+                  in
+                  {
+                    name = "fprintd-lid";
+                    enable = cfg.fprintAuthSkipLidClose;
+                    control = "[success=ignore default=1]";
+                    modulePath = "${pkgs.linux-pam}/lib/security/pam_exec.so";
+                    args = [
+                      "quiet"
+                      "${lid}"
+                    ];
+                  }
+                )
+                {
+                  name = "fprintd";
+                  enable = cfg.fprintAuth;
+                  control = "sufficient";
+                  modulePath = "${config.services.fprintd.package}/lib/security/pam_fprintd.so";
+                }
+              ]
+              ++
+                # Modules in this block require having the password set in PAM_AUTHTOK.
+                # pam_unix is marked as 'sufficient' on NixOS which means nothing will run
+                # after it succeeds. Certain modules need to run after pam_unix
+                # prompts the user for password so we run it once with 'optional' at an
+                # earlier point and it will run again with 'sufficient' further down.
+                # We use try_first_pass the second time to avoid prompting password twice.
+                #
+                # The same principle applies to systemd-homed
+                (lib.optionals
+                  (
+                    (cfg.unixAuth || config.services.homed.enable)
+                    && (
+                      config.security.pam.enableEcryptfs
+                      || config.security.pam.enableFscrypt
+                      || cfg.pamMount
+                      || cfg.kwallet.enable
+                      || cfg.enableGnomeKeyring
+                      || config.services.intune.enable
+                      || cfg.googleAuthenticator.enable
+                      || cfg.gnupg.enable
+                      || cfg.failDelay.enable
+                      || cfg.duoSecurity.enable
+                      || cfg.zfs
+                    )
+                  )
+                  [
+                    {
+                      name = "systemd_home-early";
+                      enable = config.services.homed.enable;
+                      control = "optional";
+                      modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so";
+                    }
+                    {
+                      name = "unix-early";
+                      enable = cfg.unixAuth;
+                      control = "optional";
+                      modulePath = "${package}/lib/security/pam_unix.so";
+                      settings = {
+                        nullok = cfg.allowNullPassword;
+                        inherit (cfg) nodelay;
+                        likeauth = true;
+                      };
+                    }
+                    {
+                      name = "ecryptfs";
+                      enable = config.security.pam.enableEcryptfs;
+                      control = "optional";
+                      modulePath = "${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so";
+                      settings = {
+                        unwrap = true;
+                      };
+                    }
+                    {
+                      name = "fscrypt";
+                      enable = config.security.pam.enableFscrypt;
+                      control = "optional";
+                      modulePath = "${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so";
+                    }
+                    {
+                      name = "zfs_key";
+                      enable = cfg.zfs;
+                      control = "optional";
+                      modulePath = "${config.boot.zfs.package}/lib/security/pam_zfs_key.so";
+                      settings = {
+                        inherit (config.security.pam.zfs) homes;
+                      };
+                    }
+                    {
+                      name = "mount";
+                      enable = cfg.pamMount;
+                      control = "optional";
+                      modulePath = "${pkgs.pam_mount}/lib/security/pam_mount.so";
+                      settings = {
+                        disable_interactive = true;
+                      };
+                    }
+                    {
+                      name = "kwallet";
+                      enable = cfg.kwallet.enable;
+                      control = "optional";
+                      modulePath = "${cfg.kwallet.package}/lib/security/pam_kwallet5.so";
+                    }
+                    {
+                      name = "gnome_keyring";
+                      enable = cfg.enableGnomeKeyring;
+                      control = "optional";
+                      modulePath = "${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so";
+                    }
+                    {
+                      name = "intune";
+                      enable = config.services.intune.enable;
+                      control = "optional";
+                      modulePath = "${pkgs.intune-portal}/lib/security/pam_intune.so";
+                    }
+                    {
+                      name = "gnupg";
+                      enable = cfg.gnupg.enable;
+                      control = "optional";
+                      modulePath = "${pkgs.pam_gnupg}/lib/security/pam_gnupg.so";
+                      settings = {
+                        store-only = cfg.gnupg.storeOnly;
+                      };
+                    }
+                    {
+                      name = "faildelay";
+                      enable = cfg.failDelay.enable;
+                      control = "optional";
+                      modulePath = "${package}/lib/security/pam_faildelay.so";
+                      settings = {
+                        inherit (cfg.failDelay) delay;
+                      };
+                    }
+                    {
+                      name = "google_authenticator";
+                      enable = cfg.googleAuthenticator.enable;
+                      control = "required";
+                      modulePath = "${pkgs.google-authenticator}/lib/security/pam_google_authenticator.so";
+                      settings = {
+                        no_increment_hotp = true;
+                        forward_pass = cfg.googleAuthenticator.forwardPass;
+                        nullok = cfg.googleAuthenticator.allowNullOTP;
+                      };
+                    }
+                    {
+                      name = "duo";
+                      enable = cfg.duoSecurity.enable;
+                      control = "required";
+                      modulePath = "${pkgs.duo-unix}/lib/security/pam_duo.so";
+                    }
+                  ]
+                )
+              ++ [
+                {
+                  name = "systemd_home";
+                  enable = config.services.homed.enable;
+                  control = "sufficient";
+                  modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so";
+                }
+                {
+                  name = "unix";
+                  enable = cfg.unixAuth;
+                  control = "sufficient";
+                  modulePath = "${package}/lib/security/pam_unix.so";
+                  settings = {
+                    nullok = cfg.allowNullPassword;
+                    inherit (cfg) nodelay;
+                    likeauth = true;
+                    try_first_pass = true;
+                  };
+                }
+                {
+                  name = "otpw";
+                  enable = cfg.otpwAuth;
+                  control = "sufficient";
+                  modulePath = "${pkgs.otpw}/lib/security/pam_otpw.so";
+                }
+                {
+                  name = "ldap";
+                  enable = use_ldap;
+                  control = "sufficient";
+                  modulePath = "${pam_ldap}/lib/security/pam_ldap.so";
+                  settings = {
+                    use_first_pass = true;
+                  };
+                }
+                {
+                  name = "kanidm";
+                  enable = config.services.kanidm.enablePam;
+                  control = "sufficient";
+                  modulePath = "${config.services.kanidm.package}/lib/pam_kanidm.so";
+                  settings = {
+                    ignore_unknown_user = true;
+                    use_first_pass = true;
+                  };
+                }
+                {
+                  name = "sss";
+                  enable = config.services.sssd.enable;
+                  control = "sufficient";
+                  modulePath = "${pkgs.sssd}/lib/security/pam_sss.so";
+                  settings = {
+                    use_first_pass = true;
+                  };
+                }
+                {
+                  name = "krb5";
+                  enable = config.security.pam.krb5.enable;
+                  control = "[default=ignore success=1 service_err=reset]";
+                  modulePath = "${pam_krb5}/lib/security/pam_krb5.so";
+                  settings = {
+                    use_first_pass = true;
+                  };
+                }
+                {
+                  name = "ccreds-validate";
+                  enable = config.security.pam.krb5.enable;
+                  control = "[default=die success=done]";
+                  modulePath = "${pam_ccreds}/lib/security/pam_ccreds.so";
+                  settings = {
+                    action = "validate";
+                    use_first_pass = true;
+                  };
+                }
+                {
+                  name = "ccreds-store";
+                  enable = config.security.pam.krb5.enable;
+                  control = "sufficient";
+                  modulePath = "${pam_ccreds}/lib/security/pam_ccreds.so";
+                  settings = {
+                    action = "store";
+                    use_first_pass = true;
+                  };
+                }
+                {
+                  name = "deny";
+                  control = "required";
+                  modulePath = "${package}/lib/security/pam_deny.so";
+                }
+              ]
+            );
+
+            password = autoOrderRules [
+              {
+                name = "systemd_home";
+                enable = config.services.homed.enable;
+                control = "sufficient";
+                modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so";
+              }
+              {
+                name = "unix";
+                control = "sufficient";
+                modulePath = "${package}/lib/security/pam_unix.so";
+                settings = {
+                  nullok = true;
+                  yescrypt = true;
+                };
+              }
+              {
+                name = "ecryptfs";
+                enable = config.security.pam.enableEcryptfs;
+                control = "optional";
+                modulePath = "${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so";
+              }
+              {
+                name = "fscrypt";
+                enable = config.security.pam.enableFscrypt;
+                control = "optional";
+                modulePath = "${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so";
+              }
+              {
+                name = "zfs_key";
+                enable = cfg.zfs;
+                control = "optional";
+                modulePath = "${config.boot.zfs.package}/lib/security/pam_zfs_key.so";
+                settings = {
+                  inherit (config.security.pam.zfs) homes;
+                };
+              }
+              {
+                name = "mount";
+                enable = cfg.pamMount;
+                control = "optional";
+                modulePath = "${pkgs.pam_mount}/lib/security/pam_mount.so";
+              }
+              {
+                name = "ldap";
+                enable = use_ldap;
+                control = "sufficient";
+                modulePath = "${pam_ldap}/lib/security/pam_ldap.so";
+              }
+              {
+                name = "mysql";
+                enable = cfg.mysqlAuth;
+                control = "sufficient";
+                modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so";
+                settings = {
+                  config_file = "/etc/security/pam_mysql.conf";
+                };
+              }
+              {
+                name = "kanidm";
+                enable = config.services.kanidm.enablePam;
+                control = "sufficient";
+                modulePath = "${config.services.kanidm.package}/lib/pam_kanidm.so";
+              }
+              {
+                name = "sss";
+                enable = config.services.sssd.enable;
+                control = "sufficient";
+                modulePath = "${pkgs.sssd}/lib/security/pam_sss.so";
+              }
+              {
+                name = "krb5";
+                enable = config.security.pam.krb5.enable;
+                control = "sufficient";
+                modulePath = "${pam_krb5}/lib/security/pam_krb5.so";
+                settings = {
+                  use_first_pass = true;
+                };
+              }
+              {
+                name = "gnome_keyring";
+                enable = cfg.enableGnomeKeyring;
+                control = "optional";
+                modulePath = "${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so";
+                settings = {
+                  use_authtok = true;
+                };
+              }
+            ];
+
+            session = autoOrderRules [
+              {
+                name = "env";
+                enable = cfg.setEnvironment;
+                control = "required";
+                modulePath = "${package}/lib/security/pam_env.so";
+                settings = {
+                  conffile = "/etc/pam/environment";
+                  readenv = 0;
+                };
+              }
+              {
+                name = "unix";
+                control = "required";
+                modulePath = "${package}/lib/security/pam_unix.so";
+              }
+              {
+                name = "loginuid";
+                enable = cfg.setLoginUid;
+                control = if config.boot.isContainer then "optional" else "required";
+                modulePath = "${package}/lib/security/pam_loginuid.so";
+              }
+              {
+                name = "tty_audit";
+                enable = cfg.ttyAudit.enable;
+                control = "required";
+                modulePath = "${package}/lib/security/pam_tty_audit.so";
+                settings = {
+                  open_only = cfg.ttyAudit.openOnly;
+                  enable = cfg.ttyAudit.enablePattern;
+                  disable = cfg.ttyAudit.disablePattern;
+                };
+              }
+              {
+                name = "systemd_home";
+                enable = config.services.homed.enable;
+                control = "required";
+                modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so";
+              }
+              {
+                name = "mkhomedir";
+                enable = cfg.makeHomeDir;
+                control = "required";
+                modulePath = "${package}/lib/security/pam_mkhomedir.so";
+                settings = {
+                  silent = true;
+                  skel = config.security.pam.makeHomeDir.skelDirectory;
+                  inherit (config.security.pam.makeHomeDir) umask;
+                };
+              }
+              {
+                name = "lastlog";
+                enable = cfg.updateWtmp;
+                control = "required";
+                modulePath = "${package}/lib/security/pam_lastlog.so";
+                settings = {
+                  silent = true;
+                };
+              }
+              {
+                name = "ecryptfs";
+                enable = config.security.pam.enableEcryptfs;
+                control = "optional";
+                modulePath = "${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so";
+              }
+              # Work around https://github.com/systemd/systemd/issues/8598
+              # Skips the pam_fscrypt module for systemd-user sessions which do not have a password
+              # anyways.
+              # See also https://github.com/google/fscrypt/issues/95
+              {
+                name = "fscrypt-skip-systemd";
+                enable = config.security.pam.enableFscrypt;
+                control = "[success=1 default=ignore]";
+                modulePath = "${package}/lib/security/pam_succeed_if.so";
+                args = [
+                  "service"
+                  "="
+                  "systemd-user"
+                ];
+              }
+              {
+                name = "fscrypt";
+                enable = config.security.pam.enableFscrypt;
+                control = "optional";
+                modulePath = "${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so";
+              }
+              {
+                name = "zfs_key-skip-systemd";
+                enable = cfg.zfs;
+                control = "[success=1 default=ignore]";
+                modulePath = "${package}/lib/security/pam_succeed_if.so";
+                args = [
+                  "service"
+                  "="
+                  "systemd-user"
+                ];
+              }
+              {
+                name = "zfs_key";
+                enable = cfg.zfs;
+                control = "optional";
+                modulePath = "${config.boot.zfs.package}/lib/security/pam_zfs_key.so";
+                settings = {
+                  inherit (config.security.pam.zfs) homes;
+                  nounmount = config.security.pam.zfs.noUnmount;
+                };
+              }
+              {
+                name = "mount";
+                enable = cfg.pamMount;
+                control = "optional";
+                modulePath = "${pkgs.pam_mount}/lib/security/pam_mount.so";
+                settings = {
+                  disable_interactive = true;
+                };
+              }
+              {
+                name = "ldap";
+                enable = use_ldap;
+                control = "optional";
+                modulePath = "${pam_ldap}/lib/security/pam_ldap.so";
+              }
+              {
+                name = "mysql";
+                enable = cfg.mysqlAuth;
+                control = "optional";
+                modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so";
+                settings = {
+                  config_file = "/etc/security/pam_mysql.conf";
+                };
+              }
+              {
+                name = "kanidm";
+                enable = config.services.kanidm.enablePam;
+                control = "optional";
+                modulePath = "${config.services.kanidm.package}/lib/pam_kanidm.so";
+              }
+              {
+                name = "sss";
+                enable = config.services.sssd.enable;
+                control = "optional";
+                modulePath = "${pkgs.sssd}/lib/security/pam_sss.so";
+              }
+              {
+                name = "krb5";
+                enable = config.security.pam.krb5.enable;
+                control = "optional";
+                modulePath = "${pam_krb5}/lib/security/pam_krb5.so";
+              }
+              {
+                name = "otpw";
+                enable = cfg.otpwAuth;
+                control = "optional";
+                modulePath = "${pkgs.otpw}/lib/security/pam_otpw.so";
+              }
+              {
+                name = "systemd";
+                enable = cfg.startSession;
+                control = "optional";
+                modulePath = "${config.systemd.package}/lib/security/pam_systemd.so";
+              }
+              {
+                name = "xauth";
+                enable = cfg.forwardXAuth;
+                control = "optional";
+                modulePath = "${package}/lib/security/pam_xauth.so";
+                settings = {
+                  xauthpath = "${pkgs.xorg.xauth}/bin/xauth";
+                  systemuser = 99;
+                };
+              }
+              {
+                name = "limits";
+                enable = cfg.limits != [ ];
+                control = "required";
+                modulePath = "${package}/lib/security/pam_limits.so";
+                settings = {
+                  conf = "${makeLimitsConf cfg.limits}";
+                };
+              }
+              {
+                name = "motd";
+                enable = cfg.showMotd && (config.users.motd != "" || config.users.motdFile != null);
+                control = "optional";
+                modulePath = "${package}/lib/security/pam_motd.so";
+                settings = {
+                  inherit motd;
+                };
+              }
+              {
+                name = "apparmor";
+                enable = cfg.enableAppArmor && config.security.apparmor.enable;
+                control = "optional";
+                modulePath = "${pkgs.apparmor-pam}/lib/security/pam_apparmor.so";
+                settings = {
+                  order = "user,group,default";
+                  debug = true;
+                };
+              }
+              {
+                name = "kwallet";
+                enable = cfg.kwallet.enable;
+                control = "optional";
+                modulePath = "${cfg.kwallet.package}/lib/security/pam_kwallet5.so";
+                settings = lib.mkIf cfg.kwallet.forceRun { force_run = true; };
+              }
+              {
+                name = "gnome_keyring";
+                enable = cfg.enableGnomeKeyring;
+                control = "optional";
+                modulePath = "${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so";
+                settings = {
+                  auto_start = true;
+                };
+              }
+              {
+                name = "gnupg";
+                enable = cfg.gnupg.enable;
+                control = "optional";
+                modulePath = "${pkgs.pam_gnupg}/lib/security/pam_gnupg.so";
+                settings = {
+                  no-autostart = cfg.gnupg.noAutostart;
+                };
+              }
+              {
+                name = "intune";
+                enable = config.services.intune.enable;
+                control = "optional";
+                modulePath = "${pkgs.intune-portal}/lib/security/pam_intune.so";
+              }
+            ];
+          };
+      };
+
+    };
+
+  inherit (pkgs) pam_krb5 pam_ccreds;
+
+  use_ldap = (config.users.ldap.enable && config.users.ldap.loginPam);
+  pam_ldap = if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap;
+
+  # Create a limits.conf(5) file.
+  makeLimitsConf =
+    limits:
+    pkgs.writeText "limits.conf" (
+      lib.concatMapStrings (
+        {
+          domain,
+          type,
+          item,
+          value,
+        }:
+        "${domain} ${type} ${item} ${toString value}\n"
+      ) limits
+    );
+
+  limitsType =
+    with lib.types;
+    listOf (
+      submodule (
+        { ... }:
+        {
+          options = {
+            domain = lib.mkOption {
+              description = "Username, groupname, or wildcard this limit applies to";
+              example = "@wheel";
+              type = str;
+            };
+
+            type = lib.mkOption {
+              description = "Type of this limit";
+              type = enum [
+                "-"
+                "hard"
+                "soft"
+              ];
+              default = "-";
+            };
+
+            item = lib.mkOption {
+              description = "Item this limit applies to";
+              type = enum [
+                "core"
+                "data"
+                "fsize"
+                "memlock"
+                "nofile"
+                "rss"
+                "stack"
+                "cpu"
+                "nproc"
+                "as"
+                "maxlogins"
+                "maxsyslogins"
+                "priority"
+                "locks"
+                "sigpending"
+                "msgqueue"
+                "nice"
+                "rtprio"
+              ];
+            };
+
+            value = lib.mkOption {
+              description = "Value of this limit";
+              type = oneOf [
+                str
+                int
+              ];
+            };
+          };
+        }
+      )
+    );
+
+  motd =
+    if config.users.motdFile == null then
+      pkgs.writeText "motd" config.users.motd
+    else
+      config.users.motdFile;
+
+  makePAMService = name: service: {
+    name = "pam.d/${name}";
+    value.source = pkgs.writeText "${name}.pam" service.text;
+  };
+
+  optionalSudoConfigForSSHAgentAuth =
+    lib.optionalString (config.security.pam.sshAgentAuth.enable || config.security.pam.rssh.enable)
+      ''
+        # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so and libpam_rssh.so can do their magic.
+        Defaults env_keep+=SSH_AUTH_SOCK
+      '';
+
+  enabledServices = lib.filterAttrs (name: svc: svc.enable) config.security.pam.services;
+
+in
+
+{
+
+  meta.maintainers = [ lib.maintainers.majiir ];
+
+  imports = [
+    (lib.mkRenamedOptionModule [ "security" "pam" "enableU2F" ] [ "security" "pam" "u2f" "enable" ])
+    (lib.mkRenamedOptionModule
+      [ "security" "pam" "enableSSHAgentAuth" ]
+      [ "security" "pam" "sshAgentAuth" "enable" ]
+    )
+    (lib.mkRenamedOptionModule
+      [ "security" "pam" "u2f" "authFile" ]
+      [ "security" "pam" "u2f" "settings" "authfile" ]
+    )
+    (lib.mkRenamedOptionModule
+      [ "security" "pam" "u2f" "appId" ]
+      [ "security" "pam" "u2f" "settings" "appid" ]
+    )
+    (lib.mkRenamedOptionModule
+      [ "security" "pam" "u2f" "origin" ]
+      [ "security" "pam" "u2f" "settings" "origin" ]
+    )
+    (lib.mkRenamedOptionModule
+      [ "security" "pam" "u2f" "debug" ]
+      [ "security" "pam" "u2f" "settings" "debug" ]
+    )
+    (lib.mkRenamedOptionModule
+      [ "security" "pam" "u2f" "interactive" ]
+      [ "security" "pam" "u2f" "settings" "interactive" ]
+    )
+    (lib.mkRenamedOptionModule
+      [ "security" "pam" "u2f" "cue" ]
+      [ "security" "pam" "u2f" "settings" "cue" ]
+    )
+  ];
+
+  ###### interface
+
+  options = {
+
+    security.pam.package = lib.mkPackageOption pkgs "pam" { };
+
+    security.pam.loginLimits = lib.mkOption {
+      default = [ ];
+      type = limitsType;
+      example = [
+        {
+          domain = "ftp";
+          type = "hard";
+          item = "nproc";
+          value = "0";
+        }
+        {
+          domain = "@student";
+          type = "-";
+          item = "maxlogins";
+          value = "4";
+        }
+      ];
+
+      description = ''
+        Define resource limits that should apply to users or groups.
+        Each item in the list should be an attribute set with a
+        {var}`domain`, {var}`type`,
+        {var}`item`, and {var}`value`
+        attribute.  The syntax and semantics of these attributes
+        must be that described in {manpage}`limits.conf(5)`.
+
+        Note that these limits do not apply to systemd services,
+        whose limits can be changed via {option}`systemd.extraConfig`
+        instead.
+      '';
+    };
+
+    security.pam.services = lib.mkOption {
+      default = { };
+      type = with lib.types; attrsOf (submodule pamOpts);
+      description = ''
+        This option defines the PAM services.  A service typically
+        corresponds to a program that uses PAM,
+        e.g. {command}`login` or {command}`passwd`.
+        Each attribute of this set defines a PAM service, with the attribute name
+        defining the name of the service.
+      '';
+    };
+
+    security.pam.makeHomeDir.skelDirectory = lib.mkOption {
+      type = lib.types.str;
+      default = "/var/empty";
+      example = "/etc/skel";
+      description = ''
+        Path to skeleton directory whose contents are copied to home
+        directories newly created by `pam_mkhomedir`.
+      '';
+    };
+
+    security.pam.makeHomeDir.umask = lib.mkOption {
+      type = lib.types.str;
+      default = "0077";
+      example = "0022";
+      description = ''
+        The user file mode creation mask to use on home directories
+        newly created by `pam_mkhomedir`.
+      '';
+    };
+
+    security.pam.sshAgentAuth = {
+      enable = lib.mkEnableOption ''
+        authenticating using a signature performed by the ssh-agent.
+        This allows using SSH keys exclusively, instead of passwords, for instance on remote machines
+      '';
+
+      authorizedKeysFiles = lib.mkOption {
+        type = with lib.types; listOf str;
+        description = ''
+          A list of paths to files in OpenSSH's `authorized_keys` format, containing
+          the keys that will be trusted by the `pam_ssh_agent_auth` module.
+
+          The following patterns are expanded when interpreting the path:
+          - `%f` and `%H` respectively expand to the fully-qualified and short hostname ;
+          - `%u` expands to the username ;
+          - `~` or `%h` expands to the user's home directory.
+
+          ::: {.note}
+          Specifying user-writeable files here result in an insecure configuration:  a malicious process
+          can then edit such an authorized_keys file and bypass the ssh-agent-based authentication.
+
+          See [issue #31611](https://github.com/NixOS/nixpkgs/issues/31611)
+          :::
+        '';
+        default = [ "/etc/ssh/authorized_keys.d/%u" ];
+      };
+    };
+
+    security.pam.rssh = {
+      enable = lib.mkEnableOption "authenticating using a signature performed by the ssh-agent";
+
+      settings = lib.mkOption {
+        type = lib.types.submodule {
+          freeformType = moduleSettingsType;
+          options = {
+            auth_key_file = lib.mkOption {
+              type = with lib.types; nullOr nonEmptyStr;
+              description = ''
+                Path to file with trusted public keys in OpenSSH's `authorized_keys` format. The following
+                variables are expanded to the respective PAM items:
+
+                - `service`: `PAM_SERVICE`, the service name,
+                - `user`: `PAM_USER`, the username of the entity under whose identity service will be given,
+                - `tty`: `PAM_TTY`, the terminal name,
+                - `rhost`: `PAM_RHOST`, the requesting hostname, and
+                - `ruser`: `PAM_RUSER`, the requesting entity.
+
+                These PAM items are explained in {manpage}`pam_get_item(3)`.
+
+                Variables may be specified as `$var`, `''${var}` or `''${var:defaultValue}`.
+
+                ::: {.note}
+                Specifying user-writeable files here results in an insecure configuration: a malicious process
+                can then edit such an `authorized_keys` file and bypass the ssh-agent-based authentication.
+
+                This option is ignored if {option}`security.pam.rssh.settings.authorized_keys_command` is set.
+
+                If both this option and {option}`security.pam.rssh.settings.authorized_keys_command` are unset,
+                the keys will be read from `''${HOME}/.ssh/authorized_keys`, which should be considered
+                insecure.
+              '';
+              default = "/etc/ssh/authorized_keys.d/$ruser";
+            };
+          };
+        };
+
+        default = { };
+        description = ''
+          Options to pass to the pam_rssh module. Refer to
+          <https://github.com/z4yx/pam_rssh/blob/main/README.md#optional-arguments>
+          for supported values.
+
+          ${moduleSettingsDescription}
+        '';
+      };
+    };
+
+    security.pam.enableOTPW = lib.mkEnableOption "the OTPW (one-time password) PAM module";
+
+    security.pam.dp9ik = {
+      enable = lib.mkEnableOption ''
+        the dp9ik pam module provided by tlsclient.
+
+        If set, users can be authenticated against the 9front
+        authentication server given in {option}`security.pam.dp9ik.authserver`
+      '';
+      control = lib.mkOption {
+        default = "sufficient";
+        type = lib.types.str;
+        description = ''
+          This option sets the pam "control" used for this module.
+        '';
+      };
+      authserver = lib.mkOption {
+        default = null;
+        type = with lib.types; nullOr str;
+        description = ''
+          This controls the hostname for the 9front authentication server
+          that users will be authenticated against.
+        '';
+      };
+    };
+
+    security.pam.krb5 = {
+      enable = lib.mkOption {
+        default = config.security.krb5.enable;
+        defaultText = lib.literalExpression "config.security.krb5.enable";
+        type = lib.types.bool;
+        description = ''
+          Enables Kerberos PAM modules (`pam-krb5`,
+          `pam-ccreds`).
+
+          If set, users can authenticate with their Kerberos password.
+          This requires a valid Kerberos configuration
+          (`security.krb5.enable` should be set to `true`).
+
+          Note that the Kerberos PAM modules are not necessary when using SSS
+          to handle Kerberos authentication.
+        '';
+      };
+    };
+
+    security.pam.p11 = {
+      enable = lib.mkOption {
+        default = false;
+        type = lib.types.bool;
+        description = ''
+          Enables P11 PAM (`pam_p11`) module.
+
+          If set, users can log in with SSH keys and PKCS#11 tokens.
+
+          More information can be found [here](https://github.com/OpenSC/pam_p11).
+        '';
+      };
+
+      control = lib.mkOption {
+        default = "sufficient";
+        type = lib.types.enum [
+          "required"
+          "requisite"
+          "sufficient"
+          "optional"
+        ];
+        description = ''
+          This option sets pam "control".
+          If you want to have multi factor authentication, use "required".
+          If you want to use the PKCS#11 device instead of the regular password,
+          use "sufficient".
+
+          Read
+          {manpage}`pam.conf(5)`
+          for better understanding of this option.
+        '';
+      };
+    };
+
+    security.pam.u2f = {
+      enable = lib.mkOption {
+        default = false;
+        type = lib.types.bool;
+        description = ''
+          Enables U2F PAM (`pam-u2f`) module.
+
+          If set, users listed in
+          {file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or
+          {file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is
+          not set) are able to log in with the associated U2F key. The path can
+          be changed using {option}`security.pam.u2f.authFile` option.
+
+          File format is:
+          ```
+          <username1>:<KeyHandle1>,<UserKey1>,<CoseType1>,<Options1>:<KeyHandle2>,<UserKey2>,<CoseType2>,<Options2>:...
+          <username2>:<KeyHandle1>,<UserKey1>,<CoseType1>,<Options1>:<KeyHandle2>,<UserKey2>,<CoseType2>,<Options2>:...
+          ```
+          This file can be generated using {command}`pamu2fcfg` command.
+
+          More information can be found [here](https://developers.yubico.com/pam-u2f/).
+        '';
+      };
+
+      control = lib.mkOption {
+        default = "sufficient";
+        type = lib.types.enum [
+          "required"
+          "requisite"
+          "sufficient"
+          "optional"
+        ];
+        description = ''
+          This option sets pam "control".
+          If you want to have multi factor authentication, use "required".
+          If you want to use U2F device instead of regular password, use "sufficient".
+
+          Read
+          {manpage}`pam.conf(5)`
+          for better understanding of this option.
+        '';
+      };
+
+      settings = lib.mkOption {
+        type = lib.types.submodule {
+          freeformType = moduleSettingsType;
+
+          options = {
+            authfile = lib.mkOption {
+              default = null;
+              type = with lib.types; nullOr path;
+              description = ''
+                By default `pam-u2f` module reads the keys from
+                {file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or
+                {file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is
+                not set).
+
+                If you want to change auth file locations or centralize database (for
+                example use {file}`/etc/u2f-mappings`) you can set this
+                option.
+
+                File format is:
+                `username:first_keyHandle,first_public_key: second_keyHandle,second_public_key`
+                This file can be generated using {command}`pamu2fcfg` command.
+
+                More information can be found [here](https://developers.yubico.com/pam-u2f/).
+              '';
+            };
+
+            appid = lib.mkOption {
+              default = null;
+              type = with lib.types; nullOr str;
+              description = ''
+                By default `pam-u2f` module sets the application
+                ID to `pam://$HOSTNAME`.
+
+                When using {command}`pamu2fcfg`, you can specify your
+                application ID with the `-i` flag.
+
+                More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html)
+              '';
+            };
+
+            origin = lib.mkOption {
+              default = null;
+              type = with lib.types; nullOr str;
+              description = ''
+                By default `pam-u2f` module sets the origin
+                to `pam://$HOSTNAME`.
+                Setting origin to an host independent value will allow you to
+                reuse credentials across machines
+
+                When using {command}`pamu2fcfg`, you can specify your
+                application ID with the `-o` flag.
+
+                More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html)
+              '';
+            };
+
+            debug = lib.mkOption {
+              default = false;
+              type = lib.types.bool;
+              description = ''
+                Debug output to stderr.
+              '';
+            };
+
+            interactive = lib.mkOption {
+              default = false;
+              type = lib.types.bool;
+              description = ''
+                Set to prompt a message and wait before testing the presence of a U2F device.
+                Recommended if your device doesn’t have a tactile trigger.
+              '';
+            };
+
+            cue = lib.mkOption {
+              default = false;
+              type = lib.types.bool;
+              description = ''
+                By default `pam-u2f` module does not inform user
+                that he needs to use the u2f device, it just waits without a prompt.
+
+                If you set this option to `true`,
+                `cue` option is added to `pam-u2f`
+                module and reminder message will be displayed.
+              '';
+            };
+          };
+        };
+        default = { };
+        example = {
+          authfile = "/etc/u2f_keys";
+          authpending_file = "";
+          userpresence = 0;
+          pinverification = 1;
+        };
+        description = ''
+          Options to pass to the PAM module.
+
+          ${moduleSettingsDescription}
+        '';
+      };
+    };
+
+    security.pam.ussh = {
+      enable = lib.mkOption {
+        default = false;
+        type = lib.types.bool;
+        description = ''
+          Enables Uber's USSH PAM (`pam-ussh`) module.
+
+          This is similar to `pam-ssh-agent`, except that
+          the presence of a CA-signed SSH key with a valid principal is checked
+          instead.
+
+          Note that this module must both be enabled using this option and on a
+          per-PAM-service level as well (using `usshAuth`).
+
+          More information can be found [here](https://github.com/uber/pam-ussh).
+        '';
+      };
+
+      caFile = lib.mkOption {
+        default = null;
+        type = with lib.types; nullOr path;
+        description = ''
+          By default `pam-ussh` reads the trusted user CA keys
+          from {file}`/etc/ssh/trusted_user_ca`.
+
+          This should be set the same as your `TrustedUserCAKeys`
+          option for sshd.
+        '';
+      };
+
+      authorizedPrincipals = lib.mkOption {
+        default = null;
+        type = with lib.types; nullOr commas;
+        description = ''
+          Comma-separated list of authorized principals to permit; if the user
+          presents a certificate with one of these principals, then they will be
+          authorized.
+
+          Note that `pam-ussh` also requires that the certificate
+          contain a principal matching the user's username. The principals from
+          this list are in addition to those principals.
+
+          Mutually exclusive with `authorizedPrincipalsFile`.
+        '';
+      };
+
+      authorizedPrincipalsFile = lib.mkOption {
+        default = null;
+        type = with lib.types; nullOr path;
+        description = ''
+          Path to a list of principals; if the user presents a certificate with
+          one of these principals, then they will be authorized.
+
+          Note that `pam-ussh` also requires that the certificate
+          contain a principal matching the user's username. The principals from
+          this file are in addition to those principals.
+
+          Mutually exclusive with `authorizedPrincipals`.
+        '';
+      };
+
+      group = lib.mkOption {
+        default = null;
+        type = with lib.types; nullOr str;
+        description = ''
+          If set, then the authenticating user must be a member of this group
+          to use this module.
+        '';
+      };
+
+      control = lib.mkOption {
+        default = "sufficient";
+        type = lib.types.enum [
+          "required"
+          "requisite"
+          "sufficient"
+          "optional"
+        ];
+        description = ''
+          This option sets pam "control".
+          If you want to have multi factor authentication, use "required".
+          If you want to use the SSH certificate instead of the regular password,
+          use "sufficient".
+
+          Read
+          {manpage}`pam.conf(5)`
+          for better understanding of this option.
+        '';
+      };
+    };
+
+    security.pam.yubico = {
+      enable = lib.mkOption {
+        default = false;
+        type = lib.types.bool;
+        description = ''
+          Enables Yubico PAM (`yubico-pam`) module.
+
+          If set, users listed in
+          {file}`~/.yubico/authorized_yubikeys`
+          are able to log in with the associated Yubikey tokens.
+
+          The file must have only one line:
+          `username:yubikey_token_id1:yubikey_token_id2`
+          More information can be found [here](https://developers.yubico.com/yubico-pam/).
+        '';
+      };
+      control = lib.mkOption {
+        default = "sufficient";
+        type = lib.types.enum [
+          "required"
+          "requisite"
+          "sufficient"
+          "optional"
+        ];
+        description = ''
+          This option sets pam "control".
+          If you want to have multi factor authentication, use "required".
+          If you want to use Yubikey instead of regular password, use "sufficient".
+
+          Read
+          {manpage}`pam.conf(5)`
+          for better understanding of this option.
+        '';
+      };
+      id = lib.mkOption {
+        example = "42";
+        type = lib.types.str;
+        description = "client id";
+      };
+
+      debug = lib.mkOption {
+        default = false;
+        type = lib.types.bool;
+        description = ''
+          Debug output to stderr.
+        '';
+      };
+      mode = lib.mkOption {
+        default = "client";
+        type = lib.types.enum [
+          "client"
+          "challenge-response"
+        ];
+        description = ''
+          Mode of operation.
+
+          Use "client" for online validation with a YubiKey validation service such as
+          the YubiCloud.
+
+          Use "challenge-response" for offline validation using YubiKeys with HMAC-SHA-1
+          Challenge-Response configurations. See the man-page {manpage}`ykpamcfg(1)` for further
+          details on how to configure offline Challenge-Response validation.
+
+          More information can be found [here](https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html).
+        '';
+      };
+      challengeResponsePath = lib.mkOption {
+        default = null;
+        type = lib.types.nullOr lib.types.path;
+        description = ''
+          If not null, set the path used by yubico pam module where the challenge expected response is stored.
+
+          More information can be found [here](https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html).
+        '';
+      };
+    };
+
+    security.pam.zfs = {
+      enable = lib.mkOption {
+        default = false;
+        type = lib.types.bool;
+        description = ''
+          Enable unlocking and mounting of encrypted ZFS home dataset at login.
+        '';
+      };
+
+      homes = lib.mkOption {
+        example = "rpool/home";
+        default = "rpool/home";
+        type = lib.types.str;
+        description = ''
+          Prefix of home datasets. This value will be concatenated with
+          `"/" + <username>` in order to determine the home dataset to unlock.
+        '';
+      };
+
+      noUnmount = lib.mkOption {
+        default = false;
+        type = lib.types.bool;
+        description = ''
+          Do not unmount home dataset on logout.
+        '';
+      };
+    };
+
+    security.pam.enableEcryptfs = lib.mkEnableOption "eCryptfs PAM module (mounting ecryptfs home directory on login)";
+    security.pam.enableFscrypt = lib.mkEnableOption ''
+      fscrypt, to automatically unlock directories with the user's login password.
+
+      This also enables a service at security.pam.services.fscrypt which is used by
+      fscrypt to verify the user's password when setting up a new protector. If you
+      use something other than pam_unix to verify user passwords, please remember to
+      adjust this PAM service
+    '';
+
+    users.motd = lib.mkOption {
+      default = "";
+      example = "Today is Sweetmorn, the 4th day of The Aftermath in the YOLD 3178.";
+      type = lib.types.lines;
+      description = "Message of the day shown to users when they log in.";
+    };
+
+    users.motdFile = lib.mkOption {
+      default = null;
+      example = "/etc/motd";
+      type = lib.types.nullOr lib.types.path;
+      description = "A file containing the message of the day shown to users when they log in.";
+    };
+  };
+
+  ###### implementation
+
+  config = {
+    assertions = [
+      {
+        assertion = config.users.motd == "" || config.users.motdFile == null;
+        message = ''
+          Only one of users.motd and users.motdFile can be set.
+        '';
+      }
+      {
+        assertion = config.security.pam.zfs.enable -> config.boot.zfs.enabled;
+        message = ''
+          `security.pam.zfs.enable` requires enabling ZFS (`boot.zfs.enabled`).
+        '';
+      }
+      {
+        assertion = with config.security.pam.sshAgentAuth; enable -> authorizedKeysFiles != [ ];
+        message = ''
+          `security.pam.enableSSHAgentAuth` requires `services.openssh.authorizedKeysFiles` to be a non-empty list.
+          Did you forget to set `services.openssh.enable` ?
+        '';
+      }
+      {
+        assertion =
+          with config.security.pam.rssh;
+          enable
+          -> (settings.auth_key_file or null != null || settings.authorized_keys_command or null != null);
+        message = ''
+          security.pam.rssh.enable requires either security.pam.rssh.settings.auth_key_file or
+          security.pam.rssh.settings.authorized_keys_command to be set.
+        '';
+      }
+    ];
+
+    warnings =
+      lib.optional
+        (
+          with config.security.pam.sshAgentAuth;
+          enable && lib.any (s: lib.hasPrefix "%h" s || lib.hasPrefix "~" s) authorizedKeysFiles
+        )
+        ''
+          security.pam.sshAgentAuth.authorizedKeysFiles contains files in the user's home directory.
+
+          Specifying user-writeable files there result in an insecure configuration:
+          a malicious process can then edit such an authorized_keys file and bypass the ssh-agent-based authentication.
+          See https://github.com/NixOS/nixpkgs/issues/31611
+        ''
+      ++
+        lib.optional
+          (
+            with config.security.pam.rssh;
+            enable && settings.auth_key_file or null != null && settings.authorized_keys_command or null != null
+          )
+          ''
+            security.pam.rssh.settings.auth_key_file will be ignored as
+            security.pam.rssh.settings.authorized_keys_command has been specified.
+            Explictly set the former to null to silence this warning.
+          '';
+
+    environment.systemPackages =
+      # Include the PAM modules in the system path mostly for the manpages.
+      [ package ]
+      ++ lib.optional config.users.ldap.enable pam_ldap
+      ++ lib.optional config.services.kanidm.enablePam config.services.kanidm.package
+      ++ lib.optional config.services.sssd.enable pkgs.sssd
+      ++ lib.optionals config.security.pam.krb5.enable [
+        pam_krb5
+        pam_ccreds
+      ]
+      ++ lib.optionals config.security.pam.enableOTPW [ pkgs.otpw ]
+      ++ lib.optionals config.security.pam.oath.enable [ pkgs.oath-toolkit ]
+      ++ lib.optionals config.security.pam.p11.enable [ pkgs.pam_p11 ]
+      ++ lib.optionals config.security.pam.enableFscrypt [ pkgs.fscrypt-experimental ]
+      ++ lib.optionals config.security.pam.u2f.enable [ pkgs.pam_u2f ];
+
+    boot.supportedFilesystems = lib.optionals config.security.pam.enableEcryptfs [ "ecryptfs" ];
+
+    security.wrappers = {
+      unix_chkpwd = {
+        setuid = true;
+        owner = "root";
+        group = "root";
+        source = "${package}/bin/unix_chkpwd";
+      };
+    };
+
+    environment.etc = lib.mapAttrs' makePAMService enabledServices;
+
+    security.pam.services = {
+      other.text = ''
+        auth     required pam_warn.so
+        auth     required pam_deny.so
+        account  required pam_warn.so
+        account  required pam_deny.so
+        password required pam_warn.so
+        password required pam_deny.so
+        session  required pam_warn.so
+        session  required pam_deny.so
+      '';
+
+      # Most of these should be moved to specific modules.
+      i3lock.enable = lib.mkDefault config.programs.i3lock.enable;
+      i3lock-color.enable = lib.mkDefault config.programs.i3lock.enable;
+      vlock.enable = lib.mkDefault config.console.enable;
+      xlock.enable = lib.mkDefault config.services.xserver.enable;
+      xscreensaver.enable = lib.mkDefault config.services.xscreensaver.enable;
+
+      runuser = {
+        rootOK = true;
+        unixAuth = false;
+        setEnvironment = false;
+      };
+
+      /*
+        FIXME: should runuser -l start a systemd session? Currently
+        it complains "Cannot create session: Already running in a
+        session".
+      */
+      runuser-l = {
+        rootOK = true;
+        unixAuth = false;
+      };
+    }
+    // lib.optionalAttrs (config.security.pam.enableFscrypt) {
+      # Allow fscrypt to verify login passphrase
+      fscrypt = { };
+    };
+
+    security.apparmor.includes."abstractions/pam" =
+      lib.concatMapStrings (name: "r ${config.environment.etc."pam.d/${name}".source},\n") (
+        lib.attrNames enabledServices
+      )
+      + (
+        with lib;
+        pipe enabledServices [
+          lib.attrValues
+          (catAttrs "rules")
+          (lib.concatMap lib.attrValues)
+          (lib.concatMap lib.attrValues)
+          (lib.filter (rule: rule.enable))
+          (lib.catAttrs "modulePath")
+          (map (
+            modulePath:
+            lib.throwIfNot (lib.hasPrefix "/" modulePath)
+              ''non-absolute PAM modulePath "${modulePath}" is unsupported by apparmor''
+              modulePath
+          ))
+          lib.unique
+          (map (module: "mr ${module},"))
+          concatLines
+        ]
+      );
+
+    security.sudo.extraConfig = optionalSudoConfigForSSHAgentAuth;
+    security.sudo-rs.extraConfig = optionalSudoConfigForSSHAgentAuth;
+  };
+}
diff --git a/resources/patches/gomuks-web-css.patch b/resources/patches/gomuks-web-css.patch
@@ -0,0 +1,117 @@
+From 34f456f165f3f9726ff8fccce0449959a3a111ca Mon Sep 17 00:00:00 2001
+From: "Katja Ramona Sophie Kwast (zaphyra)" <git@zaphyra.eu>
+Date: Sun, 24 Aug 2025 15:12:00 +0200
+Subject: [PATCH] web/css: add some stuff
+
+---
+ web/public/manifest.json |  2 +-
+ web/src/index.css        | 85 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 86 insertions(+), 1 deletion(-)
+
+diff --git a/web/public/manifest.json b/web/public/manifest.json
+index 1fbf843..7caa2fa 100644
+--- a/web/public/manifest.json
++++ b/web/public/manifest.json
+@@ -28,5 +28,5 @@
+ 	}],
+ 	"start_url": ".",
+ 	"display": "standalone",
+-	"theme_color": "#00c853"
++	"theme_color": "#262626"
+ }
+diff --git a/web/src/index.css b/web/src/index.css
+index 08d78d4..8d4ecda 100644
+--- a/web/src/index.css
++++ b/web/src/index.css
+@@ -293,3 +293,88 @@ a {
+ .hidden {
+ 	display: none !important;
+ }
++
++
++
++div.room-view {
++    grid-template: "header" 3.5rem "messageview" 1fr "autocomplete" 0 "typing" auto "input" auto / 1fr;
++}
++
++div.message-composer {
++    margin: 0;
++    border-radius: 0;
++}
++
++div.typing-notifications {
++    min-block-size: 1.6rem;
++    margin: 0;
++    padding-block: .25rem;
++    padding-inline: 1.6rem;
++    background-color: var(--background-color);
++
++    width: 100%;
++
++    box-shadow: 0 0 0.5rem var(--background-color);
++
++    bottom: 0;
++    position: absolute;
++
++    &.empty {
++        display: none;
++    }
++}
++
++@media (min-width: 721px) {
++  button.back {
++    display: none;
++  }
++}
++
++:root {
++  overscroll-behavior: none;
++
++  --background-color: #262626;
++  --border-color: #404040;
++  --space-list-background-overlay: #1A1A1A;
++  --room-list-background-overlay: #1A1A1A;
++  --timeline-hover-bg-color: #333;
++  --timeline-vertical-padding: .25rem;
++  --composer-background-color: #333;
++}
++
++img.avatar {
++  border-radius: 20%;
++}
++
++div.room-list-wrapper {
++  grid-template-columns: 4rem 1fr;
++}
++
++div.room-search-wrapper {
++  height: unset;
++}
++
++div.room-list-wrapper,
++div.space-bar {
++  border-right: 1px solid var(--border-color);
++}
++
++div.room-header,
++div.room-search-wrapper {
++  border-bottom: 1px solid var(--border-color);
++}
++
++div.space-entry,
++div.message-composer {
++  border: 1px solid var(--border-color);
++  padding: .35rem;
++}
++
++div.room-entry {
++  width: unset;
++  padding: .35rem;
++}
++
++div.space-entry {
++  margin: 0.8rem !important;
++}
+-- 
+2.50.1
+
diff --git a/resources/pgp/2C754046341AB6A0C3F0EF6F23100DF8D68F4FA6.asc b/resources/pgp/2C754046341AB6A0C3F0EF6F23100DF8D68F4FA6.asc
@@ -7,14 +7,16 @@ CAsCBBYCAwECHgcCF4AACgkQIxAN+NaPT6aGCQD/SlHBVYVKTNQLKWeObl3RGjU7
 Hz+6h6aePUKIddWD5o4A/jVJbD9GStaO7gPJN1cOn5RaqxY88mUpf5NlS9Nv3BQH
 iHkEExYKACEWIQQyHvpSzxVen9ZGJ54PsMoRmF619gUCZ8Mq9gMFAXgACgkQD7DK
 EZhetfbPnwEAnJixSzLgeck6BOCNXliK+uUbwDNnIl/l/4fkFTRJIcMA/jQwNdoO
-4nlI6UbqbgiiL3/9cZ9RQpv3EAomg7+XEIANuDMEZ8MdghYJKwYBBAHaRw8BAQdA
-FXEZO+2qHFmAQ3thQrl6QPcKyDeMPur15u+iSIXfq76IfgQYFgoAJhYhBCx1QEY0
-Gragw/DvbyMQDfjWj0+mBQJnwx2CAhsgBQkB4TOAAAoJECMQDfjWj0+m3cEA/2g7
-pua6XuyAABZG7U0sCJ/hekFqhGaydk3XFegXTBu/APkBAgdx8A773tsXrB5GDbDm
-4UqtOsIy6XhLju6mrStAAbg4BGfDHT4SCisGAQQBl1UBBQEBB0DHU/n//sDKHdEN
-ySqZMTSK6zcOqADjA+CTgAq+mshzRwMBCAeIfgQYFgoAJhYhBCx1QEY0Gragw/Dv
-byMQDfjWj0+mBQJnwx0+AhsMBQkB4TOAAAoJECMQDfjWj0+muYwBAIneozvzDDu6
-Zf+23SKDhISynsGo2iut4GthFXmUXb3MAQDTwRE/5M8YufAfWcPSCo4RvSegDPW5
-ZLs/U5IQS4TLBw==
-=2IoC
+4nlI6UbqbgiiL3/9cZ9RQpv3EAomg7+XEIANiHkEExYKACEWIQS/5jhsjWa81Nrh
+T8iV8P581+agIgUCaFRysAMFAXgACgkQlfD+fNfmoCIYngD/fk1UzgH9rp+o8WGU
+AlVh4qVT9zw9UDMS3J11WOfI3Z0A/3nJFjV+0+Nzb26y4VOv9LRx/zVAkI7dopy0
+gumVs+APuDMEZ8MdghYJKwYBBAHaRw8BAQdAFXEZO+2qHFmAQ3thQrl6QPcKyDeM
+Pur15u+iSIXfq76IfgQYFgoAJhYhBCx1QEY0Gragw/DvbyMQDfjWj0+mBQJnwx2C
+AhsgBQkB4TOAAAoJECMQDfjWj0+m3cEA/2g7pua6XuyAABZG7U0sCJ/hekFqhGay
+dk3XFegXTBu/APkBAgdx8A773tsXrB5GDbDm4UqtOsIy6XhLju6mrStAAbg4BGfD
+HT4SCisGAQQBl1UBBQEBB0DHU/n//sDKHdENySqZMTSK6zcOqADjA+CTgAq+mshz
+RwMBCAeIfgQYFgoAJhYhBCx1QEY0Gragw/DvbyMQDfjWj0+mBQJnwx0+AhsMBQkB
+4TOAAAoJECMQDfjWj0+muYwBAIneozvzDDu6Zf+23SKDhISynsGo2iut4GthFXmU
+Xb3MAQDTwRE/5M8YufAfWcPSCo4RvSegDPW5ZLs/U5IQS4TLBw==
+=ItM/
 -----END PGP PUBLIC KEY BLOCK-----
diff --git a/resources/pgp/BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022.asc b/resources/pgp/BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022.asc
@@ -37,20 +37,23 @@ kFMEwvsFAmhUPEADBQF4AAoJEPcBeJBTBML7Tk0A+gMC0OEOEYsavaxTridpEKQN
 gvznDp9xhfb2j40bh8uNAP4yT2m8yCh/nyYiELU3hCGeLbRJK4/cDKt3ohrKQ5//
 DYh5BBMWCgAhFiEELHVARjQatqDD8O9vIxAN+NaPT6YFAmhUT+UDBQE8AAoJECMQ
 DfjWj0+mLIMA/jKx22mOz6emt59J6YiLU2SakfQCnrYO0YXBCwvqVB1gAP9CoCXT
-WnUfvPIA87RFgXXnqhEw0nTBjWhiz6x8mcTVBbgzBGhMKC4WCSsGAQQB2kcPAQEH
-QAaCkonBYFQwH3ZxCRCP8+IrGmHlRWvZPg6urGlzoo2aiPUEGBYKACYWIQS/5jhs
-jWa81NrhT8iV8P581+agIgUCaEwoLgIbAgUJAQjaAgCBCRCV8P581+agInYgBBkW
-CgAdFiEE2M6RQxkbFw2P5Jv3r3Yw7RAYt6gFAmhMKC4ACgkQr3Yw7RAYt6g+sQEA
-04Iixee+ykv5gATzD9sCK+w6084lsWtqXLqzWPVL+eEBAN5OrdGjiTnj+Ru8hrpa
-tBQoJOduiIfXyqLVGX/M4P4GnzcA/RYSmzmDYkCkysYK0p1zkpDiz3/W4qx6c/Yq
-hTfE/0QRAP9PE5DZ9aFgO2YQxII+N92T6hu9dWa0jCUpYL/5FOIzALg4BGhMKHIS
-CisGAQQBl1UBBQEBB0CnqZulXHKcRcuiD9Sz8TAbl5SbVH1JQ/NB4rRvaCnNdAMB
-CAeIfgQYFgoAJhYhBL/mOGyNZrzU2uFPyJXw/nzX5qAiBQJoTChyAhsMBQkBCNm+
-AAoJEJXw/nzX5qAimOwBALFqQtERMLMvakHaRCVFmmf0eN1/quTr7NNApedJVmVy
-AP4+u/CwemcER9rWBDKKN39eqEzMVfHJ3Ph8d8tn5X7iBbgzBGhMKH8WCSsGAQQB
-2kcPAQEHQLTOkSPzd70xNTgPOylix/lb5JKYdt+URoewlmGRP3oZiH4EGBYKACYW
-IQS/5jhsjWa81NrhT8iV8P581+agIgUCaEwofwIbIAUJAQjZsQAKCRCV8P581+ag
-ItUgAQC2RZ/G2BqXCBaNr1W0pxWpxUzQ0v66jcB0+n8/zI14GQD+KH8GIgVPuW/X
-hMDDcxugy25oFRT66HUkGv09sy73Ngg=
-=i3Nq
+WnUfvPIA87RFgXXnqhEw0nTBjWhiz6x8mcTVBYh5BBMWCgAhFiEEqdNj6iEbqcsD
+0bdzqlniVaOJYHMFAmhbEIUDBQF4AAoJEKpZ4lWjiWBzgSIBAP+1Y32MnWQrgPJW
+iYFyvFWApBI4c9/Ul/ZFOrr9+bxhAP94Tj2P8eQ/pTa0hYUUL/pTKWYrDfVCMWiJ
+R+TYwJRjArgzBGhMKC4WCSsGAQQB2kcPAQEHQAaCkonBYFQwH3ZxCRCP8+IrGmHl
+RWvZPg6urGlzoo2aiPUEGBYKACYWIQS/5jhsjWa81NrhT8iV8P581+agIgUCaEwo
+LgIbAgUJAQjaAgCBCRCV8P581+agInYgBBkWCgAdFiEE2M6RQxkbFw2P5Jv3r3Yw
+7RAYt6gFAmhMKC4ACgkQr3Yw7RAYt6g+sQEA04Iixee+ykv5gATzD9sCK+w6084l
+sWtqXLqzWPVL+eEBAN5OrdGjiTnj+Ru8hrpatBQoJOduiIfXyqLVGX/M4P4GnzcA
+/RYSmzmDYkCkysYK0p1zkpDiz3/W4qx6c/YqhTfE/0QRAP9PE5DZ9aFgO2YQxII+
+N92T6hu9dWa0jCUpYL/5FOIzALg4BGhMKHISCisGAQQBl1UBBQEBB0CnqZulXHKc
+RcuiD9Sz8TAbl5SbVH1JQ/NB4rRvaCnNdAMBCAeIfgQYFgoAJhYhBL/mOGyNZrzU
+2uFPyJXw/nzX5qAiBQJoTChyAhsMBQkBCNm+AAoJEJXw/nzX5qAimOwBALFqQtER
+MLMvakHaRCVFmmf0eN1/quTr7NNApedJVmVyAP4+u/CwemcER9rWBDKKN39eqEzM
+VfHJ3Ph8d8tn5X7iBbgzBGhMKH8WCSsGAQQB2kcPAQEHQLTOkSPzd70xNTgPOyli
+x/lb5JKYdt+URoewlmGRP3oZiH4EGBYKACYWIQS/5jhsjWa81NrhT8iV8P581+ag
+IgUCaEwofwIbIAUJAQjZsQAKCRCV8P581+agItUgAQC2RZ/G2BqXCBaNr1W0pxWp
+xUzQ0v66jcB0+n8/zI14GQD+KH8GIgVPuW/XhMDDcxugy25oFRT66HUkGv09sy73
+Ngg=
+=eaxV
 -----END PGP PUBLIC KEY BLOCK-----
diff --git a/resources/shaders/background1.frag b/resources/shaders/background1.frag
@@ -0,0 +1,78 @@
+/*** Uses noise / fbm apparatus from Clouds by iq on shadertoy ***/
+
+float pi = 3.14159;
+
+
+mat3 m = mat3( 0.0,  0.8,  0.60,
+              -0.80,  0.36, -0.48,
+              -0.60, -0.48,  0.64 );
+
+float hash( float n )
+{
+    return fract(sin(n)*43758.5453);
+}
+
+float noise( in vec3 x )
+{
+    vec3 p = floor(x);
+    vec3 f = fract(x);
+
+    f = f*f*(3.0-2.0*f);
+    float n = p.x + p.y*57.0 + 113.0*p.z;
+
+    float res = mix(mix(mix( hash(n+  0.0), hash(n+  1.0),f.x),
+                        mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y),
+                    mix(mix( hash(n+113.0), hash(n+114.0),f.x),
+                        mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
+    return 1.0 - sqrt(res);
+}
+
+float fbm( vec3 p )
+{
+    float f;
+    f  = 0.5000*noise( p ); p = m*p*2.02;
+    f += 0.2500*noise( p ); p = m*p*2.0130;
+    f += 0.1250*noise( p ); p = m*p*2.0370;
+	// enable smallest component for more wiggliness
+	// f += 0.0625*noise( p );
+	// f /= 0.9375
+    f /= 0.875;
+    return f;
+}
+
+float nat(in vec2 q, in float z, in float mx) {
+   return mx * noise(vec3(q, z)) + (1.0 - mx) * fbm(vec3(q, z));
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
+  vec2 mouse = vec2(1.0 - iMouse.x / iResolution.x, 1.0 - iMouse.y / iResolution.y);
+  vec3 col = vec3 (0., 0., 0.);
+  
+  float s = 1.0 / ((1.0 + mouse.y) * 45.0);
+  float fbmz = 1.0 + 0.01 * iTime;
+  vec2 p = (fragCoord.xy * s);
+
+  float as = (4.0 * (1.0 - mouse.y) + (3.0 * (1.0 - mouse.x))) + 7.5;
+  float pdir = nat(p, fbmz, mouse.x) * 2.0 * pi * as;
+  float d = as * 1.0 / length(iResolution);
+  vec2 dp = vec2(d*sin(pdir), d * cos(pdir));
+  vec2 q = p + dp;
+  vec2 q2 = p - dp;
+  float qdir = nat(q, fbmz, mouse.x) * 2.0 * pi * as;
+  pdir = nat(q2, fbmz, mouse.x) * 2.0 * pi * as;
+  vec2 c = (q2 + q) / 2.0;
+  float pql = length(q - q2);
+
+  float mdir = (pdir + qdir)/2.0;
+  float ddir = mod((qdir - pdir)/2.0, pi * 2.0);
+  float tdd = tan(ddir);
+  vec2 co = vec2(pql * sin(mdir) / tdd, pql * cos(mdir) / tdd);
+  float ro = length(q2 - c + co);
+
+  float rf = .25 + (0.2 * (1.0 - mouse.x));
+  if (ro < rf) {
+    col += normalize(vec3(cos(ro/ddir),  2.5 - sin((ro/rf) * pi/2.0), 0.9 - ro/rf/ddir));
+    col *= (1.0 - (ro/rf));
+  } 
+  fragColor = vec4(col, 1.0);
+}+
\ No newline at end of file
diff --git a/resources/void/programs/waybar/style.css b/resources/void/programs/waybar/style.css
@@ -0,0 +1,205 @@
+* {
+  border: none;
+  border-radius: 0;
+  /* font-family: Fira Code; */
+  min-height: 20px;
+  padding: 5px;
+}
+window#waybar {
+  background: transparent;
+}
+window#waybar.hidden {
+  opacity: 0.2;
+}
+#workspaces {
+  margin-right: 8px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#workspaces button {
+  transition: none;
+  color: @base04;
+  background: transparent;
+  padding: 0px;
+  font-size: 18px;
+}
+#workspaces button.persistent {
+  color: @base04;
+  font-size: 12px;
+}
+/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
+#workspaces button:hover {
+  transition: none;
+  box-shadow: inherit;
+  text-shadow: inherit;
+  border-radius: inherit;
+  color: @base02;
+  background: #7c818c;
+}
+#workspaces button.focused {
+  color: @base05;
+}
+#idle_inhibitor {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#idle_inhibitor.activated {
+  color: @base00;
+  background: @base0E;
+}
+#keyboard-state {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 8px;
+  border-radius: 10px 10px 10px 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#keyboard-state label.locked {
+  color: @base00;
+  background: @base0D;
+}
+#mode {
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#network {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#clock {
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px 10px 10px 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#wireplumber {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#wireplumber.muted {
+  background-color: @base03;
+  color: @base08;
+}
+#cpu {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#memory {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#temperature {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#temperature.critical {
+  background-color: @base08;
+}
+#backlight {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#battery {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#battery.charging {
+  color: @base05;
+  background-color: @base0B;
+}
+#battery.warning:not(.charging) {
+  background-color: @base09;
+  color: @base00;
+}
+#battery.critical:not(.charging) {
+  background-color: @base08;
+  color: @base00;
+  animation-name: blink;
+  animation-duration: 0.5s;
+  animation-timing-function: linear;
+  animation-iteration-count: infinite;
+  animation-direction: alternate;
+}
+#tray {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#power-profiles-daemon {
+  margin-right: 8px;
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+#custom-power {
+  padding-left: 16px;
+  padding-right: 16px;
+  border-radius: 10px;
+  transition: none;
+  color: @base05;
+  background: @base02;
+}
+@keyframes blink {
+  to {
+    background-color: @base05;
+    color: #000000;
+  }
+}
+
diff --git a/secrets/common.yaml b/secrets/common.yaml
@@ -1,75 +1,94 @@
 voidPassword: ENC[AES256_GCM,data:g9X7iIkETTCTXIc7P7+duqAxrXuxr8RRCBc5WvubM+8ljbQbYh6S/1W2ebhRbb2It+vbq2IDTOEtfep+TghO4KmvLl7VketTPw==,iv:KRhga4XDbK9d1BrWrNnY3NzJX9rf4ynYx8F6I63E7IY=,tag:FTBC0YEexpeHzjvSn1hyFw==,type:str]
-zaphyraPassword: ENC[AES256_GCM,data:rW2g6n71PA6R5+KZ9i4EZ8doC9JGCLMGf+29r+8zvPMgz2ndJ0Hltkq0I12AQ5GILhS2x6lOLTpTjZ4SkG5PM1FRN/3Vi0wrdQ==,iv:weyksZS/MnkZLlM5nScUD4NvX17XnRG0dmut6Lyjqoo=,tag:scrtArW3n69CDaAPxwbQ8Q==,type:str]
+zaphyraPassword: ENC[AES256_GCM,data:PejTikjFR8ilcVEJS9JI5Fh2I5d6qcxgxNg6BmgoDRhBqkEllF8LG96nnh8gpAlrumy2ntsU+q/sVrzE4Q/hpoYVRKIRt4i7Qw==,iv:zc5XnVy9fTfFNdnfiFwM60mz7RDh/3Y3iB22AzwHrZQ=,tag:KrNlWECBrUZ2A731vXCsCg==,type:str]
 resticEnv:
     novus: ENC[AES256_GCM,data:KTTd0UMQiOHrrFIbY9pIJWO9MVIFWs2pvjm4Vo46CE/CrgGfxJur5uYtxHvR94bwaoLXd8RpdlONSRzbShQlH0xE86C/MyRNWiZR5QLyWj6YwzFd+DSdHQD0h0AlRviZY/vFze1EJRPZ0d6XCMJBX+aTizVSxw==,iv:pSfa9Kgpwq/wqn6nOKozgEy2h9C22oVWSCA7X07aW1w=,tag:+aD8wh33mA9hqQ1TKT1m8w==,type:str]
 environments:
     networkManagerProfiles:
         voidPhone: ENC[AES256_GCM,data:7C9QJVQRSrw+P2jCJit3oT+gPxHW9pHx0XFj4uXuAOdR7Xk1cBzOJNiEGaXagycecw9OE+6A+pMuWw==,iv:UHNcKDeVPM3/K2cLEUa7X96dZ+10vTAjXDyNlDRH+8A=,tag:vMyw8f3bYogrgnewZj07ew==,type:str]
         voidHome: ENC[AES256_GCM,data:kxQ7Bn0dULnFQnSR5PozRUK4GUhw3y9ienTyFNwcW1rlZ0d4UpkRRvpG2XehMrEfRaxds0RVboQ8Li3z9Q==,iv:gbB6R0X8Xr+e9/dvSAXuQIIHX3mF9j3H63A+AXXq0hY=,tag:kY/Gs5VSWtwBH2VjDDNYwg==,type:str]
-        zaphyraPhone: ENC[AES256_GCM,data:mghBydVnJ8tuhXBMZKlQIXh06PCQsvcElHyWIya2hLbQlUYyAMD+l8J1Z1tU3RUrSYW3Gd32TdfQpQ==,iv:C9wTZF0HU0NeJcsNUwLpIX0ELUxjgtyDWpdbWiksDSw=,tag:w0alvDbx1cl1e7izVZV9HA==,type:str]
+        zaphyraPhone: ENC[AES256_GCM,data:WxGXvbz20SImLfNTUOpBcWtDq9Ia6bqEQFqkijpNYxgyiv1cloZAcy4ag7n4HOE1vVxIBDNlvCtAzHTWAnzJzw==,iv:pA1HYcOD58ivIbRp/aoiuG6ZK5ZSbxm9F8d0tCIQf/A=,tag:mqpYSMiM55HErXItBrQ59Q==,type:str]
         zaphyraHome: ENC[AES256_GCM,data:xMwLPSh78GIuiVh+4z84QgVQKOU7QW7VGjPJZpBwdZhvgXVQt5cMOmN4DD/Yev+Bme/2C7SigEY8bFJcgpHnbZ6Fp1E=,iv:fJtciKFZ2J3j32xF2L3XHS0cVBhPlOmpUzP4q0A3WHg=,tag:wd2XA4Q5p9TYjp9kfWDjAQ==,type:str]
+        grogHome: ENC[AES256_GCM,data:ASt5/wqH9c1yq6Ig6PAFEHwPEKCsigIDc+svk+H00jwdaFHqtivk2CzZKPfGe5U/keAJIQ0YsEFkuh/637LUCTz0U31MP7glshB+Fc5SBpexfY06r8IeQNyFNGMX,iv:hThh6hJ43LUfzZfprMgu+AtE98YdKuzj2/9nCmGkQJ0=,tag:aomJeVLG0Z6WaYKqy/DOTg==,type:str]
 sops:
     age:
+        - recipient: age1lkdpl26w3wyaes75hg6wwc2p3puqv24d4xyuf5xc9q9u9we0jq6q8lvz8f
+          enc: |
+            -----BEGIN AGE ENCRYPTED FILE-----
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxWkJETUpKRURGYWdVbHB5
+            cmIyU1RVRWs0Wm9tc3VZU3hNK2I4YVRHTlZJCk13YWxpdnpsVENzays4cWtPRDFT
+            Y2pCVGpZd2tQSjB5RklDRW9wM3NjYlEKLS0tIFJQWjRmUDE0TzNDQmF3TWFscndl
+            c2E3WXozTzFXQzNTaG1vYW5Rd2ExVVUK62bq/q6D3wkkwkgAFDl9//Sc7AL82DAA
+            VGXOX1BgCtXZCNC5StfXcLmPkk5FnMKEpA8qhvwc2xXxWLFDX6sNkQ==
+            -----END AGE ENCRYPTED FILE-----
         - recipient: age1laajqafnm4ft2m73wq7yqug4ts04ddn59wlqs4t30upeqa35dpdqu8fu3n
           enc: |
             -----BEGIN AGE ENCRYPTED FILE-----
-            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3QTkzdndWaFhLZy9pa3FQ
-            aURYemVnN2pTeFoxQmdaMUJnOW5UK2tSZ3lZCmwzNldDaU9CU3M0b2F5bEttRHZ4
-            bVJyQ3dPV04vZ0JTMWVZMFVsWkRuVjgKLS0tIFMwc3hmRUgwTTFMVkc1TVVWOFF2
-            VTluTTNXN1lwMUNNbGIvUXdTT1ZINncK1vSZvkMtI0Cal3JJ7stQ6r1ifiZN57wS
-            Gwq5BN8e6/sPihezsVN6CudDXP8FWgxc2/HFbtey17ZNWCtrH2FMuQ==
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVRDNEeUhLTEhjZnRtRk1G
+            QStnOFYvdWJkRVZ1Z2tCcE5SQSthQytNNVNNCk12QUtuY1dGNjE1SWhiU0NSYUxn
+            QTVTV2VhbkczbFc0ajJ3bkt1OTc1NVUKLS0tIFZEYTVZczlTNWkva0NZWDQ1MHBC
+            TmxTYWlpd3pVcjd3RWVidWlCaVp5TDAKcSXKP5gDTcrNWwq+XT6jEwfWjk4mtjNq
+            h2Mc1R73aMd/PRy3Oe2k8lJeK2+CQh+2x8sWFgsPQUeBX34idezCow==
             -----END AGE ENCRYPTED FILE-----
         - recipient: age1wpffcr5p88a2x9dzx5v3sq4jqurvygu94fx773n229fqk4p95qzs840cmn
           enc: |
             -----BEGIN AGE ENCRYPTED FILE-----
-            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkL1QxcmZBcFBtYlJSSmxH
-            RnVoRlZkeElweEwyMlFFQ2g1YW9kckFvZ0RnCk02VWc4M3NqMlNFakM0V3MyREtL
-            NUtYZ0xrc3ViSWRmS0docysyaGFxcjAKLS0tIG9tOFY5bUNuTFBydEdSM3lNb3Jo
-            V0Z3Nm1DSTJva3ZIdUx3WC9uNzFxcU0KK1MD39JlHr2VJ1CkO3vPGwaSJ6LvHB6F
-            AKkvWtDtXCFsxicbMf1po5u8Am3No2LuTkF4njIke394zpbH5/KGtQ==
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWN1hKZGVld2RFNDFZOGxq
+            K0UyY3JzMWRXVGRUc1RBdS9JSVpaRnBQb3lnClNUQ0tDelhpcXZIbmZQV1lOdkxQ
+            YnBLbG1YTWljR3dkR29TVTYzMThyWFkKLS0tIEpwOU1XeThETTIvbjY1Ri9RYlpm
+            cWN2NEJQNGk0T3NzWmZqcW9Xb0w1NnMKl638/KMXr1VHJhuYAWeoECEDC1iknlGT
+            N3tDMPTMfnI0osv+1Uw2OlrSO3+b+MQs/xht9QWDJNn1odqkKjphUQ==
             -----END AGE ENCRYPTED FILE-----
         - recipient: age1tud4lvpmpx5nqceyp09ls9ej8l80zlh29d8cpjxcajfnnyy85fvqs63snm
           enc: |
             -----BEGIN AGE ENCRYPTED FILE-----
-            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIaDJWc1YyU2YrQUZ2aS9H
-            cTgzZGFSb3pHL2FGMmR6YlUxTG1KRFJrWmtZCkQyRGJQV3cySk5PNENRQXQwRlcr
-            L3ZJVUpncFFtaVJ6UDVBT0tVRnFFNUEKLS0tIG8zaVBGWEQ4L3hYdVE5NDJUTFQ5
-            anhNZGxHWXJCT2ZJY1g4YTRkR0JPOWcKv1PHYJYbUod++c1dkW8mB6WoifFrQ6Ze
-            hMUxXOn4GiJRmO/B3HwKnrxaZpA67yPP/JUsah5VApbWE7ZIGhC/hQ==
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFS2xnQm5WOE5YNWtteGls
+            dC9FZTg5b1p1NnU4WnV3UmtzRUJhMFB2cGxNCi90Y3RWcE04SytlNDNBc0hVdmw2
+            NkFNTGxaNGNDR0VobVoyaVJRdGtZVTgKLS0tIHJjUURMMXRkZ2lwOVpzcmI3cDYr
+            VXBmUENTd3VsQThiUTFRRlNybCsyNU0KbqsNDTmU6U1WUhakZl/n7ZX945O6N8s2
+            Yj04q92AbhvHHqZmQo6EjVdytlSTSy6AJaGJCvwoHOPMmntsxD1FiA==
             -----END AGE ENCRYPTED FILE-----
         - recipient: age1qyqy5we7zua06ppj654rgd6t7kyw3gem6hnexna98j60klyus4zq68cjlz
           enc: |
             -----BEGIN AGE ENCRYPTED FILE-----
-            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2STdUd3d1ZU9PdWlBTUFx
-            ZUp6YWNTQVZHUWtmQ0JOVU5FU0xrNWhWQUdRCjZhWkFHNkM2MjNUZXhMeXBNWG11
-            SVl6M21vcjFaODhyVkNGNzljR3Q0OW8KLS0tIFVsWndDVTFEN2M1clArV0E2L292
-            TmN5THYvMjdWUUYvaDV6RFdlcjVIQ0EKu35B5iKErPdDFvnHmAuCpkBlAsP3J0Ml
-            /6/AZlBG3r02iCBzdjZW8peBAg2LjR/LbNcY4uy35JLbT4wL0jV9yA==
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzb3FBUzlRNFdUd292MHpJ
+            OXZzazZRdDN6OGFnKzdYdGZUQUltZm1xbXlnCkg0eUt0aW4yZGFid3V3eVovUlJV
+            UGZiTjlwL3FIbTZYTVl0R2ZrUDlDKzQKLS0tIG1yYXdabldrdzF2T0FNSm1FUGdp
+            NVdiSVpsT1VqUUgrZGVDRkpZVmxPQWsKGQ8b3Ih5o7KPH96i/FzIFiKJ9+u06NlM
+            t1wCDNS9mVPFaw0YwxQCpqrzvMCgWh2IAlkk6zNw+6/X30xNMQWX4g==
+            -----END AGE ENCRYPTED FILE-----
+        - recipient: age13f7t27x326hamq39qps2ygrftq3ylyn2nx8xga2kqaxgra2p748sphmetv
+          enc: |
+            -----BEGIN AGE ENCRYPTED FILE-----
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsVDhuKzNJR1VsOUpmcnZ4
+            OWxpNll3TUdNTG5LVFZTOGdMNUliTU9CR3g0CnA1SUtMTkVJbFVMekdHS0dMempW
+            RDMvbEwrSXhGSmpuaHNqYUFEczNjSFkKLS0tIFZUY3huYk1VZTRIVjNvK1RzM1JQ
+            RitwSFhUeE9QUGZzUzhvSlh4ZStiNmsKz/3dzIqR3kW7ywu38Rlh5pZo6kJqDADK
+            Y6WwzRLUcAqR3HEzh82lZP1Ll/2pzjk7yobtAZ9mWqKbINNn3v5EwQ==
             -----END AGE ENCRYPTED FILE-----
-    lastmodified: "2025-06-24T09:53:59Z"
-    mac: ENC[AES256_GCM,data:GLXHEZrgDwF05NiePcI17RjU3odB2mMhK6WwCEt7DwP5cqd5JQzlBRTpxzfZ9+KEBURq9JhrPWx2XpyBFZ+ippDzuLeTKxgMbcMZn1gpa80c+CBaZL/N94a5sf52FXFdsNfMseWn1IHGYAxW6YPY4SdT8Y57MTbxQkBSP56urOc=,iv:fAiOTOeqfM33qLezJobwe086PW3k8zgf2I1hL3XuGmU=,tag:Yigw5EN+lSUDcMGv9L1yxw==,type:str]
+    lastmodified: "2025-07-08T11:24:38Z"
+    mac: ENC[AES256_GCM,data:ZDjPpLKJlu/EtuL+SSAInl+4aKkGKH1QZRvRYuhQLWuL3/Vcydjv5aG2Fy6F73o7NlMUubixufdgsoITpH+SNndtH6rEQkl12Oo0H7MNGTdecJVjXtpLmHdmlVZvV1binbzOSfD+SRzXILQlzKq/jBqXC0TW0YUgPvIky12dSCs=,iv:KQw+K0px71dkdVpKom0+tV9CI8jczkLrd4HUuTkdkKM=,tag:kH2DYck3tVZtP1o6W13wDQ==,type:str]
     pgp:
-        - created_at: "2025-06-28T08:59:04Z"
+        - created_at: "2025-11-12T14:50:53Z"
           enc: |-
             -----BEGIN PGP MESSAGE-----
 
-            hF4DfdBfTP3jZzQSAQdA2QboSjnkI6dJiVwB1dvEht3YATzKibs4Pmk/r34zmScw
-            H3q5BRMqYsC1HAUrX02tpBYaK9lJMiYER0jZQkdQwKgO3sdktlIC3Fo5bQ+//u6W
-            0l4BItuNHClcqEa8bN+XxUw6dY+96HxfUtsXtkZI9Oy8mmagN27bKgz1lGw/9GB8
-            s3NjQVOpdo+/5WISaC31QL3CCM6V3fFEDoflPgiiEv5NC2H9Sxx/prNzHb8hJRWi
-            =1foN
+            hF4D3Q9NEB9zpDESAQdAaa13SU3jdrSGvu/244UyRzCbvr/Eh8gSTHeS/TfhIDEw
+            /lftv5V/E9tZu7WS2GVsgEiI4UbzjOh+U8iB7e6PHgHsdR7/+1e/IKFiolmKDhcU
+            0l4BRod9kuNlcmA/UMr5StEGZDsaco/E7xNyEPBJCRwe0mPgk1l3tnZnT0zMva7y
+            Z9e3DctKZXrZNknG0dFdeJ5kDtS/3a2vYLOf1ENJWjs9KM0bNyeNmyZNo/nrQw2G
+            =D3fg
             -----END PGP MESSAGE-----
-          fp: BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022
-        - created_at: "2025-06-28T08:59:04Z"
+          fp: AB27F5D1136B20D3149FBCC00389451731A3ADDD
+        - created_at: "2025-11-12T14:50:53Z"
           enc: |-
             -----BEGIN PGP MESSAGE-----
 
-            hF4D3Q9NEB9zpDESAQdAcNbbGzDvhVnvCYnPBGfY9hladAD0+aEm8WMjerbhxzYw
-            hWRtkWYpFp5V9XEWZnXVjioKkfGZpvLGD05zYWdnP97JbNDpSzZHWO8Rm9X8mAup
-            0l4B2JGXj9a92CcbjW/NRUDUp41lWHbG/p7BfeyaZwVHMOw7ioGcJsSAgKze3h+z
-            9UvRZVXM9PxMGm4teeeF6XW5gtXPOxAypvBucsJZaGoPneYXGRokzRrwrphrKRGG
-            =vBAB
+            hF4DfdBfTP3jZzQSAQdADDzxA5hRt36IL8K/U3aA4ZCqlhVVjdi7GdyL6euCHhEw
+            u2AMn3D0PRw1TU8A4G64EfXvvOE70Z6RB3VIhw3XYgCH8pDytvJn85FtfhQXfBHv
+            0l4BVUs+srg7Glm//UakQrjOzf4GnRjKOm5iIyuBBdmsRHNqMUTHdrjLHjjPhULX
+            sgRnG0A21eLwci2M2XycX3dfG+ZAFOQZlCfyQjG1gZz3rPbN5WGZCx/aJ92i9mdj
+            =fUsd
             -----END PGP MESSAGE-----
-          fp: AB27F5D1136B20D3149FBCC00389451731A3ADDD
+          fp: BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022
     unencrypted_suffix: _unencrypted
     version: 3.10.2
diff --git a/secrets/eximius.yaml b/secrets/eximius.yaml
@@ -0,0 +1,28 @@
+voidPassword: ENC[AES256_GCM,data:iaZ7Tilcrmc7JdKSFxpJ55lXtSOqTnw8Y8zzxzgJoj+rDXsEVz9ilxVvw6RRE3bhCYsP7lvOXc8oFLX2MQOGavF7rlIRHO6T8g==,iv:yvV+GOCCWF3IGRMqXeRK6Oi1F5yqq/Jj6ZkyrPHGaHE=,tag:NigKN87jGjedsecf16zQhg==,type:str]
+sops:
+    age:
+        - recipient: age1lkdpl26w3wyaes75hg6wwc2p3puqv24d4xyuf5xc9q9u9we0jq6q8lvz8f
+          enc: |
+            -----BEGIN AGE ENCRYPTED FILE-----
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOT1dvdVlqaGV0MjNUSVhj
+            Q3ZJMGR2OHhYYUVXSUFLTEZuNTBnaWtUb3dBClVXS2tsSzgvUEJkVlNiNlk1S1RI
+            czJQV09LcHJNOU5WZHN2TFRyNmtlR3MKLS0tIENsL2h5SjFTUnVLd3lCejVDZnJk
+            YVFQRGZRK3lVWlZrWm9KU3BHOElkK3MKORf4RgUNw4XdagWzBh/k6lqf3Zv6C+Vo
+            VbAmIsW6zJe3WPR/kZleUD92SnZA73skCLy6CaJKVgKU0jQFWSxUBA==
+            -----END AGE ENCRYPTED FILE-----
+    lastmodified: "2025-10-01T10:23:50Z"
+    mac: ENC[AES256_GCM,data:/SrARrT5kOZJsAUuP7wIxfgF4iYJW0q+6Wd6P/GR4a+6mz640IFCvjC6RbfRHUOmYMB9Hf9cWnxgZaMaqBkQf96J/GGIgTardxwMh917C8iiAR8wtOcx3ndBQCgg5vU7XdWm1GlCGs+PJ3vgeL6pumz2ZhFthkpEY+eCtMHxJ1k=,iv:wxpTioCp8t4NNNR7SDgCGel2EveSqAnye2A7wD4d1U8=,tag:F8Xe/LYFoRVHygEvrjd7Kw==,type:str]
+    pgp:
+        - created_at: "2025-10-01T10:43:14Z"
+          enc: |-
+            -----BEGIN PGP MESSAGE-----
+
+            hF4D3Q9NEB9zpDESAQdAW+m/XozTtV23R02QxTxpH6Now+yT4dVaL3NFsFs1YCYw
+            VL2s5EEM4keAuyn1ZexBci1r5I/ActQxq/NC1PyvNvHjUxWGbqnKNe6kDuU69lNO
+            0l4Bsid2JwX5DWPg6SiC/Cg8L4Rnlw5sRe3moYKvyg3LdXTip2PpkRTt1wTKPxqh
+            dQ/7V7NI4qBaE0pW5aHR708S+JZC9Uh0EGLeulbkGMAGKTEuzlSLyJX8SZgka+91
+            =q/NN
+            -----END PGP MESSAGE-----
+          fp: AB27F5D1136B20D3149FBCC00389451731A3ADDD
+    unencrypted_suffix: _unencrypted
+    version: 3.10.2
diff --git a/secrets/morio.yaml b/secrets/morio.yaml
@@ -14,8 +14,8 @@ resticPasswords:
     grapevine: ENC[AES256_GCM,data:ElNtJC2elPstqJ1vTJRJpNr0OyhTuTxCulh22qq459c=,iv:sgQCekPMcnyFzir/fISJAQZvV91e+43z9D9xShAz4Pg=,tag:LVjr6ZxFO9VmPXZWtz20Uw==,type:str]
     vaultwarden: ENC[AES256_GCM,data:MmXXWit37MC4dpJG1654IpxfRdw0b+2mpfu7K80ZTRQ=,iv:4wRi3ovrLrzCkUjiGpEpWWPSDkHUdpI82joofhoIP8U=,tag:zgTTK+h/vqLmxCNNtfrxwg==,type:str]
     things: ENC[AES256_GCM,data:9jjtqiUHwtCJKF1Mfg5bNZQhGHDFNZlAm04umn0SqnM=,iv:5sx+9tOTX/GHk7KwEZo1r4vJVX8LTe7clNsjxIhRAYw=,tag:D5b7/H4CWCCnAmTPPyCMyg==,type:str]
-knotKeys: ENC[AES256_GCM,data:wIpO5tMT7rj0oRuCeuQ7sGkuAumvubX2BRWXEm/5Agr3jnyt5zH62b3PvtPWxBjH6EPErpjz350jiDTsGwE9UJsPVD2wn3ZbjZLE9SjEyauI845tiyuB4i3/MPJ3JDO3KmwxJklSV4HPrkTvtvtjhhVOvO5G4i6lYd78f5lK7RJEdx0z87iSCDc6oJuVGcxD7akQUrQehlQqERGhKXyEZKYqe970svh111E5juvA/FCDWvNNzyFNmOfAsG03WEJuaynUxJcP4NF6V23GARtUXDepcpNm33m3XZczuVdUqIwugRmDekYhef1w5+Sb+AK0s1Y/axKOl41hT5vClZB3KV1upSoQCXT/KsBDrcgNKu2m4mU7PPRgMrmkV/Kc4MUHHK74FBKE0b1kKezanm8U4yqctwGc7MbacHUGW0af4oconRux8g1KizuGsycV0P/bGgA7QAXQ0RQ0NbTaNlB8lXGf/o8t+L9C32rWc6L2nufiY5G1HoqrgOJT8YgPE7dSp4N6DixCJqEt4qV9JwyhV/i6i3F0dQ08bbttE2sjm1nZwANjAJrBK+Y9EegIb0Q4N4spVzasOcVghH/I7RvkNEaEtxepCPhsKRXESH/LUrCjr7B/x2F2aKxKzD/dyKbppiN1AHfI9DsGTcQTJMRtIVqopiX2RzAvyy7/syAOpUjkQ7MZ7p90+JQgQ7KQHUjKEDS1UMLuJuuy6jipqhdL7QFGzkXsCIosapamc/TT/9cFOI9GPKrls/1jXg5niMf3st9iG26xwrCLsuMZRmpi7CkvNijkSS0OmjUAKc7SSxsYGfM4hhgl5ZinB+YADXPwoDpKuBWVRU8K4L6H3MGA+G6b7aMbsUsZ+UMbkbUUjJmuB3hKKyVhAdHDLkIuM5auQ/l/2ei9jcWdy8E6YJl1PKrEPSt7vssx+ZrE/3micOXCS9wK4wT64MZvwJjzZOLMde9csT7HN9V7IIUOzH8c3OMscBm5BZKOzwHf6ZdmnqA2w8rNJSszNpTKtxP+hToMcUyLmvmkZOks4TRLVAeei0rgTpyfO2jPOjml8FyaT+0UdjVIS1UaCQClm8yK6vnPcEiNvyHcJfEhqDlhblAC39aJyRenSw9sBDsGwJa7RZv1A8IgnvkUY+uvQyrZfENRt0c5i+u1y5tgziwkKgqa6I9EhQ5ZMWHtOTKAo9RWRQ3s1EiB/zvfz2VHgR0xmGt1cfIYIKqWCT1ILwD0RbzL/ZaPbgTwu3oQqDuoGCvMfUwUC8FCRUxj2oU3h7+7kImowJfkvsLapYFc9vIhBooCBYDwSeSRaoC594JCYNC4oaENKQTKE+NLfb3nJ2/+w5MWBZAgYVx0vE55lUbqfywdI2tml40cT/PMPpApS4yAg4Ou,iv:J9HssMnxmDQEURlOzQXBv2z3fXaJtT9uNaYcFqWO3vs=,tag:1Sk3TPOYSs7MfQZ2SZ0nKw==,type:str]
-radicaleUsers: ENC[AES256_GCM,data:01HlvCWJ/FFCmVQdBaJx4/GMxeZFwRly4gr+ITPPpwszDCegJUtKuNYqTAzIC7HRQdiHu7j7h7Qsh+qANMZL0URg46VMfMySB1Te8E9rOReUTuq457GtN3nbth1wazBUeoKqJgYHPagXbAu5s1qLTd5F5rM8vVEE9uEpZ8f/NH15gphQu6wRfPyRWOA572Yshm8P+1Gnvy5erA==,iv:eBgT+mbmKWGhNuqXrqmK7938tGYfNO9RpQlj+3ow6Mc=,tag:pH6MbDN9MajyGuSHH3lSWA==,type:str]
+knotKeys: ENC[AES256_GCM,data:MkbkQA15mDcnNPqmcMyVj6rKU+pXGjwtgZQK087w/K1dt6Xfi/ExkZd6rUFzj7w1Jd6Y9MKXg9G+veUNLg17jhcuyaC2VIX68ycWCIM8F/dtcAMlrewtegY1yzii9Qwdj4TJaealQ108K2oQotF062GaZtm9lY0pVAnC3/4gO970C8gvrpfS6vKtktU0qFUYmksduF42EOo8n7zk7lAQF8Zezu1Txar396kPnoPnnV+xIdVdoW6vT6WHBcbFhqE4Mw9vyOrMv+I+nHQIthTVDKnDhuhQW63H9y+DpNXztshN4JMgHnwHsj215DWKFZWXraotVdij50ZKDrO18N/Hei6D8WIenD9jsshwRFx8JpMoU9w6AvCoiI9WhxkJSBaeqk50nZUOCrQAmrZP1xjgTxoPUUGXG+wiXPL1EsJwT3C1Cj4hn98fKBiApFBm+6iiKCASLXvLus0sGOYt7ucxC0flcLUf2tOHBG1p8JhTRZDmDf63zYcGhYekBC8hTSsHUB2NzMVKHngjAUXqw8doToPiEFwwuW88fEL7/ij2h+rVKzqppnNYXX5kJ//h6RLKMhNwW2YwUnmCR/ngqrNr2dBoXLxuuimoPkWL1GXvwJLlvtFpQDwTRaYC5JDORbu8/jGK5uuVhW0sVGs0WwWYCT2R3tpZnP0bcCaYCCEuWk1sTY+l+estsMTHz1yXP4FdMe9wNkCetBYm6IHi8gvW29eMaWTD2wliSGB1zoigTMWZPfbc1gNUx5mhQfzfqD0w1xtO125Yz0zpsKug8z2UJbiegmHtTpacn0o6VJ4WVPyO0qmQU/MDz0isbPSpf9CwJp3Pv1RF+dL/Jx+kh4kD4UX5nqeZJLl8ec0I5k5yDD22e4uSYoC/ECrud2PMD7aaQW/tGrAMHDrf+Me6iba+QgRcr/KPLdjAet/P3RBcDjg7Hd33UVz2UGw8CAcISN4EXOD0lY4Ng89tmIkErGtVZvdsN0pUdBsO9yp1cUHkYNwMVLsr1Jj2ukaKvqZ2EWqKXHiAKuopiK7hR+05za4YQFWdFwsKOMjfoki0eWk01xWBCbIq40nA0D5hhwuTDtZ77L+qL2PBL9FuXxlP8h8CgUCnGGjHJFw51lOFbWvaW/NX3MdVUylk/QgWxTGuwsJJx1Bh8jgI6vsUu/LmcygIHKXfudGhO6K+hVB5lgdKfFhHULgIt9WirVGVb5VFXyFGyMaV6IJol+S13P7X5VDif93mzjOJwjELm44AX/lkhlXTCfJY3+7JGeMjnLsGNXJOqIxsq51EXGHu9nqOa0r87okf5o9Qm3VUoSamQIOIqX3U/h8x7vmNrxO/aH898YQVP9IPcQVKH7BrxgT2gw9oWzrmP/Tumx2+QRXEtrlxwaGysXr4hZIOxoiCWh9xRLBD6D1skoQrN5CRT3VOAuGKq+yCDdw8WtQR/a9zn8U1D5y8A8DYrOo5tPuGCTeIiyyUwN1e3siwzDbPkg0gKDzg8d9Clv+cFl2Mp9dmW8Us8CeicoQsP+CiYHAojcqwUooWAQulQd+0uv0aAnTNydzRyAi7CY/JC09HOexGz2hKjZLAOIBi4cE21L2HVYvXjJyOB+3WfJMkjJ98LQURZeyIsfeMOaLI2KGurtTvOHbH3O4vLeWRh2bdiJbSe+yi/j5Iy2UDFGU02gRUe5h6cOjd5WR6iwGTDYrcnyWxxUVJ,iv:G+Xxn2Z7ll/K1rn0rJDowrhTNV1SOTbnFcw3TCB/xnM=,tag:2iY0+oIHvczvr6YOKGdRKw==,type:str]
+radicaleUsers: ENC[AES256_GCM,data:lsVr2x3jZJY8nqJnIEXcd9qNyQsVF4OvcFUwUa+hdlXyACafN7wtDYuc6lvNp7eD6eMz3AD7BO9A6X5SVLQ6bMxUQ8hJYpm0+VeBQSTFFMDdXcVRbad5ymtS3D5sG3v20rlzrLC6tQCkrY7uyKdSKSBCEVcY1BDQMea9uRDi3bRRpiQC8Vz/frxhDnAiVGWtWTOb12KBJPs83STF+IOdZoEZuoKFzuzuhIUekuyEl/l+k/SbXAYA15q+4xK59lbMrJE=,iv:exwd7GdQrYCOFBIi6urDBC3xERo7I1YATN1e/38BIa0=,tag:CtkpxDz5kuU/6/nWEYB23A==,type:str]
 gotosocialEnv: ENC[AES256_GCM,data:5hvURqX+EqN8zpjirBmh5TIWWgaCga9QxnAfyW1rwOXELnM9ZBJAmqwLdxUa2j2DGrXsqw==,iv:nhVyiAoOJY0HtjB13FnmnQyLB+BWSRwDVrwUiFHBrE4=,tag:P207zPou7yXJKJBf+pxlHg==,type:str]
 environments:
     vaultwarden: ENC[AES256_GCM,data:uKc/1bnfXcxcUyBrvi5eYXpikmJna6hav0P0x4mopMY4VE6vGp/pSyqWXDzdjBYgV69/O2vqbfS4o61B+OjAS/ssYVyLvVHR3CJ+FCZmgA0zjO52C+TcVFYggxKUtcCVgBuNIzIqZ4lRE5T4I8V8WO6czQtmnBqvu27GY94sjyRUdG7hIySRVRbyhyCPFEYh9PKWUBEcdQf3P9dk9O3KKEG7TrngSm6yJtG0H7hc2M+4/xu8r7+j05AI5y2gs1oFN7QZqqSZ4Es4bUUn/SUXaeHnNCG/fr718fBKmvQuwrHjIfHwnxADA6HfklASKwRYm5EfWSW4RcCLKekFFfdR5O3mhQJR/mis46MdFUlhXvMJWQk=,iv:LnxnMS+xqlQuUQ88h9Etzk5IfpZenW/nOfWLYzABl0E=,tag:t10UUaatvmvZD/WEB0eL6g==,type:str]

@@ -36,8 +36,8 @@ sops:
             Ym5kdER1cTdYM09ydEgwUUlhQ3lXUEEKVjdcjjDXUhmpszI5i3NsjrsF6XRHf1a6
             qzqyN7FQTuwy23N9PBdJMTe7aAcw12vbvuY2v7UfmNzxkvggaDXJ0Q==
             -----END AGE ENCRYPTED FILE-----
-    lastmodified: "2025-06-18T10:40:25Z"
-    mac: ENC[AES256_GCM,data:M+2gpD8oE0av9i5vobwu3H6i2GoaC2h0k8yhkNvP3uGS5dnUEIf+tuOndD1XRV+gK5FQUg0PMsZOZWQvBHZjnQyUQAgo5fy/5kYqwsbyDDVFtvaovRhKKgjyMHFqe7zz0nWG9wG9rPc/CHyAZeZBrkmvy8QprEEidM3SozbT1gs=,iv:dolga3vHDzNgRho9LmE98zc0hAE5IAE0gtr/m3lqQYo=,tag:C3r5XF5QrfnBdotaUIqqaQ==,type:str]
+    lastmodified: "2025-09-21T18:06:07Z"
+    mac: ENC[AES256_GCM,data:zweRo8cjvz3d9af3Wwfkgn79aLxSeyfangKteVCbALjQHlyjtriST0QwlzXz8zQWEBKQzZ2XITR8jyp8Owm2gX/DlRPoY85HpdGMStTkLFXpGgn2xZDxQzccdSRUwue97SfzC1wjwPUcrsg2pnB6aYQgYLkRHDHjqB7xWDG9ixw=,iv:xDgcAWdZNg27cvCTLrBycwD7KjwpvbWni373IGva1Ls=,tag:xPhTNCAj2xcAW3kHx1KXiQ==,type:str]
     pgp:
         - created_at: "2025-06-16T13:06:52Z"
           enc: |-
diff --git a/secrets/novus.yaml b/secrets/novus.yaml
@@ -10,9 +10,6 @@ environments:
 dn42:
     wgPrivateKey: ENC[AES256_GCM,data:/D4liqLV+oo8d/M1j52MlzoB9cLnHKYc4tHFK8X9xXKgm+Fcj+pq9mKMCco=,iv:+Dt0QjFivY8cEwVEY8WMncLIieQvn7HeUMI/ETOhZlE=,tag:m2ajMB51iPryrjYYw1yWqQ==,type:str]
     peerings:
-        void:
-            wgPrivateKey: ENC[AES256_GCM,data:4N59Ti9SFQwKuTM4gHHvVfxrVChD5ijC3vYFJ+gdME2AAr7yD4otZepSfiI=,iv:yUA89MIb+9h/C5vrzZwpc5ducgqsXlvN5JlXsVNH3JU=,tag:K9DRXKS/9rXp4yfmolHZyA==,type:str]
-            wgPresharedKey: ENC[AES256_GCM,data:/KIS9wWtf8rk8oTgipWZjRtv+TRDVOznRnq7PeTdMa/ZP8qzAHWBPX2un3A=,iv:14aQm8ufGD74Rjy6tZal8ZGeDZ6Qhtd1T8LXchOOYG4=,tag:Lg3pEtM40HB3czTM8OK3iA==,type:str]
         tech9:
             wgPrivateKey: ENC[AES256_GCM,data:/4wOdZbhE80GvpfzZNyenSqQQoMd+ToJdXEdjaaSGAptYT5jjNroH8FEJco=,iv:GQz9Fg9ryBvtQTpwNTt4bxlRtqr36Vmt+SXAjX6ru1U=,tag:0woEX1Li06edjV2jKzQePg==,type:str]
         kioubit:

@@ -53,8 +50,8 @@ sops:
             MVZLcXBEallUZWJDTzBiQ0FCM3BjWDAKqssbQDMhQ5b2/6Z53ueIRlRT+ds2OrT/
             oPF1GopV5YD7Fsj9+n800gIw1fVmhoTOO8mZ6rxMrNvtBbntwDoheQ==
             -----END AGE ENCRYPTED FILE-----
-    lastmodified: "2025-06-19T19:01:02Z"
-    mac: ENC[AES256_GCM,data:8LOsv5kmQjwVAZxCJBu663Wpnfs+Wbvfg0v88rVgLyLkBmGbu+UWyUh5zOTMRzh5cLHC7CVDWUnMeZTLYOtFMZcA/2j2ABQHdttqr1yvGDNXOf1Jz7hizqJt0b5w8WVpzEVkX7cfK5VaEZm90cYYnfVk/ZjH5tY17sm2iO6NahY=,iv:Dp87qWiXkQie/Hd92p+9A2umihV/v72622o+tdufCe0=,tag:lnKKDHrKatHPmpSiHJiB0w==,type:str]
+    lastmodified: "2025-07-26T12:57:04Z"
+    mac: ENC[AES256_GCM,data:2VYn/1pGBgGReA0ZRfdIIyGEwzwHxm5xAbLoW5EzMz/SKZ1liSqmGU+0+4BSAO89mB6phEjcY44VTL0257rtfidx4438lqKgZzI/+efJlYfVsFA44nadO/v6Ux6RM9YzxlqlWqh9O2hVvJgirNXBI0YKovfTlObgjv8fAB36KEQ=,iv:LcwPESD2/z9feSxodeP3bpj9PGSSexhB9NdVc4TBn1g=,tag:m5T93LVv+REmEjHq6+mv8A==,type:str]
     pgp:
         - created_at: "2025-06-16T13:06:54Z"
           enc: |-
diff --git a/secrets/pratorum.yaml b/secrets/pratorum.yaml
@@ -0,0 +1,34 @@
+acmeTSIGKey: ENC[AES256_GCM,data:qfY0SbY0rusU+vCr7oiHTLHjICZBU1lYlBn7D2BLY5IWJbgrEO7OL0UvJAsUBtjMYsOrcFQB443K/3qThqtKDA==,iv:1TaM1oTvGzKlawxo/pv7cdBgqd7SxDMoy8fsDIk+VJg=,tag:DJ8sjxoSdjcGpbh70TjIjw==,type:str]
+syncthing:
+    cert: ENC[AES256_GCM,data:fOMcvmhu9QkF99SD95kzZEveMiwAR/R8GDffsqW0Nmp2gW2ThYG7pVi9TVnFwkPoncxEor5+vPDtDlTHuMHt3wAHvCZ7gftorvABrzkyhVEqNRLDln3JlgZ/YpAzjutXRCiuliE85AgOMB8WsniBSPQihCDIe2MolbYo8JlLJXL/5D6p9CGQqmRzlbmw2Unxzk7Xjw9Cm7RjaszK4SuB+loPdI3suVrCtfKQxQkCzDwQUdBnfeCyesYoPXJBBMDAtForu9i65LOXibDmvKj2rH5/zoUvvV5NO5wncMLED3X5Xyasz5ALJwxmOC+SR9u80emqoW6oN++V/IK8vG5/iiOSdTc7VYHjOgwzgfk47RMS9180cfP3c75Dap4uztdI3bMVYCt5UUkd4bqKI1IEOXG+TL2Ouorcti14G1JlIS17L+KLwnKsc4Ggend0fC7TQz/zAMkG95FmR30YK9G4dzsj7IKdQQeXBpMl7n/WY5byG3qAWqJbOK3EX8glZUHQjUlGCQSokk8CRGB9AhS66wisRNR7BQoYR2c9KjUD/xwVUCIeRDt+6ysUiFOhnhoGAgsnFTZtiuk+JOGhLx5LFWCV/l1kDzwtPa0lSUGeuoMb6rrnEc5HmFzmgKNAD+safXkuEt5ZoqjlCcI2XlnwLsLqQucroky6XhUomFqjesZj4cu2Y3OlkXB7sYQUGIOMBi/lvBKja0Bj0/MzSZp4Mj+8aiMXDdBgoTnIAhLVI3Y7E2x9E31z8I9SbxzxsN+aTyY/XRpF94m5bH3Z2P4MF4Ffk8k3UBPu0iFR89xgTq1gvrG/QMTDRWUtGBgWmf0g/u8St5Tb+Rb4xSew7pGGX6QAmcpsbcyAbEtDxgefnK6RXiPT6YjPJbtSmAxy3GMvOT0STy4Jh1mnqvZhCoxEsx2p8JglrdIe6JA2ShWaVxXkaLJpYZOxgVFJkjHi1xQxKPeC26Iqj3UlKNbmvcstYslhdLAEgmPTqurJoTUMQTvQI4zCe7/3IkVNfA+su269WpdK22Jk7QkHOyk0+BNJ9RF7kLDma54Rj7o=,iv:tO+qA9EMtzD4fCQjSlu0X5WqKZnsWmVBU0mKg6Cp1X0=,tag:N193+z2RwjSwruEsvwIBdA==,type:str]
+    key: ENC[AES256_GCM,data:VvshG8n3LT/eWm18iCIQkHc9GRZQsBWdq066ttqI4JoTohEB9IXR7dQDOC6QwTg8LObLL6zSUFTk2NAS8LyVZfQ4VMmqa24Pf+amwQmkXEv7w4h9ZEaBiU5b8i2JYaV1KDJvr5d+Svt2ZIVnLrIuu+l7C684xHRkX2yFkMh/XBtKRYT/CdhJeM0F4wfVZheBxdokJUlJdDueABaPOoo6PBWyNy3hwFkqInSHC/3aSk7HvB2d6eVDTZN0r27hlozD+JxWMtGhteJbmDZX4fL8oeRyKnJLW74jfxdipVWGw2bp/mQMVzU0JsbdAACDy4Gw5HsEW3+3F0G8xzW+vPm1r60M4+frPO2FbkT9nD7RpSPRKaRy4mYQtHujSougQhn4,iv:MGOWNw1aGAoYCWWgliInm6u2Nu4178OHIgrlD1TeO7s=,tag:p81V6XQJ9K1ux/W2NpAIFA==,type:str]
+zigbee2mqttSecrets: ENC[AES256_GCM,data:XuRVNV4gVr5FLgqGRXxgyaMAVJIt38adDOzJnY0GWaN52Lb9/E7Sx/TWB41cEO9D4/+LRlf0VbE2B0zehYjQGw1dHlf4rvS5OH8PefKdqBv6w+G0BKRXGh8daERsU8v2r+Vjw7kWtyiADzKP2NRJrVLnJiITwq8kmHHsrYNcs+/492Z1/ElDTe3B32Hq7ATHaP+G7xbfgxMuxIcf9z1EFl39krpgQaw/5eWq7WT7QZIHKD7tZqSpgAUxSDBSNjE+M3wq8PmaqecvO1h/+UtEq5MzxnzfpF0yopJa9cch5SwQqT6XHrxzbM2DldZctuGGmcTJrWpcqHkT4mcO4MfwlanJ/YaT70H25ukJEAHKG/rU86QCk5pIUwGSH15GSxi8ze83QFmJhskzMAoJuDJ6h1AoS9bRn5wY,iv:kZqhnTlwMhIvXg4deiC1D73Y+gspZwdu08yoyeAEngk=,tag:GuzryBSDNke+5jXOuDtwDw==,type:str]
+dn42:
+    wgPrivateKey: ENC[AES256_GCM,data:CjFgiBZieQdWPyDPl6gcz3xarWR5GTYJ9Ruee7/9pQLlypm+RWRys/3WOFo=,iv:uC7A58MS0zvwKMc74x0xSTIAJS7GbvoJN5N9KfXFVyw=,tag:y9sNo65Qk1TxqN0ReKDCAQ==,type:str]
+sops:
+    age:
+        - recipient: age13f7t27x326hamq39qps2ygrftq3ylyn2nx8xga2kqaxgra2p748sphmetv
+          enc: |
+            -----BEGIN AGE ENCRYPTED FILE-----
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwRkU3ZHdNOFZKMmhnMDlT
+            cnBCbEFUbS9mUGxQdk14T1EzT3JMdTFMUXlrClpKVnMxWEpFcDdQaXpjQWR3RzEv
+            VlNGQWcxa0RWTEpoa3ViVm10NDZJYlEKLS0tIEZHT3huQ3ZCa3FVMzNnSzVmV2N5
+            TndyejhxbVZDTVdaYWRXT1htMVVsOTgKWAOJekArzYzoJF/JcPTSWrhQnvQrl9bU
+            A7H0mCdklZZ66jiUo4iKLwocBn7h9VJ4p3lBdRxyqXuN6dicdQfafg==
+            -----END AGE ENCRYPTED FILE-----
+    lastmodified: "2025-09-22T17:42:12Z"
+    mac: ENC[AES256_GCM,data:oN5xWdhk4JTJ9x6YjnIfuPlc/h59XKacSHZqPJPd6Q4b7M4zZqZ+SlZ+4E2UAI5w8eoqXHCJAGCSEOzYZ9MBW+zVu9oiWTWWDWBn0D6KRct+NAN+hDisGWBS1dL2uTNchdQfBsFp81Yc9HvLjQ8R40vqp2i/y03JjZChYexpl0I=,iv:Zj2Uj6cra7GXZzeJYj2z7Nc2KArPuf2/dUvYwCAZuO8=,tag:tb2a+0JqDz4u+i2/bAVXAA==,type:str]
+    pgp:
+        - created_at: "2025-09-21T19:21:14Z"
+          enc: |-
+            -----BEGIN PGP MESSAGE-----
+
+            hF4DfdBfTP3jZzQSAQdAiw5PHq1LVzAedKgptTmvtM/ceMb3XRBI9ETefYggjCAw
+            0VKqi/lqc7b2HukVAIyfT+dsyC5+gvoTpSTUQjsSVeQA7cCS/M6n0gH8B2KeoHWY
+            0l4BqbX0jNreduP38y3+feILHV94ZQe3Lo9KPYNWjNC0G4nbYw3X/XAl22weEcZy
+            90pmUIfmPSGmgl1n73ePBKyX3eSo2TNc2OsJ9YQzTJNdhSoLUMq4oirMaxZIivbY
+            =cOXC
+            -----END PGP MESSAGE-----
+          fp: BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022
+    unencrypted_suffix: _unencrypted
+    version: 3.10.2
diff --git a/secrets/zaphyra/sieve.yaml b/secrets/zaphyra/sieve.yaml
@@ -4,36 +4,25 @@ sops:
         - recipient: age1wpffcr5p88a2x9dzx5v3sq4jqurvygu94fx773n229fqk4p95qzs840cmn
           enc: |
             -----BEGIN AGE ENCRYPTED FILE-----
-            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsTDJSRzI0ZkFCM29lMmJj
-            THNMb0F5SklUbXltTnNjT3pMd2hGZkNBekZzCnlrTGFpdzBucThCbnp4VW5qTisz
-            ZDdueG84bDhYb28rMjlRL2pERGhLbnMKLS0tIG5Xd08yL0crK3pRck4vcC92Rkwr
-            WlRxTDhwTmJLV012aXRLTDROSVFmL00KjqNd3ZPDmVpRvltq7WZLXRdznFaMMXT4
-            DXucNg0l4L3eNGVqHj7jylpK/K0E8qn5zVTI0BRxLojonQAikFm/2w==
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzcXc4d1BxcER3cVNGa2cw
+            R21WZTJYb3dnM0lXOTN4cy9SdGh1WGl3eDFrCnpib1BwdzMrczZiZ3hiaU9qTEtC
+            bVYxT1NURWdMdjhNMkFSd0JWM1RibUEKLS0tIHZza0ExbHBiK3BOSGlHaDIxaDlp
+            MmtvS1VYeWtZRFRxQ0ZYWksrb1hLcDAKwDMF/ps6CsJFZQMbC2xluDXNCvoy3JhQ
+            HIJ3MhE+t1072emdkdMV32myvhLDrqjgVRq9emSRtLoqJi7kGgfO6w==
             -----END AGE ENCRYPTED FILE-----
     lastmodified: "2025-05-24T11:26:16Z"
     mac: ENC[AES256_GCM,data:KQP4IvHkCVWUYoWmvThQ6MageJzohS/O+039Kg6MvPeWiLbPdIEJH9GHG1bvXZ47Xl3cPVlQwJBQ24g2iqYFkGRnwVpnJ4mz2v2fp4JaTP8DJdAAJS4Xl4pseMsatvbFL8ZVNVBXvbbbYGvWzE/muMQv8xZ6em+AwwACNjtPWV4=,iv:CJIeT6eYh1Oku4N6lC/ESBiyPtE7m2ffka1S9x2YHzU=,tag:HKkRE5+VSgxrn+QsoKykKQ==,type:str]
     pgp:
-        - created_at: "2025-06-16T13:07:16Z"
+        - created_at: "2025-11-12T14:51:05Z"
           enc: |-
             -----BEGIN PGP MESSAGE-----
 
-            hF4DfdBfTP3jZzQSAQdAwMC+8SP6GLKtuM/48DUHdLQB4d+eOEEcQjhkf1ubPjMw
-            OIijBS1UWxcX12Cvsq2fZ1bnJYGGdN7fkrwGMKKiCjBAK7wuqDJcuAZJYPP4nzS0
-            0l4Bk8JWqyXZ0G3sRRNAhb/sbJYNwB88igDpxErqiSvjhwlHxSxqRvyrOuwptYYa
-            vD6OVzmiD7nvXv4spNLWmoeFBS8GSH+/IYObwz06/vJbKvieKRR10gkkhNnHh7Yx
-            =D8wp
+            hF4DfdBfTP3jZzQSAQdAxIb5Nel67yYrxtBuTHQI7s0dgJglBNMISS2HP/3HfCIw
+            DOhNTgFgf3bfDKH1p/7i6YHfMn5CI9jQTtj1alOdyzygioutYaNI6DJU3qhD2hZU
+            0l4BUOBSWFxsLHZ07vKBu+j89ryvMPkbWoNBv0I0goSVN1JEJDFDxTvcUgXctq0Z
+            DESk+850m1QCvezSnH3cC/LKZ3ePWVqPdHz6UbfYFjdK+FhY7CMqY2iTYa23ApSQ
+            =//B1
             -----END PGP MESSAGE-----
           fp: BFE6386C8D66BCD4DAE14FC895F0FE7CD7E6A022
-        - created_at: "2025-06-16T13:07:16Z"
-          enc: |-
-            -----BEGIN PGP MESSAGE-----
-
-            hF4DaBViTd9dOpwSAQdA9w51QzHk9EFaruOqirieCVTb76SxmnoWdDbS5GTsay4w
-            LeR9CoG+EoIoUFtxxWJ+1KjOVVnNj02z2LO8AkNKdoHc6JEHAL02fXM3O5FwBzzj
-            0l4Bg7yI3fD7iU5Aa7uTjGRZ3K4oS/abbJKDqnMOoCMMwW1Ipk2DjH1DdkW+JOi+
-            ueQLjYxjDPRrdxRnLWiOVxCGke717hkkZOweCvwO8Vu+AhoZhEoXvVlE4zeihoZ1
-            =K2tb
-            -----END PGP MESSAGE-----
-          fp: 321EFA52CF155E9FD646279E0FB0CA11985EB5F6
     unencrypted_suffix: _unencrypted
     version: 3.9.4
diff --git a/statix.toml b/statix.toml
@@ -0,0 +1,6 @@
+disabled = [
+    'collapsible_let_in'
+]
+nix_version = '2.4'
+ignore = ['.direnv', 'resources' ]
+