zaphyra's git: nixfiles

zaphyra and void's nixfiles

commit 2930ff73dcc5da49d9a70fdcd58b74dcf05e7779
parent ad47266d4f5c14d99f026cb128f67d331b668fe7
Author: Katja (zaphyra) <git@ctu.cx>
Date: Fri, 6 Jun 2025 20:10:19 +0200

rename `katja` -> `zaphyra`
107 files changed, 1962 insertions(+), 1965 deletions(-)
D
config/home/katja/common.nix
|
39
---------------------------------------
D
config/home/katja/configure/gnome.nix
|
187
-------------------------------------------------------------------------------
D
config/home/katja/impermanence.nix
|
23
-----------------------
D
config/home/katja/programs/errands.nix
|
11
-----------
D
config/home/katja/programs/firefox.nix
|
317
-------------------------------------------------------------------------------
D
config/home/katja/programs/fish.nix
|
14
--------------
D
config/home/katja/programs/fractal.nix
|
14
--------------
D
config/home/katja/programs/mcfly.nix
|
16
----------------
D
config/home/katja/programs/ssh.nix
|
29
-----------------------------
D
config/home/katja/programs/thunderbird.nix
|
51
---------------------------------------------------
D
config/home/katja/programs/tuba.nix
|
21
---------------------
D
config/home/katja/services/easyeffects.nix
|
28
----------------------------
A
config/home/zaphyra/common.nix
|
39
+++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/configure/gnome.nix
|
187
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R
config/home/katja/configure/xdg.nix -> config/home/zaphyra/configure/xdg.nix
|
0
R
config/home/katja/gnomeExtensions/bluetoothBatteryMeter.nix -> config/home/zaphyra/gnomeExtensions/bluetoothBatteryMeter.nix
|
0
R
config/home/katja/gnomeExtensions/dash-to-dock.nix -> config/home/zaphyra/gnomeExtensions/dash-to-dock.nix
|
0
R
config/home/katja/gnomeExtensions/emoji-copy.nix -> config/home/zaphyra/gnomeExtensions/emoji-copy.nix
|
0
R
config/home/katja/gnomeExtensions/just-perfection.nix -> config/home/zaphyra/gnomeExtensions/just-perfection.nix
|
0
R
config/home/katja/gnomeExtensions/pip-on-top.nix -> config/home/zaphyra/gnomeExtensions/pip-on-top.nix
|
0
R
config/home/katja/gnomeExtensions/search-light.nix -> config/home/zaphyra/gnomeExtensions/search-light.nix
|
0
R
config/home/katja/gnomeExtensions/space-bar.nix -> config/home/zaphyra/gnomeExtensions/space-bar.nix
|
0
A
config/home/zaphyra/impermanence.nix
|
23
+++++++++++++++++++++++
R
config/home/katja/programs/alacritty.nix -> config/home/zaphyra/programs/alacritty.nix
|
0
R
config/home/katja/programs/ansible.nix -> config/home/zaphyra/programs/ansible.nix
|
0
R
config/home/katja/programs/apostrophe.nix -> config/home/zaphyra/programs/apostrophe.nix
|
0
R
config/home/katja/programs/bat.nix -> config/home/zaphyra/programs/bat.nix
|
0
R
config/home/katja/programs/bitwarden-cli.nix -> config/home/zaphyra/programs/bitwarden-cli.nix
|
0
R
config/home/katja/programs/celluloid.nix -> config/home/zaphyra/programs/celluloid.nix
|
0
R
config/home/katja/programs/deploymentUtilities.nix -> config/home/zaphyra/programs/deploymentUtilities.nix
|
0
A
config/home/zaphyra/programs/errands.nix
|
11
+++++++++++
R
config/home/katja/programs/eza.nix -> config/home/zaphyra/programs/eza.nix
|
0
A
config/home/zaphyra/programs/firefox.nix
|
317
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/home/zaphyra/programs/fish.nix
|
14
++++++++++++++
A
config/home/zaphyra/programs/fractal.nix
|
14
++++++++++++++
R
config/home/katja/programs/ghostty.nix -> config/home/zaphyra/programs/ghostty.nix
|
0
R
config/home/katja/programs/git.nix -> config/home/zaphyra/programs/git.nix
|
0
R
config/home/katja/programs/gpg.nix -> config/home/zaphyra/programs/gpg.nix
|
0
R
config/home/katja/programs/helix.nix -> config/home/zaphyra/programs/helix.nix
|
0
R
config/home/katja/programs/htop.nix -> config/home/zaphyra/programs/htop.nix
|
0
R
config/home/katja/programs/imv.nix -> config/home/zaphyra/programs/imv.nix
|
0
R
config/home/katja/programs/javascript.nix -> config/home/zaphyra/programs/javascript.nix
|
0
R
config/home/katja/programs/libreoffice.nix -> config/home/zaphyra/programs/libreoffice.nix
|
0
A
config/home/zaphyra/programs/mcfly.nix
|
16
++++++++++++++++
R
config/home/katja/programs/micro.nix -> config/home/zaphyra/programs/micro.nix
|
0
R
config/home/katja/programs/mpv.nix -> config/home/zaphyra/programs/mpv.nix
|
0
R
config/home/katja/programs/nautilus.nix -> config/home/zaphyra/programs/nautilus.nix
|
0
R
config/home/katja/programs/nim.nix -> config/home/zaphyra/programs/nim.nix
|
0
R
config/home/katja/programs/nix-cleanup.nix -> config/home/zaphyra/programs/nix-cleanup.nix
|
0
R
config/home/katja/programs/ocrmypdf.nix -> config/home/zaphyra/programs/ocrmypdf.nix
|
0
R
config/home/katja/programs/paper-plane.nix -> config/home/zaphyra/programs/paper-plane.nix
|
0
R
config/home/katja/programs/papers.nix -> config/home/zaphyra/programs/papers.nix
|
0
R
config/home/katja/programs/password-store.nix -> config/home/zaphyra/programs/password-store.nix
|
0
R
config/home/katja/programs/pdfarranger.nix -> config/home/zaphyra/programs/pdfarranger.nix
|
0
R
config/home/katja/programs/phockup.nix -> config/home/zaphyra/programs/phockup.nix
|
0
R
config/home/katja/programs/shellUtilities.nix -> config/home/zaphyra/programs/shellUtilities.nix
|
0
A
config/home/zaphyra/programs/ssh.nix
|
25
+++++++++++++++++++++++++
R
config/home/katja/programs/starship.nix -> config/home/zaphyra/programs/starship.nix
|
0
R
config/home/katja/programs/texlive.nix -> config/home/zaphyra/programs/texlive.nix
|
0
A
config/home/zaphyra/programs/thunderbird.nix
|
51
+++++++++++++++++++++++++++++++++++++++++++++++++++
R
config/home/katja/programs/tmux.nix -> config/home/zaphyra/programs/tmux.nix
|
0
A
config/home/zaphyra/programs/tuba.nix
|
21
+++++++++++++++++++++
R
config/home/katja/programs/typst.nix -> config/home/zaphyra/programs/typst.nix
|
0
R
config/home/katja/programs/yt-dlp.nix -> config/home/zaphyra/programs/yt-dlp.nix
|
0
R
config/home/katja/programs/zathura.nix -> config/home/zaphyra/programs/zathura.nix
|
0
R
config/home/katja/programs/zoxide.nix -> config/home/zaphyra/programs/zoxide.nix
|
0
R
config/home/katja/programs/zsh.nix -> config/home/zaphyra/programs/zsh.nix
|
0
A
config/home/zaphyra/services/easyeffects.nix
|
28
++++++++++++++++++++++++++++
R
config/home/katja/services/mako.nix -> config/home/zaphyra/services/mako.nix
|
0
R
config/home/katja/services/waybar.nix -> config/home/zaphyra/services/waybar.nix
|
0
R
config/home/katja/services/wlsunset.nix -> config/home/zaphyra/services/wlsunset.nix
|
0
M
config/nixos/modules/filesystem/impermanence.nix
|
2
+-
D
config/nixos/modules/presets/katja/enable.nix
|
133
-------------------------------------------------------------------------------
D
config/nixos/modules/presets/katja/router/enable.nix
|
93
-------------------------------------------------------------------------------
D
config/nixos/modules/presets/katja/router/systemd-networkd.nix
|
246
-------------------------------------------------------------------------------
D
config/nixos/modules/presets/katja/smarthome/enable.nix
|
32
--------------------------------
D
config/nixos/modules/presets/katja/smarthome/mqttWebUI.nix
|
71
-----------------------------------------------------------------------
D
config/nixos/modules/presets/katja/smarthome/zigbee2mqtt.nix
|
122
-------------------------------------------------------------------------------
D
config/nixos/modules/presets/katja/syncthing.nix
|
176
-------------------------------------------------------------------------------
R
config/nixos/modules/presets/katja/dnsServer.nix -> config/nixos/modules/presets/zaphyra/dnsServer.nix
|
0
A
config/nixos/modules/presets/zaphyra/enable.nix
|
133
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R
config/nixos/modules/presets/katja/mailServer.nix -> config/nixos/modules/presets/zaphyra/mailServer.nix
|
0
R
config/nixos/modules/presets/katja/mautrixBridges/signal.nix -> config/nixos/modules/presets/zaphyra/mautrixBridges/signal.nix
|
0
R
config/nixos/modules/presets/katja/mautrixBridges/telegram.nix -> config/nixos/modules/presets/zaphyra/mautrixBridges/telegram.nix
|
0
R
config/nixos/modules/presets/katja/mautrixBridges/whatsapp.nix -> config/nixos/modules/presets/zaphyra/mautrixBridges/whatsapp.nix
|
0
A
config/nixos/modules/presets/zaphyra/router/enable.nix
|
93
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R
config/nixos/modules/presets/katja/router/pppd.nix -> config/nixos/modules/presets/zaphyra/router/pppd.nix
|
0
A
config/nixos/modules/presets/zaphyra/router/systemd-networkd.nix
|
246
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/nixos/modules/presets/zaphyra/smarthome/enable.nix
|
32
++++++++++++++++++++++++++++++++
R
config/nixos/modules/presets/katja/smarthome/influxdb2.nix -> config/nixos/modules/presets/zaphyra/smarthome/influxdb2.nix
|
0
R
config/nixos/modules/presets/katja/smarthome/mosqitto.nix -> config/nixos/modules/presets/zaphyra/smarthome/mosqitto.nix
|
0
A
config/nixos/modules/presets/zaphyra/smarthome/mqttWebUI.nix
|
71
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R
config/nixos/modules/presets/katja/smarthome/telegraf.nix -> config/nixos/modules/presets/zaphyra/smarthome/telegraf.nix
|
0
A
config/nixos/modules/presets/zaphyra/smarthome/zigbee2mqtt.nix
|
122
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
config/nixos/modules/presets/zaphyra/syncthing.nix
|
176
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
config/nixos/modules/users/katja.nix
|
109
-------------------------------------------------------------------------------
A
config/nixos/modules/users/zaphyra.nix
|
110
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
hosts/huntii/default.nix
|
6
+++---
M
hosts/morio/default.nix
|
6
+++---
M
hosts/novus/default.nix
|
6
+++---
M
hosts/polaris/default.nix
|
6
+++---
D
resources/katja/mqttWebUI/config.nix
|
217
-------------------------------------------------------------------------------
A
resources/zaphyra/mqttWebUI/config.nix
|
217
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R
resources/katja/mqttWebUI/extra-css.css -> resources/zaphyra/mqttWebUI/extra-css.css
|
0
R
resources/katja/rootCA.crt -> resources/zaphyra/rootCA.crt
|
0
R
resources/katja/routerRuleset.nft -> resources/zaphyra/routerRuleset.nft
|
0
M
secrets/common.yaml
|
6
+++---
diff --git a/config/home/katja/common.nix b/config/home/katja/common.nix
@@ -1,39 +0,0 @@
-{ lib, homeManagerModules, ... }:
-
-{
-
-  home = {
-    username = "katja";
-    homeDirectory = "/home/katja";
-
-    language = {
-      "base" = "en_US.UTF-8";
-      "time" = "de_DE.utf8";
-      "address" = "de_DE.utf8";
-      "monetary" = "de_DE.utf8";
-      "paper" = "de_DE.utf8";
-    };
-
-    stateVersion = lib.mkDefault "24.11";
-  };
-
-  imports = [
-    homeManagerModules.katja.programs.fish
-    homeManagerModules.katja.programs.starship
-    homeManagerModules.katja.programs.mcfly
-    homeManagerModules.katja.programs.zoxide
-    homeManagerModules.katja.programs.eza
-    homeManagerModules.katja.programs.bat
-
-    homeManagerModules.katja.programs.micro
-    homeManagerModules.katja.programs.helix
-    homeManagerModules.katja.programs.tmux
-    homeManagerModules.katja.programs.htop
-
-    homeManagerModules.katja.programs.deploymentUtilities
-    homeManagerModules.katja.programs.shellUtilities
-
-    homeManagerModules.katja.programs.nix-cleanup
-  ];
-
-}
diff --git a/config/home/katja/configure/gnome.nix b/config/home/katja/configure/gnome.nix
@@ -1,187 +0,0 @@
-{
-  inputs,
-  lib,
-  pkgs,
-  ...
-}:
-
-let
-  nixStd = inputs.nixStd.lib;
-
-in
-{
-
-  manual.html.enable = true;
-
-  home.sessionVariables = {
-    QT_QPA_PLATFORMTHEME = "gnome";
-  };
-
-  home.persistence."/nix/persist/home/katja".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"
-  ];
-
-  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
-    ]);
-
-  gtk = {
-    enable = true;
-
-    iconTheme.package = pkgs.adwaita-colors-icon-theme;
-    iconTheme.name = "Adwaita-green";
-
-    gtk3.extraConfig = {
-      gtk-application-prefer-dark-theme = 1;
-      gtk-theme-name = "adw-gtk3-dark";
-    };
-  };
-
-  # Use `dconf watch /` to track stateful changes you are doing and store them here.
-  dconf.settings =
-    with inputs.homeManager.lib.hm.gvariant;
-    let
-      numWorkspaces = 7;
-      workspaces = (
-        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
-      );
-    in
-    {
-      "org/gnome/mutter" = {
-        edge-tiling = true;
-        dynamic-workspaces = false;
-        # Enable fractional scaling
-        experimental-features = [ "scale-monitor-framebuffer" ];
-      };
-
-      "org/gnome/desktop/wm/preferences" = {
-        button-layout = "close:appmenu";
-        auto-raise = false;
-        focus-mode = "sloppy";
-        num-workspaces = lib.lists.last workspaces;
-        workspace-names = [
-          "Main"
-          "Mail"
-          "Term"
-        ];
-      };
-
-      "org/gnome/desktop/wm/keybindings" =
-        builtins.listToAttrs (
-          builtins.concatMap (v: [
-            {
-              name = "switch-to-workspace-${toString v}";
-              value = [ "<Super>${toString v}" ];
-            }
-            {
-              name = "move-to-workspace-${toString v}";
-              value = [ "<Super><Shift>${toString v}" ];
-            }
-          ]) workspaces
-        )
-        // {
-          switch-input-source = [ "<Control><Super>space" ];
-          switch-input-source-backward = [ "<Shift><Control><Super>space" ];
-        };
-
-      "org/gnome/shell/keybindings" = builtins.listToAttrs (
-        map (v: {
-          name = "switch-to-application-${toString v}";
-          value = [ ];
-        }) workspaces
-      );
-      "org/gnome/shell" = {
-        disable-extension-version-validation = true;
-        disable-user-extensions = false;
-        enabled-extensions = with pkgs.gnomeExtensions; [
-          battery-time-percentage-compact.extensionUuid
-          caffeine.extensionUuid
-        ];
-        favorite-apps = [
-          "org.gnome.Nautilus.desktop"
-          "firefox.desktop"
-          "thunderbird.desktop"
-          "org.gnome.Fractal.desktop"
-          "dev.geopjr.Tuba.desktop"
-          "org.gnome.Calendar.desktop"
-          "io.github.mrvladus.List.desktop"
-          "org.gnome.Podcasts.desktop"
-          "com.mitchellh.ghostty.desktop"
-          "org.gnome.Settings.desktop"
-        ];
-      };
-
-      "org/gnome/settings-daemon/plugins/media-keys"."custom-keybindings" = [
-        "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/"
-      ];
-      "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0" = {
-        name = "Start Terminal";
-        command = "ghostty";
-        binding = "<Super>Return";
-      };
-
-      "org/gnome/settings-daemon/plugins/color".night-light-enabled = true;
-      "org/gnome/settings-daemon/plugins/power".sleep-inactive-ac-type = "nothing";
-
-      "org/gnome/desktop/a11y".always-show-universal-access-status = false;
-      "org/gnome/desktop/privacy".remember-recent-files = false;
-      "org/gnome/desktop/interface" = {
-        color-scheme = "prefer-dark";
-        accent-color = "green";
-        enable-hot-corners = false;
-        show-battery-percentage = true;
-      };
-
-      "org/gnome/desktop/input-sources".sources = [
-        (mkTuple [
-          "xkb"
-          "us+mac"
-        ])
-        (mkTuple [
-          "xkb"
-          "de"
-        ])
-        (mkTuple [
-          "xkb"
-          "ru+mac"
-        ])
-      ];
-      "org/gnome/desktop/background" = {
-        picture-uri = "file://${pkgs.nixos-artwork.wallpapers.simple-blue.gnomeFilePath}";
-        picture-uri-dark = "file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray.gnomeFilePath}";
-      };
-      "org/gnome/desktop/screensaver" = {
-        picture-uri = "file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray.gnomeFilePath}";
-        primary-color = "#3465a4";
-        secondary-color = "#000000";
-      };
-    };
-
-}
diff --git a/config/home/katja/impermanence.nix b/config/home/katja/impermanence.nix
@@ -1,22 +0,0 @@
-{ ... }:
-
-{
-
-  home.persistence."/nix/persist/home/katja" = {
-    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")
-    ];
-  };
-
-}-
\ No newline at end of file
diff --git a/config/home/katja/programs/errands.nix b/config/home/katja/programs/errands.nix
@@ -1,11 +0,0 @@
-{ lib, pkgs, ... }:
-
-{
-
-  home.packages = [ pkgs.errands ];
-
-  home.persistence."/nix/persist/home/katja".directories = [
-    "tuba/.local/share/errands"
-  ];
-
-}
diff --git a/config/home/katja/programs/firefox.nix b/config/home/katja/programs/firefox.nix
@@ -1,317 +0,0 @@
-{
-  inputs,
-  pkgs,
-  lib,
-  ...
-}:
-
-{
-
-  home.sessionVariables = {
-    BROWSER = "firefox";
-  };
-
-  home.file."firefox-gnome-theme" = {
-    source = inputs.firefoxGnomeTheme;
-    target = ".mozilla/firefox/katja/chrome/firefox-gnome-theme";
-  };
-
-  home.persistence."/nix/persist/home/katja".directories = [
-    "firefox/.mozilla/firefox/"
-    "firefox/.cache/mozilla/firefox"
-  ];
-
-  programs.firefox = {
-    enable = true;
-    package = pkgs.firefox;
-    nativeMessagingHosts = [ pkgs.ff2mpv-rust ];
-
-    profiles.katja = {
-      id = 0;
-      isDefault = true;
-
-      settings = {
-        # required for firefox-gnome-theme
-        "browser.toolbars.bookmarks.visibility" = "never";
-        "browser.tabs.drawInTitlebar" = true;
-        "browser.theme.dark-private-windows" = false;
-        "browser.uidensity" = 0;
-        "svg.context-properties.content.enabled" = true;
-        "toolkit.legacyUserProfileCustomizations.stylesheets" = true;
-      };
-
-      userChrome = ''
-        @import "firefox-gnome-theme/userChrome.css";
-      '';
-
-      userContent = ''
-        @import "firefox-gnome-theme/userContent.css";
-      '';
-
-      search.force = true; # Required to prevent search engine symlink being overwritten. See https://github.com/nix-community/home-manager/issues/3698
-      search.engines = {
-        "Noogle" = {
-          icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
-          definedAliases = [ "@noogle" ];
-          urls = [ { template = "https://noogle.dev/q?term={searchTerms}"; } ];
-        };
-
-        "NixOS Options" = {
-          icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
-          definedAliases = [ "@nixos" ];
-          urls = [ { template = "https://search.nixos.org/options?query={searchTerms}"; } ];
-        };
-
-        "Nix Packages" = {
-          icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
-          definedAliases = [ "@nixpkgs" ];
-          urls = [ { template = "https://search.nixos.org/packages?query={searchTerms}"; } ];
-        };
-      };
-    };
-
-    policies = {
-      DisableSetDesktopBackground = true;
-
-      # disable tracking bullshit
-      DisableTelemetry = true;
-      DisablePocket = true;
-      DisableFirefoxStudies = true;
-      DisableFeedbackCommands = true;
-
-      # disable password manager
-      PasswordManagerEnabled = false;
-      OfferToSaveLogins = false;
-      PrimaryPassword = false;
-      AutofillCreditCardEnabled = false;
-
-      # disable bookmark-toolbar
-      NoDefaultBookmarks = true;
-      DisplayBookmarksToolbar = "never";
-      DisplayMenuBar = "default-off";
-
-      Homepage.StartPage = "previous-session";
-      Homepage.Locked = true;
-
-      # disable DoH
-      DNSOverHTTPS.Enabled = false;
-      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;
-
-      Handlers.schemes =
-        let
-          handler = {
-            action = "useHelperApp";
-            ask = true;
-            handlers = [
-              {
-                name = "VDV PKPass DB Navigator Hook";
-                path = pkgs.writeShellScript "db-hook" ''
-                  #!/usr/bin/env bash
-
-                  if [[ "$1" == "dbnav:"* ]]; then
-                    url=$(echo -n $1 | base64)
-                    xdg-open "https://vdv-pkpass.magicalcodewit.ch/account/db_login/callback?url=$url"
-                  elif [[ "$1" == "bahnbonus:"* ]]; then
-                    url=$(echo -n $1 | base64)
-                    xdg-open "https://vdv-pkpass.magicalcodewit.ch/account/bahnbonus_login/callback?url=$url"
-                  else
-                    xdg-open "$1"
-                  fi
-                '';
-              }
-            ];
-          };
-        in
-        {
-          dbnav = handler;
-          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"
-              ];
-            };
-          };
-        }
-        // (
-          {
-            # 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
-          [
-            "menupanel"
-            "sponsorBlocker@ajay.app"
-          ] # SponsorBlock for YouTube - Skip Sponsorships
-          [
-            "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
-      );
-    };
-  };
-
-  wayland.windowManager.sway.config.startup = [
-    { command = "firefox"; }
-  ];
-
-  xdg = {
-    enable = true;
-    mime.enable = true;
-
-    #force hm to override existing mimeapps.list file
-    configFile."mimeapps.list".force = true;
-
-    mimeApps = {
-      enable = true;
-      defaultApplications = {
-        "x-scheme-handler/http" = "firefox.desktop";
-        "x-scheme-handler/https" = "firefox.desktop";
-        "x-scheme-handler/chrome" = "firefox.desktop";
-
-        "image/svg+xml" = "firefox.desktop";
-
-        "text/html" = "firefox.desktop";
-        "text/xml" = "firefox.desktop";
-      };
-    };
-  };
-
-}
diff --git a/config/home/katja/programs/fish.nix b/config/home/katja/programs/fish.nix
@@ -1,14 +0,0 @@
-{ pkgs, lib, ... }:
-
-{
-
-  home.persistence."/nix/persist/home/katja".directories = [
-    "fish/.local/share/fish"
-  ];
-
-  programs.fish = {
-    enable = true;
-    generateCompletions = true;
-  };
-
-}
diff --git a/config/home/katja/programs/fractal.nix b/config/home/katja/programs/fractal.nix
@@ -1,14 +0,0 @@
-{ pkgs, ... }:
-
-{
-
-  home = {
-    packages = [ pkgs.fractal ];
-
-    persistence."/nix/persist/home/katja".directories = [
-      "fractal/.local/share/fractal/"
-      "fractal/.cache/fractal/"
-    ];
-  };
-
-}
diff --git a/config/home/katja/programs/mcfly.nix b/config/home/katja/programs/mcfly.nix
@@ -1,16 +0,0 @@
-{ config, lib, ... }:
-
-{
-
-  home.persistence."/nix/persist/home/katja".directories = [
-    "mcfly/.local/share/mcfly"
-  ];
-
-  programs.mcfly = {
-    enable = true;
-    enableFishIntegration = true;
-    enableZshIntegration = true;
-    fuzzySearchFactor = 2;
-  };
-
-}
diff --git a/config/home/katja/programs/ssh.nix b/config/home/katja/programs/ssh.nix
@@ -1,29 +0,0 @@
-{ ... }:
-
-{
-
-
-  home.persistence."/nix/persist/home/katja".files = [
-    "ssh/.ssh/known_hosts"
-  ];
-
-  programs.ssh = {
-    enable = true;
-    compression = true;
-
-    controlMaster = "auto";
-    controlPersist = "2m";
-
-    matchBlocks = {
-      "ctucx-git" = {
-        user = "git";
-        hostname = "git.katja.wtf";
-      };
-      "zaphyra-git" = {
-        user = "git";
-        hostname = "git.zaphyra.eu";
-      };
-    };
-  };
-
-}
diff --git a/config/home/katja/programs/thunderbird.nix b/config/home/katja/programs/thunderbird.nix
@@ -1,51 +0,0 @@
-{
-  config,
-  pkgs,
-  lib,
-  ...
-}:
-
-{
-
-  home.packages = [ pkgs.thunderbird ];
-
-  home.persistence."/nix/persist/home/katja".directories = [
-    "thunderbird/.thunderbird/"
-    "thunderbird/.cache/thunderbird"
-  ];
-
-  systemd.user.services.thunderbird = lib.mkIf config.wayland.windowManager.sway.enable {
-    Unit.After = [ "graphical-session-pre.target" ];
-    Unit.PartOf = [ "graphical-session.target" ];
-
-    Service = {
-      Environment = "PATH=/run/wrappers/bin:/home/katja/.nix-profile/bin:/etc/profiles/per-user/katja/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin";
-      ExecStart = "${pkgs.thunderbird}/bin/thunderbird";
-      Restart = "always";
-      RestartSec = 5;
-    };
-
-    Install.WantedBy = [ "graphical-session.target" ];
-  };
-
-  wayland.windowManager.sway.config.startup = [
-    {
-      always = true;
-      command = "systemctl --user restart thunderbird";
-    }
-  ];
-
-  xdg = {
-    enable = true;
-    mime.enable = true;
-
-    #force hm to override existing mimeapps.list file
-    configFile."mimeapps.list".force = true;
-
-    mimeApps.enable = true;
-    mimeApps.defaultApplications = {
-      "x-scheme-handler/mailto" = "thunderbird.desktop";
-    };
-  };
-
-}
diff --git a/config/home/katja/programs/tuba.nix b/config/home/katja/programs/tuba.nix
@@ -1,21 +0,0 @@
-{ lib, pkgs, ... }:
-
-{
-
-  home.packages = [ pkgs.tuba ];
-
-  home.persistence."/nix/persist/home/katja".directories = [
-    "tuba/.cache/tuba"
-  ];
-
-  dconf.settings = {
-    "dev/geopjr/Tuba" = {
-      work-in-background = true;
-      dim-trivial-notifications = true;
-      group-push-notifications = true;
-      reply-to-old-post-reminder = false;
-      show-spoilers = true;
-    };
-  };
-
-}
diff --git a/config/home/katja/services/easyeffects.nix b/config/home/katja/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/katja/.nix-profile/bin:/etc/profiles/per-user/katja/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/common.nix b/config/home/zaphyra/common.nix
@@ -0,0 +1,39 @@
+{ lib, homeManagerModules, ... }:
+
+{
+
+  home = {
+    username = "zaphyra";
+    homeDirectory = "/home/zaphyra";
+
+    language = {
+      "base" = "en_US.UTF-8";
+      "time" = "de_DE.utf8";
+      "address" = "de_DE.utf8";
+      "monetary" = "de_DE.utf8";
+      "paper" = "de_DE.utf8";
+    };
+
+    stateVersion = lib.mkDefault "24.11";
+  };
+
+  imports = with homeManagerModules.zaphyra; [
+    programs.fish
+    programs.starship
+    programs.mcfly
+    programs.zoxide
+    programs.eza
+    programs.bat
+
+    programs.micro
+    programs.helix
+    programs.tmux
+    programs.htop
+
+    programs.deploymentUtilities
+    programs.shellUtilities
+
+    programs.nix-cleanup
+  ];
+
+}
diff --git a/config/home/zaphyra/configure/gnome.nix b/config/home/zaphyra/configure/gnome.nix
@@ -0,0 +1,187 @@
+{
+  inputs,
+  lib,
+  pkgs,
+  ...
+}:
+
+let
+  nixStd = inputs.nixStd.lib;
+
+in
+{
+
+  manual.html.enable = true;
+
+  home.sessionVariables = {
+    QT_QPA_PLATFORMTHEME = "gnome";
+  };
+
+  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"
+  ];
+
+  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
+    ]);
+
+  gtk = {
+    enable = true;
+
+    iconTheme.package = pkgs.adwaita-colors-icon-theme;
+    iconTheme.name = "Adwaita-green";
+
+    gtk3.extraConfig = {
+      gtk-application-prefer-dark-theme = 1;
+      gtk-theme-name = "adw-gtk3-dark";
+    };
+  };
+
+  # Use `dconf watch /` to track stateful changes you are doing and store them here.
+  dconf.settings =
+    with inputs.homeManager.lib.hm.gvariant;
+    let
+      numWorkspaces = 7;
+      workspaces = (
+        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
+      );
+    in
+    {
+      "org/gnome/mutter" = {
+        edge-tiling = true;
+        dynamic-workspaces = false;
+        # Enable fractional scaling
+        experimental-features = [ "scale-monitor-framebuffer" ];
+      };
+
+      "org/gnome/desktop/wm/preferences" = {
+        button-layout = "close:appmenu";
+        auto-raise = false;
+        focus-mode = "sloppy";
+        num-workspaces = lib.lists.last workspaces;
+        workspace-names = [
+          "Main"
+          "Mail"
+          "Term"
+        ];
+      };
+
+      "org/gnome/desktop/wm/keybindings" =
+        builtins.listToAttrs (
+          builtins.concatMap (v: [
+            {
+              name = "switch-to-workspace-${toString v}";
+              value = [ "<Super>${toString v}" ];
+            }
+            {
+              name = "move-to-workspace-${toString v}";
+              value = [ "<Super><Shift>${toString v}" ];
+            }
+          ]) workspaces
+        )
+        // {
+          switch-input-source = [ "<Control><Super>space" ];
+          switch-input-source-backward = [ "<Shift><Control><Super>space" ];
+        };
+
+      "org/gnome/shell/keybindings" = builtins.listToAttrs (
+        map (v: {
+          name = "switch-to-application-${toString v}";
+          value = [ ];
+        }) workspaces
+      );
+      "org/gnome/shell" = {
+        disable-extension-version-validation = true;
+        disable-user-extensions = false;
+        enabled-extensions = with pkgs.gnomeExtensions; [
+          battery-time-percentage-compact.extensionUuid
+          caffeine.extensionUuid
+        ];
+        favorite-apps = [
+          "org.gnome.Nautilus.desktop"
+          "firefox.desktop"
+          "thunderbird.desktop"
+          "org.gnome.Fractal.desktop"
+          "dev.geopjr.Tuba.desktop"
+          "org.gnome.Calendar.desktop"
+          "io.github.mrvladus.List.desktop"
+          "org.gnome.Podcasts.desktop"
+          "com.mitchellh.ghostty.desktop"
+          "org.gnome.Settings.desktop"
+        ];
+      };
+
+      "org/gnome/settings-daemon/plugins/media-keys"."custom-keybindings" = [
+        "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/"
+      ];
+      "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0" = {
+        name = "Start Terminal";
+        command = "ghostty";
+        binding = "<Super>Return";
+      };
+
+      "org/gnome/settings-daemon/plugins/color".night-light-enabled = true;
+      "org/gnome/settings-daemon/plugins/power".sleep-inactive-ac-type = "nothing";
+
+      "org/gnome/desktop/a11y".always-show-universal-access-status = false;
+      "org/gnome/desktop/privacy".remember-recent-files = false;
+      "org/gnome/desktop/interface" = {
+        color-scheme = "prefer-dark";
+        accent-color = "green";
+        enable-hot-corners = false;
+        show-battery-percentage = true;
+      };
+
+      "org/gnome/desktop/input-sources".sources = [
+        (mkTuple [
+          "xkb"
+          "us+mac"
+        ])
+        (mkTuple [
+          "xkb"
+          "de"
+        ])
+        (mkTuple [
+          "xkb"
+          "ru+mac"
+        ])
+      ];
+      "org/gnome/desktop/background" = {
+        picture-uri = "file://${pkgs.nixos-artwork.wallpapers.simple-blue.gnomeFilePath}";
+        picture-uri-dark = "file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray.gnomeFilePath}";
+      };
+      "org/gnome/desktop/screensaver" = {
+        picture-uri = "file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray.gnomeFilePath}";
+        primary-color = "#3465a4";
+        secondary-color = "#000000";
+      };
+    };
+
+}
diff --git a/config/home/katja/configure/xdg.nix b/config/home/zaphyra/configure/xdg.nix
diff --git a/config/home/katja/gnomeExtensions/bluetoothBatteryMeter.nix b/config/home/zaphyra/gnomeExtensions/bluetoothBatteryMeter.nix
diff --git a/config/home/katja/gnomeExtensions/dash-to-dock.nix b/config/home/zaphyra/gnomeExtensions/dash-to-dock.nix
diff --git a/config/home/katja/gnomeExtensions/emoji-copy.nix b/config/home/zaphyra/gnomeExtensions/emoji-copy.nix
diff --git a/config/home/katja/gnomeExtensions/just-perfection.nix b/config/home/zaphyra/gnomeExtensions/just-perfection.nix
diff --git a/config/home/katja/gnomeExtensions/pip-on-top.nix b/config/home/zaphyra/gnomeExtensions/pip-on-top.nix
diff --git a/config/home/katja/gnomeExtensions/search-light.nix b/config/home/zaphyra/gnomeExtensions/search-light.nix
diff --git a/config/home/katja/gnomeExtensions/space-bar.nix b/config/home/zaphyra/gnomeExtensions/space-bar.nix
diff --git a/config/home/zaphyra/impermanence.nix b/config/home/zaphyra/impermanence.nix
@@ -0,0 +1,22 @@
+{ ... }:
+
+{
+
+  home.persistence."/nix/persist/home/zaphyra" = {
+    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")
+    ];
+  };
+
+}+
\ No newline at end of file
diff --git a/config/home/katja/programs/alacritty.nix b/config/home/zaphyra/programs/alacritty.nix
diff --git a/config/home/katja/programs/ansible.nix b/config/home/zaphyra/programs/ansible.nix
diff --git a/config/home/katja/programs/apostrophe.nix b/config/home/zaphyra/programs/apostrophe.nix
diff --git a/config/home/katja/programs/bat.nix b/config/home/zaphyra/programs/bat.nix
diff --git a/config/home/katja/programs/bitwarden-cli.nix b/config/home/zaphyra/programs/bitwarden-cli.nix
diff --git a/config/home/katja/programs/celluloid.nix b/config/home/zaphyra/programs/celluloid.nix
diff --git a/config/home/katja/programs/deploymentUtilities.nix b/config/home/zaphyra/programs/deploymentUtilities.nix
diff --git a/config/home/zaphyra/programs/errands.nix b/config/home/zaphyra/programs/errands.nix
@@ -0,0 +1,11 @@
+{ lib, pkgs, ... }:
+
+{
+
+  home.packages = [ pkgs.errands ];
+
+  home.persistence."/nix/persist/home/zaphyra".directories = [
+    "tuba/.local/share/errands"
+  ];
+
+}
diff --git a/config/home/katja/programs/eza.nix b/config/home/zaphyra/programs/eza.nix
diff --git a/config/home/zaphyra/programs/firefox.nix b/config/home/zaphyra/programs/firefox.nix
@@ -0,0 +1,317 @@
+{
+  inputs,
+  pkgs,
+  lib,
+  ...
+}:
+
+{
+
+  home.sessionVariables = {
+    BROWSER = "firefox";
+  };
+
+  home.file."firefox-gnome-theme" = {
+    source = inputs.firefoxGnomeTheme;
+    target = ".mozilla/firefox/zaphyra/chrome/firefox-gnome-theme";
+  };
+
+  home.persistence."/nix/persist/home/zaphyra".directories = [
+    "firefox/.mozilla/firefox/"
+    "firefox/.cache/mozilla/firefox"
+  ];
+
+  programs.firefox = {
+    enable = true;
+    package = pkgs.firefox;
+    nativeMessagingHosts = [ pkgs.ff2mpv-rust ];
+
+    profiles.zaphyra = {
+      id = 0;
+      isDefault = true;
+
+      settings = {
+        # required for firefox-gnome-theme
+        "browser.toolbars.bookmarks.visibility" = "never";
+        "browser.tabs.drawInTitlebar" = true;
+        "browser.theme.dark-private-windows" = false;
+        "browser.uidensity" = 0;
+        "svg.context-properties.content.enabled" = true;
+        "toolkit.legacyUserProfileCustomizations.stylesheets" = true;
+      };
+
+      userChrome = ''
+        @import "firefox-gnome-theme/userChrome.css";
+      '';
+
+      userContent = ''
+        @import "firefox-gnome-theme/userContent.css";
+      '';
+
+      search.force = true; # Required to prevent search engine symlink being overwritten. See https://github.com/nix-community/home-manager/issues/3698
+      search.engines = {
+        "Noogle" = {
+          icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
+          definedAliases = [ "@noogle" ];
+          urls = [ { template = "https://noogle.dev/q?term={searchTerms}"; } ];
+        };
+
+        "NixOS Options" = {
+          icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
+          definedAliases = [ "@nixos" ];
+          urls = [ { template = "https://search.nixos.org/options?query={searchTerms}"; } ];
+        };
+
+        "Nix Packages" = {
+          icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
+          definedAliases = [ "@nixpkgs" ];
+          urls = [ { template = "https://search.nixos.org/packages?query={searchTerms}"; } ];
+        };
+      };
+    };
+
+    policies = {
+      DisableSetDesktopBackground = true;
+
+      # disable tracking bullshit
+      DisableTelemetry = true;
+      DisablePocket = true;
+      DisableFirefoxStudies = true;
+      DisableFeedbackCommands = true;
+
+      # disable password manager
+      PasswordManagerEnabled = false;
+      OfferToSaveLogins = false;
+      PrimaryPassword = false;
+      AutofillCreditCardEnabled = false;
+
+      # disable bookmark-toolbar
+      NoDefaultBookmarks = true;
+      DisplayBookmarksToolbar = "never";
+      DisplayMenuBar = "default-off";
+
+      Homepage.StartPage = "previous-session";
+      Homepage.Locked = true;
+
+      # disable DoH
+      DNSOverHTTPS.Enabled = false;
+      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;
+
+      Handlers.schemes =
+        let
+          handler = {
+            action = "useHelperApp";
+            ask = true;
+            handlers = [
+              {
+                name = "VDV PKPass DB Navigator Hook";
+                path = pkgs.writeShellScript "db-hook" ''
+                  #!/usr/bin/env bash
+
+                  if [[ "$1" == "dbnav:"* ]]; then
+                    url=$(echo -n $1 | base64)
+                    xdg-open "https://vdv-pkpass.magicalcodewit.ch/account/db_login/callback?url=$url"
+                  elif [[ "$1" == "bahnbonus:"* ]]; then
+                    url=$(echo -n $1 | base64)
+                    xdg-open "https://vdv-pkpass.magicalcodewit.ch/account/bahnbonus_login/callback?url=$url"
+                  else
+                    xdg-open "$1"
+                  fi
+                '';
+              }
+            ];
+          };
+        in
+        {
+          dbnav = handler;
+          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"
+              ];
+            };
+          };
+        }
+        // (
+          {
+            # 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
+          [
+            "menupanel"
+            "sponsorBlocker@ajay.app"
+          ] # SponsorBlock for YouTube - Skip Sponsorships
+          [
+            "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
+      );
+    };
+  };
+
+  wayland.windowManager.sway.config.startup = [
+    { command = "firefox"; }
+  ];
+
+  xdg = {
+    enable = true;
+    mime.enable = true;
+
+    #force hm to override existing mimeapps.list file
+    configFile."mimeapps.list".force = true;
+
+    mimeApps = {
+      enable = true;
+      defaultApplications = {
+        "x-scheme-handler/http" = "firefox.desktop";
+        "x-scheme-handler/https" = "firefox.desktop";
+        "x-scheme-handler/chrome" = "firefox.desktop";
+
+        "image/svg+xml" = "firefox.desktop";
+
+        "text/html" = "firefox.desktop";
+        "text/xml" = "firefox.desktop";
+      };
+    };
+  };
+
+}
diff --git a/config/home/zaphyra/programs/fish.nix b/config/home/zaphyra/programs/fish.nix
@@ -0,0 +1,14 @@
+{ pkgs, lib, ... }:
+
+{
+
+  home.persistence."/nix/persist/home/zaphyra".directories = [
+    "fish/.local/share/fish"
+  ];
+
+  programs.fish = {
+    enable = true;
+    generateCompletions = true;
+  };
+
+}
diff --git a/config/home/zaphyra/programs/fractal.nix b/config/home/zaphyra/programs/fractal.nix
@@ -0,0 +1,14 @@
+{ pkgs, ... }:
+
+{
+
+  home = {
+    packages = [ pkgs.fractal ];
+
+    persistence."/nix/persist/home/zaphyra".directories = [
+      "fractal/.local/share/fractal/"
+      "fractal/.cache/fractal/"
+    ];
+  };
+
+}
diff --git a/config/home/katja/programs/ghostty.nix b/config/home/zaphyra/programs/ghostty.nix
diff --git a/config/home/katja/programs/git.nix b/config/home/zaphyra/programs/git.nix
diff --git a/config/home/katja/programs/gpg.nix b/config/home/zaphyra/programs/gpg.nix
diff --git a/config/home/katja/programs/helix.nix b/config/home/zaphyra/programs/helix.nix
diff --git a/config/home/katja/programs/htop.nix b/config/home/zaphyra/programs/htop.nix
diff --git a/config/home/katja/programs/imv.nix b/config/home/zaphyra/programs/imv.nix
diff --git a/config/home/katja/programs/javascript.nix b/config/home/zaphyra/programs/javascript.nix
diff --git a/config/home/katja/programs/libreoffice.nix b/config/home/zaphyra/programs/libreoffice.nix
diff --git a/config/home/zaphyra/programs/mcfly.nix b/config/home/zaphyra/programs/mcfly.nix
@@ -0,0 +1,16 @@
+{ config, lib, ... }:
+
+{
+
+  home.persistence."/nix/persist/home/zaphyra".directories = [
+    "mcfly/.local/share/mcfly"
+  ];
+
+  programs.mcfly = {
+    enable = true;
+    enableFishIntegration = true;
+    enableZshIntegration = true;
+    fuzzySearchFactor = 2;
+  };
+
+}
diff --git a/config/home/katja/programs/micro.nix b/config/home/zaphyra/programs/micro.nix
diff --git a/config/home/katja/programs/mpv.nix b/config/home/zaphyra/programs/mpv.nix
diff --git a/config/home/katja/programs/nautilus.nix b/config/home/zaphyra/programs/nautilus.nix
diff --git a/config/home/katja/programs/nim.nix b/config/home/zaphyra/programs/nim.nix
diff --git a/config/home/katja/programs/nix-cleanup.nix b/config/home/zaphyra/programs/nix-cleanup.nix
diff --git a/config/home/katja/programs/ocrmypdf.nix b/config/home/zaphyra/programs/ocrmypdf.nix
diff --git a/config/home/katja/programs/paper-plane.nix b/config/home/zaphyra/programs/paper-plane.nix
diff --git a/config/home/katja/programs/papers.nix b/config/home/zaphyra/programs/papers.nix
diff --git a/config/home/katja/programs/password-store.nix b/config/home/zaphyra/programs/password-store.nix
diff --git a/config/home/katja/programs/pdfarranger.nix b/config/home/zaphyra/programs/pdfarranger.nix
diff --git a/config/home/katja/programs/phockup.nix b/config/home/zaphyra/programs/phockup.nix
diff --git a/config/home/katja/programs/shellUtilities.nix b/config/home/zaphyra/programs/shellUtilities.nix
diff --git a/config/home/zaphyra/programs/ssh.nix b/config/home/zaphyra/programs/ssh.nix
@@ -0,0 +1,25 @@
+{ ... }:
+
+{
+
+
+  home.persistence."/nix/persist/home/zaphyra".files = [
+    "ssh/.ssh/known_hosts"
+  ];
+
+  programs.ssh = {
+    enable = true;
+    compression = true;
+
+    controlMaster = "auto";
+    controlPersist = "2m";
+
+    matchBlocks = {
+      "zaphyra-git" = {
+        user = "git";
+        hostname = "git.zaphyra.eu";
+      };
+    };
+  };
+
+}
diff --git a/config/home/katja/programs/starship.nix b/config/home/zaphyra/programs/starship.nix
diff --git a/config/home/katja/programs/texlive.nix b/config/home/zaphyra/programs/texlive.nix
diff --git a/config/home/zaphyra/programs/thunderbird.nix b/config/home/zaphyra/programs/thunderbird.nix
@@ -0,0 +1,51 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+
+{
+
+  home.packages = [ pkgs.thunderbird ];
+
+  home.persistence."/nix/persist/home/zaphyra".directories = [
+    "thunderbird/.thunderbird/"
+    "thunderbird/.cache/thunderbird"
+  ];
+
+  systemd.user.services.thunderbird = lib.mkIf config.wayland.windowManager.sway.enable {
+    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";
+      Restart = "always";
+      RestartSec = 5;
+    };
+
+    Install.WantedBy = [ "graphical-session.target" ];
+  };
+
+  wayland.windowManager.sway.config.startup = [
+    {
+      always = true;
+      command = "systemctl --user restart thunderbird";
+    }
+  ];
+
+  xdg = {
+    enable = true;
+    mime.enable = true;
+
+    #force hm to override existing mimeapps.list file
+    configFile."mimeapps.list".force = true;
+
+    mimeApps.enable = true;
+    mimeApps.defaultApplications = {
+      "x-scheme-handler/mailto" = "thunderbird.desktop";
+    };
+  };
+
+}
diff --git a/config/home/katja/programs/tmux.nix b/config/home/zaphyra/programs/tmux.nix
diff --git a/config/home/zaphyra/programs/tuba.nix b/config/home/zaphyra/programs/tuba.nix
@@ -0,0 +1,21 @@
+{ lib, pkgs, ... }:
+
+{
+
+  home.packages = [ pkgs.tuba ];
+
+  home.persistence."/nix/persist/home/zaphyra".directories = [
+    "tuba/.cache/tuba"
+  ];
+
+  dconf.settings = {
+    "dev/geopjr/Tuba" = {
+      work-in-background = true;
+      dim-trivial-notifications = true;
+      group-push-notifications = true;
+      reply-to-old-post-reminder = false;
+      show-spoilers = true;
+    };
+  };
+
+}
diff --git a/config/home/katja/programs/typst.nix b/config/home/zaphyra/programs/typst.nix
diff --git a/config/home/katja/programs/yt-dlp.nix b/config/home/zaphyra/programs/yt-dlp.nix
diff --git a/config/home/katja/programs/zathura.nix b/config/home/zaphyra/programs/zathura.nix
diff --git a/config/home/katja/programs/zoxide.nix b/config/home/zaphyra/programs/zoxide.nix
diff --git a/config/home/katja/programs/zsh.nix b/config/home/zaphyra/programs/zsh.nix
diff --git a/config/home/zaphyra/services/easyeffects.nix b/config/home/zaphyra/services/easyeffects.nix
@@ -0,0 +1,28 @@
+{ 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/katja/services/mako.nix b/config/home/zaphyra/services/mako.nix
diff --git a/config/home/katja/services/waybar.nix b/config/home/zaphyra/services/waybar.nix
diff --git a/config/home/katja/services/wlsunset.nix b/config/home/zaphyra/services/wlsunset.nix
diff --git a/config/nixos/modules/filesystem/impermanence.nix b/config/nixos/modules/filesystem/impermanence.nix
@@ -141,7 +141,7 @@ in
           ] ++ cfg.system.files;
         };
 
-        #katja: hack to persist `/var/lib/private/<service>` (see https://github.com/nix-community/impermanence/issues/213)
+        #zaphyra: hack to persist `/var/lib/private/<service>` (see https://github.com/nix-community/impermanence/issues/213)
         system.activationScripts = {
           "createPersistentStorageDirs".deps = [ "var-lib-private-permissions" "users" "groups" ];
           "var-lib-private-permissions" = {
diff --git a/config/nixos/modules/presets/katja/enable.nix b/config/nixos/modules/presets/katja/enable.nix
@@ -1,133 +0,0 @@
-{
-  povSelf,
-  pkgs,
-  lib,
-  config,
-  hostConfig,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath povSelf config;
-
-in
-{
-
-  option = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf cfg {
-    sops.secrets.acmeTSIGKey = { };
-
-    users.users.root = {
-      extraGroups = [ "ssh" ];
-      openssh.authorizedKeys.keys = [
-        (builtins.readFile "${pkgs.zaphyra-website}/ssh_pubkey.asc")
-      ];
-    };
-
-    dns.zones."zaphyra.eu".subdomains."${lib.removeSuffix ".zaphyra.eu" config.networking.fqdn}" =
-      lib.mkIf (hostConfig ? networking)
-        (
-          let
-            networkCfg = hostConfig.networking;
-          in
-          {
-            AAAA = lib.mkIf ((networkCfg ? ip6Address) && !networkCfg.ip6IsPrivate) [ networkCfg.ip6Address ];
-            A = lib.mkIf ((networkCfg ? ip4Address) && !networkCfg.ip4IsPrivate) [ networkCfg.ip4Address ];
-          }
-        );
-
-    modules = {
-      presets.katja = {
-        syncthing.enable = lib.mkDefault true;
-      };
-
-      hardware.smartcard.enable = lib.mkDefault config.modules.presets.graphical.enable;
-
-      services = {
-        keyd.enable = lib.mkDefault config.modules.presets.graphical.enable;
-        openssh = {
-          enable = lib.mkDefault true;
-          enableRSASupport = lib.mkDefault true;
-        };
-        prometheusExporters.enable = lib.mkDefault true;
-        vnstat.enable = true;
-        vnstat.vnstati.enable = true;
-      };
-    };
-
-    modules.filesystem.impermanence.system.dirs = [ "/var/lib/acme" ];
-    security.acme = {
-      acceptTerms = true;
-      defaults = {
-        email = "letsencrypt@zaphyra.eu";
-        keyType = "ec384";
-        dnsProvider = "rfc2136";
-        environmentFile = pkgs.writeText "acme-dns-env" ''
-          RFC2136_NAMESERVER=morio.infra.zaphyra.eu
-          RFC2136_TSIG_KEY=acme-nix-${config.networking.hostName}
-          RFC2136_TSIG_ALGORITHM=hmac-sha384
-        '';
-        credentialFiles = {
-          RFC2136_TSIG_SECRET_FILE = config.sops.secrets.acmeTSIGKey.path;
-        };
-      };
-      certs."${config.networking.fqdn}" = {
-        group = lib.mkIf config.services.nginx.enable "nginx";
-        extraDomainNames = (
-          config.services.nginx.virtualHosts
-          |> lib.mapAttrsToList (
-            key: config: [
-              (if config ? serverAliases then config.serverAliases else [ ])
-              key
-            ]
-          )
-          |> lib.flatten
-        );
-      };
-    };
-
-    services = {
-      timesyncd.enable = lib.mkDefault true;
-      fstrim.enable = lib.mkDefault true;
-
-      journald.extraConfig = "SystemMaxUse=2.5G";
-
-      logind.killUserProcesses = lib.mkDefault true;
-
-      nginx = {
-        enable = lib.mkDefault true;
-        recommendedGzipSettings = true;
-        recommendedOptimisation = true;
-        recommendedProxySettings = true;
-        recommendedTlsSettings = true;
-        commonHttpConfig = ''
-          server_names_hash_bucket_size 64;
-          charset utf-8;
-
-          access_log off;
-        '';
-
-        virtualHosts."${config.networking.fqdn}" = {
-          useACMEHost = "${config.networking.fqdn}";
-          forceSSL = true;
-          kTLS = true;
-          default = true;
-        };
-      };
-    };
-
-    networking.firewall.allowedTCPPorts = [
-      80
-      443
-    ];
-
-    environment.systemPackages = with pkgs; [
-      ghostty.terminfo
-    ];
-  };
-
-}
diff --git a/config/nixos/modules/presets/katja/router/enable.nix b/config/nixos/modules/presets/katja/router/enable.nix
@@ -1,93 +0,0 @@
-{
-  inputs,
-  pov,
-  pkgs,
-  lib,
-  config,
-  hostConfig,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath pov config;
-
-in
-{
-
-  option = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf cfg.enable {
-
-    environment.systemPackages = [ pkgs.wireguard-tools ];
-
-    boot.initrd.kernelModules = [ "jool" ];
-
-    hardware.firmware = [
-      (pkgs.runCommandNoCC "rtl8168h-firmware" { } ''
-        mkdir -p $out/lib/firmware/rtl_nic
-        cp ${pkgs.linux-firmware}/lib/firmware/rtl_nic/rtl8168h-2.fw $out/lib/firmware/rtl_nic/rtl8168h-2.fw
-      '')
-    ];
-
-    modules.presets.katja.router = {
-      systemd-networkd = true;
-      pppd = true;
-    };
-
-    networking = {
-      useNetworkd = true;
-      useDHCP = false;
-      firewall.enable = false;
-
-      nftables.enable = true;
-      nftables.rulesetFile = inputs.self.resources.katja.routerRuleset;
-
-      jool.enable = true;
-      jool.nat64.default = { };
-    };
-
-    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'
-          }
-        }
-
-        policy.add(function (request, query)
-          return policy.FORWARD(dns_providers[math.random(1, #dns_providers)])
-        end)
-      '';
-    };
-
-  };
-
-}
diff --git a/config/nixos/modules/presets/katja/router/systemd-networkd.nix b/config/nixos/modules/presets/katja/router/systemd-networkd.nix
@@ -1,246 +0,0 @@
-{
-  povSelf,
-  pkgs,
-  lib,
-  config,
-  hostConfig,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath povSelf config;
-
-in
-{
-
-  option = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf cfg {
-    sops.secrets.wireguardPrivKey = {
-      mode = "640";
-      owner = "root";
-      group = "systemd-network";
-    };
-
-    systemd.network = {
-      enable = true;
-      wait-online.enable = false;
-
-      config.networkConfig = {
-        IPv4Forwarding = true;
-        IPv6Forwarding = true;
-      };
-
-      links."5-dtagdsl" = {
-        matchConfig.PermanentMACAddress = "d0:37:45:06:de:de";
-        linkConfig.Name = "dtagdsl";
-      };
-
-      links."5-iphone" = {
-        matchConfig.PermanentMACAddress = "aa:ab:b5:18:95:d9";
-        linkConfig.Name = "iphone";
-      };
-
-      netdevs."20-brlan" = {
-        netdevConfig = {
-          Kind = "bridge";
-          Name = "brlan";
-        };
-      };
-
-      netdevs."10-wg-novus" = {
-        netdevConfig = {
-          Kind = "wireguard";
-          Name = "wg-novus";
-        };
-
-        wireguardConfig = {
-          PrivateKeyFile = config.sops.secrets.wireguardPrivKey.path;
-          ListenPort = 51820;
-          FirewallMark = 51820;
-        };
-
-        wireguardPeers = [
-          {
-            Endpoint = "novus.infra.zaphyra.eu:51820";
-            PublicKey = "J+kRRNU65JGc0yk04v6P3tFwHSQOIfq8EkfD2gFupg4=";
-            AllowedIPs = [ "::/0" ];
-            PersistentKeepalive = 10;
-          }
-        ];
-      };
-
-      networks = {
-        "5-dtagdsl" = {
-          matchConfig.Name = "dtagdsl";
-
-          address = [ "192.168.1.2/24" ];
-
-          linkConfig.RequiredForOnline = false;
-          networkConfig.LinkLocalAddressing = false;
-        };
-
-        "5-enp1s0" = {
-          matchConfig.Name = "enp1s0";
-
-          bridge = [ "brlan" ];
-          networkConfig.ConfigureWithoutCarrier = true;
-        };
-
-        "5-iphone" = {
-          matchConfig.Name = "iphone";
-
-          networkConfig.DHCP = true;
-        };
-
-        "10-ppp-dtagdsl" = {
-          matchConfig.Type = "ppp";
-          linkConfig.RequiredForOnline = "routable";
-
-          networkConfig = {
-            KeepConfiguration = true;
-            IPv6AcceptRA = true;
-            DHCP = "ipv6";
-          };
-
-          ipv6AcceptRAConfig = {
-            UseDNS = false;
-          };
-
-          ipv6SendRAConfig = {
-            Managed = true;
-          };
-
-          dhcpV6Config = {
-            WithoutRA = "solicit";
-            PrefixDelegationHint = "::/56";
-            IAID = 0;
-            UseDNS = false;
-          };
-        };
-
-        "10-wg-novus" = {
-          matchConfig.Name = "wg-novus";
-
-          linkConfig = {
-            RequiredForOnline = false;
-          };
-
-          routes = [
-            {
-              Destination = "::/0";
-              Table = "1234";
-            }
-          ];
-        };
-
-        "20-brlan" = {
-          matchConfig = {
-            Name = "brlan";
-            Driver = "bridge";
-          };
-
-          linkConfig = {
-            RequiredForOnline = "routable";
-          };
-
-          address = [
-            "${hostConfig.networking.ip4Address}/${toString hostConfig.networking.ip4PrefixLength}"
-            "${hostConfig.networking.ip6Address}/${toString hostConfig.networking.ip6PrefixLength}"
-          ];
-
-          routingPolicyRules = [
-            {
-              From = "2a03:4000:4d:5e:acab::/112";
-              Table = 254;
-              Priority = 1900;
-              SuppressPrefixLength = 0;
-            }
-            {
-              From = "2a03:4000:4d:5e:acab::/112";
-              Table = 1234;
-              Priority = 2000;
-            }
-          ];
-
-          networkConfig = {
-            ConfigureWithoutCarrier = true;
-
-            DHCPPrefixDelegation = true;
-            IPv6PrivacyExtensions = false;
-            IPv6AcceptRA = false;
-            IPv6SendRA = true;
-
-            DHCPServer = true;
-            DNS = hostConfig.networking.ip4Address;
-          };
-
-          dhcpPrefixDelegationConfig = {
-            UplinkInterface = "ppp-dtagdsl";
-            Announce = true;
-            SubnetId = 0;
-            Token = "::1";
-          };
-
-          ipv6SendRAConfig = {
-            RouterLifetimeSec = 1800;
-            EmitDNS = true;
-            DNS = "_link_local";
-          };
-
-          ipv6PREF64Prefixes = [
-            {
-              Prefix = "64:ff9b::/96";
-            }
-          ];
-
-          dhcpServerConfig = {
-            PersistLeases = true;
-            PoolOffset = 100;
-            PoolSize = 100;
-            EmitDNS = true;
-            DNS = hostConfig.networking.ip4Address;
-            IPv6OnlyPreferredSec = 300;
-          };
-
-          dhcpServerStaticLeases = [
-            {
-              # accesspoint
-              MACAddress = "48:a9:8a:8e:dd:0b";
-              Address = "10.0.0.2";
-            }
-            {
-              # pbx
-              MACAddress = "34:31:c4:46:88:31";
-              Address = "10.0.0.3";
-            }
-            {
-              # scanner
-              MACAddress = "5c:f3:70:b9:35:9c";
-              Address = "10.0.0.4";
-            }
-            {
-              # printer
-              MACAddress = "70:77:81:2a:e7:96";
-              Address = "10.0.0.5";
-            }
-            {
-              # nix snowflake (wled)
-              MACAddress = "28:37:2f:6a:e7:14";
-              Address = "10.0.0.6";
-            }
-            {
-              # katja x13
-              MACAddress = "04:CF:4B:76:93:55";
-              Address = "10.0.0.10";
-            }
-          ];
-        };
-      };
-    };
-  };
-
-}
diff --git a/config/nixos/modules/presets/katja/smarthome/enable.nix b/config/nixos/modules/presets/katja/smarthome/enable.nix
@@ -1,32 +0,0 @@
-{
-  inputs,
-  pov,
-  pkgs,
-  lib,
-  config,
-  hostConfig,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath pov config;
-
-in
-{
-
-  option = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf cfg.enable {
-    modules.presets.katja.smarthome = {
-      mosqitto = true;
-      zigbee2mqtt = true;
-      mqttWebUI = true;
-      influxdb2 = true;
-      telegraf = true;
-    };
-  };
-
-}
diff --git a/config/nixos/modules/presets/katja/smarthome/mqttWebUI.nix b/config/nixos/modules/presets/katja/smarthome/mqttWebUI.nix
@@ -1,71 +0,0 @@
-{
-  inputs,
-  povSelf,
-  pkgs,
-  lib,
-  config,
-  hostConfig,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath povSelf config;
-
-in
-{
-
-  option = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf cfg {
-    dns.zones."zaphyra.eu".subdomains."smart.home.infra".AAAA = [ hostConfig.networking.ip6Address ];
-
-    services.nginx = {
-      enable = true;
-      virtualHosts."smart.${config.networking.domain}" = {
-        useACMEHost = config.networking.fqdn;
-        forceSSL = true;
-        kTLS = true;
-        extraConfig = ''
-          ssl_client_certificate ${inputs.self.resources.katja.rootCA};
-          ssl_verify_client optional;
-        '';
-        locations = {
-          "/" = {
-            root = "${
-              pkgs.buildEnv {
-                name = "mqtt-webui-env";
-                paths = [
-                  pkgs.mqtt-webui
-                  (pkgs.writeTextDir "extra.css" (builtins.toJSON inputs.self.resources.katja.mqttWebUI.extra-css))
-                  (pkgs.writeTextDir "config.json" (
-                    builtins.toJSON (import inputs.self.resources.katja.mqttWebUI.config)
-                  ))
-                ];
-              }
-            }/";
-            extraConfig = ''
-              location ~ ^/(?!(favicon-512x512\.png|manifest\.json)) {
-                if ($ssl_client_verify != SUCCESS) {
-                    return 403;
-                }
-              }
-            '';
-          };
-          "/mqtt" = {
-            proxyPass = "http://[::1]:9005";
-            proxyWebsockets = true;
-            extraConfig = ''
-              if ($ssl_client_verify != SUCCESS) {
-                  return 403;
-              }
-            '';
-          };
-        };
-      };
-    };
-  };
-
-}
diff --git a/config/nixos/modules/presets/katja/smarthome/zigbee2mqtt.nix b/config/nixos/modules/presets/katja/smarthome/zigbee2mqtt.nix
@@ -1,122 +0,0 @@
-{
-  inputs,
-  povSelf,
-  pkgs,
-  lib,
-  config,
-  hostConfig,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath povSelf config;
-
-in
-{
-
-  option = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf cfg {
-    dns.zones."zaphyra.eu".subdomains."zigbee2mqtt.home.infra".AAAA = [
-      hostConfig.networking.ip6Address
-    ];
-
-    modules.filesystem.impermanence.system.dirs = [
-      {
-        directory = "/var/lib/zigbee2mqtt";
-        mode = "0770";
-        user = "zigbee2mqtt";
-        group = "zigbee2mqtt";
-      }
-    ];
-
-    sops.secrets."zigbee2mqttSecrets.yaml" = {
-      owner = "zigbee2mqtt";
-      key = "zigbee2mqttSecrets";
-    };
-
-    systemd.services.zigbee2mqtt = {
-      requires = [ "mosquitto.service" ];
-      after = [ "mosquitto.service" ];
-      serviceConfig = {
-        Restart = lib.mkForce "always";
-        RuntimeMaxSec = "1d";
-      };
-    };
-
-    services = {
-      udev.extraRules = ''
-        SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{serial}=="00_12_4B_00_25_9B_C1_FC", SYMLINK+="zigbee0"
-        ATTR{idVendor}=="0451", ATTR{idProduct}=="16a8", ENV{ID_MM_DEVICE_IGNORE}="1"
-        SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="zigbee0"
-      '';
-
-      nginx = {
-        enable = true;
-        virtualHosts."zigbee2mqtt.${config.networking.domain}" = {
-          useACMEHost = config.networking.fqdn;
-          forceSSL = true;
-          kTLS = true;
-          extraConfig = ''
-            ssl_client_certificate ${inputs.self.resources.katja.rootCA};
-            ssl_verify_client on;
-          '';
-          locations."/" = {
-            proxyPass = "http://[::1]:${toString config.services.zigbee2mqtt.settings.frontend.port}";
-            proxyWebsockets = true;
-          };
-        };
-      };
-
-      zigbee2mqtt = {
-        enable = true;
-        package = pkgs.zigbee2mqtt;
-        settings = {
-          homeassistant = false;
-          permit_join = false;
-
-          mqtt = {
-            base_topic = "zigbee2mqtt";
-            server = "mqtt://[::1]";
-          };
-
-          serial = {
-            port = "/dev/zigbee0";
-            disable_led = true;
-          };
-
-          frontend = {
-            port = 8422;
-            host = "::1";
-          };
-
-          advanced = {
-            log_level = "info";
-            log_output = [ "console" ];
-            channel = 26;
-            network_key = "!${config.sops.secrets."zigbee2mqttSecrets.yaml".path} network_key";
-          };
-
-          device_options.retain = true;
-          devices = {
-            "0x84fd27fffe6b9ddd".friendly_name = "ikea_lamp_hallway";
-            "0x94deb8fffe52e639".friendly_name = "ikea_lamp_rgb";
-            "0x84fd27fffe44369e".friendly_name = "ikea_lamp_sleepingroom";
-            "0x84fd27fffea515fc".friendly_name = "ikea_lamp_livingroom";
-
-            "0xa4c138da0f6d23de".friendly_name = "tuya_led_stripe_desk";
-
-            "0xa4c1389d5f391891".friendly_name = "tuya_sensor_fridge";
-            "0xa4c13809f76bcdc2".friendly_name = "tuya_sensor_bathroom";
-            "0xa4c13882b76fa1ac".friendly_name = "tuya_sensor_sleepingroom";
-            "0xa4c138ebeae2efd2".friendly_name = "tuya_sensor_l2";
-          };
-        };
-      };
-    };
-  };
-
-}
diff --git a/config/nixos/modules/presets/katja/syncthing.nix b/config/nixos/modules/presets/katja/syncthing.nix
@@ -1,176 +0,0 @@
-{
-  pov,
-  pkgs,
-  lib,
-  config,
-  hostConfig,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath pov config;
-
-in
-{
-
-  options.enable = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf (cfg.enable && cfg.syncthing.enable) (
-    let
-      syncthingDevices = {
-        #mobile devices
-        blechkasten.id = "HGPWBVY-RD4JKBQ-X3V53IB-KRVDXEQ-4YLN5F2-WPPSMYR-SOXGTY6-IDFOAAC";
-        coladose.id = "BNCAOEB-CYTYIBA-ZKFJKRB-DX4C3MT-SDH7IWQ-5EI35PJ-YUIJSYH-COCGUAW";
-        seifenkiste.id = "6YZT5PZ-EKXZBMV-C2MJL75-OCQ36LC-L3QIRPW-VJ5EU3C-2ICZDDO-IZ7IGAO";
-
-        iphone.id = "3SM3LJV-XMHYW2D-MU5WQ3T-KGYUJOI-LXOL6YI-BSVZ2B5-QJ6GVXN-MPWMKQ7";
-
-        #servers
-        hector.name = "hector.infra.katja.wtf";
-        hector.id = "MVGBPSX-YSZNBDO-E7HZFGJ-WULYWQ5-XDHVMJO-BKA4R37-GPPRLLS-Z5DQMQJ";
-        wanderduene.name = "wanderduene.infra.katja.wtf";
-        wanderduene.id = "WEFYARN-GY3WZXB-TIXBI56-ZZ77AHS-GFH5SH2-Q35NTBI-VPT3OEM-EQNAMQH";
-        briefkasten.name = "briefkasten.infra.katja.wtf";
-        briefkasten.id = "QI2EPUE-4VMZ3XV-LXX3GXP-RHCWTRY-AACLSGL-YG7MIYV-THST74N-KJGIBQ6";
-      };
-
-      enabledShares = {
-        briefkasten = [
-          "ctucx-music-orig"
-          "ctucx-media"
-        ];
-      };
-
-      defaultVersioning = {
-        type = "trashcan";
-        params = {
-          cleanoutDays = "3";
-        };
-      };
-
-      isCurrentHost = key: value: key != config.networking.hostName;
-
-      deviceNames = (syncthingDevices |> lib.filterAttrs isCurrentHost |> builtins.attrNames);
-
-      shareDeviceNames =
-        share:
-        (
-          enabledShares
-          |> lib.filterAttrs isCurrentHost
-          |> lib.filterAttrs (key: value: builtins.elem share value)
-          |> builtins.attrNames
-        );
-
-      isShareEnabled =
-        share:
-        (
-          if builtins.hasAttr config.networking.hostName enabledShares then
-            (if builtins.elem share enabledShares.${config.networking.hostName} then true else false)
-          else
-            false
-        );
-
-      devices = lib.filterAttrs isCurrentHost syncthingDevices;
-
-      folders =
-        let
-          dataDir = config.services.syncthing.dataDir;
-
-        in
-        {
-          "${dataDir}/Audiobooks" = {
-            enable = lib.mkDefault true;
-            id = "ctucx-audiobooks";
-            label = "Audiobooks";
-            devices = deviceNames;
-            versioning = lib.mkDefault defaultVersioning;
-          };
-
-          "${dataDir}/Documents" = {
-            enable = lib.mkDefault true;
-            id = "ctucx-documents";
-            label = "Documents";
-            devices = deviceNames;
-            versioning = lib.mkDefault defaultVersioning;
-          };
-
-          "${dataDir}/Music" = {
-            enable = lib.mkDefault true;
-            id = "ctucx-music";
-            label = "Music";
-            devices = deviceNames;
-            versioning = lib.mkDefault defaultVersioning;
-          };
-
-          "${dataDir}/Pictures" = {
-            enable = lib.mkDefault true;
-            id = "ctucx-pictures";
-            label = "Pictures";
-            devices = deviceNames;
-            versioning = lib.mkDefault defaultVersioning;
-          };
-
-          "${dataDir}/Videos" = {
-            enable = lib.mkDefault true;
-            id = "ctucx-videos";
-            label = "Videos";
-            devices = deviceNames;
-            versioning = lib.mkDefault defaultVersioning;
-          };
-
-          "${dataDir}/Bahn-Richtlinien" = {
-            enable = lib.mkDefault true;
-            id = "Bahn-Richtlinien";
-            label = "Bahn-Richtlinien";
-            devices = deviceNames;
-            versioning = lib.mkDefault defaultVersioning;
-          };
-
-          "${dataDir}/Music (Originals)" = rec {
-            enable = lib.mkDefault (isShareEnabled "${id}");
-            id = "ctucx-music-orig";
-            label = "Music (Originals)";
-            devices = shareDeviceNames "${id}";
-            versioning = lib.mkDefault defaultVersioning;
-          };
-
-          "${dataDir}/Media (legacy)" = rec {
-            enable = lib.mkDefault (isShareEnabled "${id}");
-            id = "ctucx-media";
-            label = "Media (legacy)";
-            devices = shareDeviceNames "${id}";
-            versioning = lib.mkDefault defaultVersioning;
-          };
-        };
-
-    in
-    {
-      sops.secrets = lib.genAttrs [ "syncthingCert" "syncthingKey" ] (name: {
-        owner = "katja";
-        group = "users";
-      });
-
-      services.syncthing = {
-        enable = true;
-        openDefaultPorts = true;
-        guiAddress = "[::1]:8384";
-
-        user = lib.mkDefault "katja";
-        group = lib.mkDefault "users";
-
-        cert = lib.mkDefault config.sops.secrets.syncthingCert.path;
-        key = lib.mkDefault config.sops.secrets.syncthingKey.path;
-
-        dataDir = lib.mkDefault "/home/katja";
-        configDir = lib.mkDefault "/home/katja/.config/syncthing";
-
-        settings.devices = devices;
-        settings.folders = folders;
-      };
-    }
-  );
-
-}
diff --git a/config/nixos/modules/presets/katja/dnsServer.nix b/config/nixos/modules/presets/zaphyra/dnsServer.nix
diff --git a/config/nixos/modules/presets/zaphyra/enable.nix b/config/nixos/modules/presets/zaphyra/enable.nix
@@ -0,0 +1,133 @@
+{
+  povSelf,
+  pkgs,
+  lib,
+  config,
+  hostConfig,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  option = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg {
+    sops.secrets.acmeTSIGKey = { };
+
+    users.users.root = {
+      extraGroups = [ "ssh" ];
+      openssh.authorizedKeys.keys = [
+        (builtins.readFile "${pkgs.zaphyra-website}/ssh_pubkey.asc")
+      ];
+    };
+
+    dns.zones."zaphyra.eu".subdomains."${lib.removeSuffix ".zaphyra.eu" config.networking.fqdn}" =
+      lib.mkIf (hostConfig ? networking)
+        (
+          let
+            networkCfg = hostConfig.networking;
+          in
+          {
+            AAAA = lib.mkIf ((networkCfg ? ip6Address) && !networkCfg.ip6IsPrivate) [ networkCfg.ip6Address ];
+            A = lib.mkIf ((networkCfg ? ip4Address) && !networkCfg.ip4IsPrivate) [ networkCfg.ip4Address ];
+          }
+        );
+
+    modules = {
+      presets.zaphyra = {
+        syncthing.enable = lib.mkDefault true;
+      };
+
+      hardware.smartcard.enable = lib.mkDefault config.modules.presets.graphical.enable;
+
+      services = {
+        keyd.enable = lib.mkDefault config.modules.presets.graphical.enable;
+        openssh = {
+          enable = lib.mkDefault true;
+          enableRSASupport = lib.mkDefault true;
+        };
+        prometheusExporters.enable = lib.mkDefault true;
+        vnstat.enable = true;
+        vnstat.vnstati.enable = true;
+      };
+    };
+
+    modules.filesystem.impermanence.system.dirs = [ "/var/lib/acme" ];
+    security.acme = {
+      acceptTerms = true;
+      defaults = {
+        email = "letsencrypt@zaphyra.eu";
+        keyType = "ec384";
+        dnsProvider = "rfc2136";
+        environmentFile = pkgs.writeText "acme-dns-env" ''
+          RFC2136_NAMESERVER=morio.infra.zaphyra.eu
+          RFC2136_TSIG_KEY=acme-nix-${config.networking.hostName}
+          RFC2136_TSIG_ALGORITHM=hmac-sha384
+        '';
+        credentialFiles = {
+          RFC2136_TSIG_SECRET_FILE = config.sops.secrets.acmeTSIGKey.path;
+        };
+      };
+      certs."${config.networking.fqdn}" = {
+        group = lib.mkIf config.services.nginx.enable "nginx";
+        extraDomainNames = (
+          config.services.nginx.virtualHosts
+          |> lib.mapAttrsToList (
+            key: config: [
+              (if config ? serverAliases then config.serverAliases else [ ])
+              key
+            ]
+          )
+          |> lib.flatten
+        );
+      };
+    };
+
+    services = {
+      timesyncd.enable = lib.mkDefault true;
+      fstrim.enable = lib.mkDefault true;
+
+      journald.extraConfig = "SystemMaxUse=2.5G";
+
+      logind.killUserProcesses = lib.mkDefault true;
+
+      nginx = {
+        enable = lib.mkDefault true;
+        recommendedGzipSettings = true;
+        recommendedOptimisation = true;
+        recommendedProxySettings = true;
+        recommendedTlsSettings = true;
+        commonHttpConfig = ''
+          server_names_hash_bucket_size 64;
+          charset utf-8;
+
+          access_log off;
+        '';
+
+        virtualHosts."${config.networking.fqdn}" = {
+          useACMEHost = "${config.networking.fqdn}";
+          forceSSL = true;
+          kTLS = true;
+          default = true;
+        };
+      };
+    };
+
+    networking.firewall.allowedTCPPorts = [
+      80
+      443
+    ];
+
+    environment.systemPackages = with pkgs; [
+      ghostty.terminfo
+    ];
+  };
+
+}
diff --git a/config/nixos/modules/presets/katja/mailServer.nix b/config/nixos/modules/presets/zaphyra/mailServer.nix
diff --git a/config/nixos/modules/presets/katja/mautrixBridges/signal.nix b/config/nixos/modules/presets/zaphyra/mautrixBridges/signal.nix
diff --git a/config/nixos/modules/presets/katja/mautrixBridges/telegram.nix b/config/nixos/modules/presets/zaphyra/mautrixBridges/telegram.nix
diff --git a/config/nixos/modules/presets/katja/mautrixBridges/whatsapp.nix b/config/nixos/modules/presets/zaphyra/mautrixBridges/whatsapp.nix
diff --git a/config/nixos/modules/presets/zaphyra/router/enable.nix b/config/nixos/modules/presets/zaphyra/router/enable.nix
@@ -0,0 +1,93 @@
+{
+  inputs,
+  pov,
+  pkgs,
+  lib,
+  config,
+  hostConfig,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath pov config;
+
+in
+{
+
+  option = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    environment.systemPackages = [ pkgs.wireguard-tools ];
+
+    boot.initrd.kernelModules = [ "jool" ];
+
+    hardware.firmware = [
+      (pkgs.runCommandNoCC "rtl8168h-firmware" { } ''
+        mkdir -p $out/lib/firmware/rtl_nic
+        cp ${pkgs.linux-firmware}/lib/firmware/rtl_nic/rtl8168h-2.fw $out/lib/firmware/rtl_nic/rtl8168h-2.fw
+      '')
+    ];
+
+    modules.presets.zaphyra.router = {
+      systemd-networkd = true;
+      pppd = true;
+    };
+
+    networking = {
+      useNetworkd = true;
+      useDHCP = false;
+      firewall.enable = false;
+
+      nftables.enable = true;
+      nftables.rulesetFile = inputs.self.resources.zaphyra.routerRuleset;
+
+      jool.enable = true;
+      jool.nat64.default = { };
+    };
+
+    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'
+          }
+        }
+
+        policy.add(function (request, query)
+          return policy.FORWARD(dns_providers[math.random(1, #dns_providers)])
+        end)
+      '';
+    };
+
+  };
+
+}
diff --git a/config/nixos/modules/presets/katja/router/pppd.nix b/config/nixos/modules/presets/zaphyra/router/pppd.nix
diff --git a/config/nixos/modules/presets/zaphyra/router/systemd-networkd.nix b/config/nixos/modules/presets/zaphyra/router/systemd-networkd.nix
@@ -0,0 +1,246 @@
+{
+  povSelf,
+  pkgs,
+  lib,
+  config,
+  hostConfig,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  option = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg {
+    sops.secrets.wireguardPrivKey = {
+      mode = "640";
+      owner = "root";
+      group = "systemd-network";
+    };
+
+    systemd.network = {
+      enable = true;
+      wait-online.enable = false;
+
+      config.networkConfig = {
+        IPv4Forwarding = true;
+        IPv6Forwarding = true;
+      };
+
+      links."5-dtagdsl" = {
+        matchConfig.PermanentMACAddress = "d0:37:45:06:de:de";
+        linkConfig.Name = "dtagdsl";
+      };
+
+      links."5-iphone" = {
+        matchConfig.PermanentMACAddress = "aa:ab:b5:18:95:d9";
+        linkConfig.Name = "iphone";
+      };
+
+      netdevs."20-brlan" = {
+        netdevConfig = {
+          Kind = "bridge";
+          Name = "brlan";
+        };
+      };
+
+      netdevs."10-wg-novus" = {
+        netdevConfig = {
+          Kind = "wireguard";
+          Name = "wg-novus";
+        };
+
+        wireguardConfig = {
+          PrivateKeyFile = config.sops.secrets.wireguardPrivKey.path;
+          ListenPort = 51820;
+          FirewallMark = 51820;
+        };
+
+        wireguardPeers = [
+          {
+            Endpoint = "novus.infra.zaphyra.eu:51820";
+            PublicKey = "J+kRRNU65JGc0yk04v6P3tFwHSQOIfq8EkfD2gFupg4=";
+            AllowedIPs = [ "::/0" ];
+            PersistentKeepalive = 10;
+          }
+        ];
+      };
+
+      networks = {
+        "5-dtagdsl" = {
+          matchConfig.Name = "dtagdsl";
+
+          address = [ "192.168.1.2/24" ];
+
+          linkConfig.RequiredForOnline = false;
+          networkConfig.LinkLocalAddressing = false;
+        };
+
+        "5-enp1s0" = {
+          matchConfig.Name = "enp1s0";
+
+          bridge = [ "brlan" ];
+          networkConfig.ConfigureWithoutCarrier = true;
+        };
+
+        "5-iphone" = {
+          matchConfig.Name = "iphone";
+
+          networkConfig.DHCP = true;
+        };
+
+        "10-ppp-dtagdsl" = {
+          matchConfig.Type = "ppp";
+          linkConfig.RequiredForOnline = "routable";
+
+          networkConfig = {
+            KeepConfiguration = true;
+            IPv6AcceptRA = true;
+            DHCP = "ipv6";
+          };
+
+          ipv6AcceptRAConfig = {
+            UseDNS = false;
+          };
+
+          ipv6SendRAConfig = {
+            Managed = true;
+          };
+
+          dhcpV6Config = {
+            WithoutRA = "solicit";
+            PrefixDelegationHint = "::/56";
+            IAID = 0;
+            UseDNS = false;
+          };
+        };
+
+        "10-wg-novus" = {
+          matchConfig.Name = "wg-novus";
+
+          linkConfig = {
+            RequiredForOnline = false;
+          };
+
+          routes = [
+            {
+              Destination = "::/0";
+              Table = "1234";
+            }
+          ];
+        };
+
+        "20-brlan" = {
+          matchConfig = {
+            Name = "brlan";
+            Driver = "bridge";
+          };
+
+          linkConfig = {
+            RequiredForOnline = "routable";
+          };
+
+          address = [
+            "${hostConfig.networking.ip4Address}/${toString hostConfig.networking.ip4PrefixLength}"
+            "${hostConfig.networking.ip6Address}/${toString hostConfig.networking.ip6PrefixLength}"
+          ];
+
+          routingPolicyRules = [
+            {
+              From = "2a03:4000:4d:5e:acab::/112";
+              Table = 254;
+              Priority = 1900;
+              SuppressPrefixLength = 0;
+            }
+            {
+              From = "2a03:4000:4d:5e:acab::/112";
+              Table = 1234;
+              Priority = 2000;
+            }
+          ];
+
+          networkConfig = {
+            ConfigureWithoutCarrier = true;
+
+            DHCPPrefixDelegation = true;
+            IPv6PrivacyExtensions = false;
+            IPv6AcceptRA = false;
+            IPv6SendRA = true;
+
+            DHCPServer = true;
+            DNS = hostConfig.networking.ip4Address;
+          };
+
+          dhcpPrefixDelegationConfig = {
+            UplinkInterface = "ppp-dtagdsl";
+            Announce = true;
+            SubnetId = 0;
+            Token = "::1";
+          };
+
+          ipv6SendRAConfig = {
+            RouterLifetimeSec = 1800;
+            EmitDNS = true;
+            DNS = "_link_local";
+          };
+
+          ipv6PREF64Prefixes = [
+            {
+              Prefix = "64:ff9b::/96";
+            }
+          ];
+
+          dhcpServerConfig = {
+            PersistLeases = true;
+            PoolOffset = 100;
+            PoolSize = 100;
+            EmitDNS = true;
+            DNS = hostConfig.networking.ip4Address;
+            IPv6OnlyPreferredSec = 300;
+          };
+
+          dhcpServerStaticLeases = [
+            {
+              # accesspoint
+              MACAddress = "48:a9:8a:8e:dd:0b";
+              Address = "10.0.0.2";
+            }
+            {
+              # pbx
+              MACAddress = "34:31:c4:46:88:31";
+              Address = "10.0.0.3";
+            }
+            {
+              # scanner
+              MACAddress = "5c:f3:70:b9:35:9c";
+              Address = "10.0.0.4";
+            }
+            {
+              # printer
+              MACAddress = "70:77:81:2a:e7:96";
+              Address = "10.0.0.5";
+            }
+            {
+              # nix snowflake (wled)
+              MACAddress = "28:37:2f:6a:e7:14";
+              Address = "10.0.0.6";
+            }
+            {
+              # zaphyra x13
+              MACAddress = "04:CF:4B:76:93:55";
+              Address = "10.0.0.10";
+            }
+          ];
+        };
+      };
+    };
+  };
+
+}
diff --git a/config/nixos/modules/presets/zaphyra/smarthome/enable.nix b/config/nixos/modules/presets/zaphyra/smarthome/enable.nix
@@ -0,0 +1,32 @@
+{
+  inputs,
+  pov,
+  pkgs,
+  lib,
+  config,
+  hostConfig,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath pov config;
+
+in
+{
+
+  option = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    modules.presets.zaphyra.smarthome = {
+      mosqitto = true;
+      zigbee2mqtt = true;
+      mqttWebUI = true;
+      influxdb2 = true;
+      telegraf = true;
+    };
+  };
+
+}
diff --git a/config/nixos/modules/presets/katja/smarthome/influxdb2.nix b/config/nixos/modules/presets/zaphyra/smarthome/influxdb2.nix
diff --git a/config/nixos/modules/presets/katja/smarthome/mosqitto.nix b/config/nixos/modules/presets/zaphyra/smarthome/mosqitto.nix
diff --git a/config/nixos/modules/presets/zaphyra/smarthome/mqttWebUI.nix b/config/nixos/modules/presets/zaphyra/smarthome/mqttWebUI.nix
@@ -0,0 +1,71 @@
+{
+  inputs,
+  povSelf,
+  pkgs,
+  lib,
+  config,
+  hostConfig,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  option = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg {
+    dns.zones."zaphyra.eu".subdomains."smart.home.infra".AAAA = [ hostConfig.networking.ip6Address ];
+
+    services.nginx = {
+      enable = true;
+      virtualHosts."smart.${config.networking.domain}" = {
+        useACMEHost = config.networking.fqdn;
+        forceSSL = true;
+        kTLS = true;
+        extraConfig = ''
+          ssl_client_certificate ${inputs.self.resources.zaphyra.rootCA};
+          ssl_verify_client optional;
+        '';
+        locations = {
+          "/" = {
+            root = "${
+              pkgs.buildEnv {
+                name = "mqtt-webui-env";
+                paths = [
+                  pkgs.mqtt-webui
+                  (pkgs.writeTextDir "extra.css" (builtins.toJSON inputs.self.resources.zaphyra.mqttWebUI.extra-css))
+                  (pkgs.writeTextDir "config.json" (
+                    builtins.toJSON (import inputs.self.resources.zaphyra.mqttWebUI.config)
+                  ))
+                ];
+              }
+            }/";
+            extraConfig = ''
+              location ~ ^/(?!(favicon-512x512\.png|manifest\.json)) {
+                if ($ssl_client_verify != SUCCESS) {
+                    return 403;
+                }
+              }
+            '';
+          };
+          "/mqtt" = {
+            proxyPass = "http://[::1]:9005";
+            proxyWebsockets = true;
+            extraConfig = ''
+              if ($ssl_client_verify != SUCCESS) {
+                  return 403;
+              }
+            '';
+          };
+        };
+      };
+    };
+  };
+
+}
diff --git a/config/nixos/modules/presets/katja/smarthome/telegraf.nix b/config/nixos/modules/presets/zaphyra/smarthome/telegraf.nix
diff --git a/config/nixos/modules/presets/zaphyra/smarthome/zigbee2mqtt.nix b/config/nixos/modules/presets/zaphyra/smarthome/zigbee2mqtt.nix
@@ -0,0 +1,122 @@
+{
+  inputs,
+  povSelf,
+  pkgs,
+  lib,
+  config,
+  hostConfig,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  option = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg {
+    dns.zones."zaphyra.eu".subdomains."zigbee2mqtt.home.infra".AAAA = [
+      hostConfig.networking.ip6Address
+    ];
+
+    modules.filesystem.impermanence.system.dirs = [
+      {
+        directory = "/var/lib/zigbee2mqtt";
+        mode = "0770";
+        user = "zigbee2mqtt";
+        group = "zigbee2mqtt";
+      }
+    ];
+
+    sops.secrets."zigbee2mqttSecrets.yaml" = {
+      owner = "zigbee2mqtt";
+      key = "zigbee2mqttSecrets";
+    };
+
+    systemd.services.zigbee2mqtt = {
+      requires = [ "mosquitto.service" ];
+      after = [ "mosquitto.service" ];
+      serviceConfig = {
+        Restart = lib.mkForce "always";
+        RuntimeMaxSec = "1d";
+      };
+    };
+
+    services = {
+      udev.extraRules = ''
+        SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{serial}=="00_12_4B_00_25_9B_C1_FC", SYMLINK+="zigbee0"
+        ATTR{idVendor}=="0451", ATTR{idProduct}=="16a8", ENV{ID_MM_DEVICE_IGNORE}="1"
+        SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="zigbee0"
+      '';
+
+      nginx = {
+        enable = true;
+        virtualHosts."zigbee2mqtt.${config.networking.domain}" = {
+          useACMEHost = config.networking.fqdn;
+          forceSSL = true;
+          kTLS = true;
+          extraConfig = ''
+            ssl_client_certificate ${inputs.self.resources.zaphyra.rootCA};
+            ssl_verify_client on;
+          '';
+          locations."/" = {
+            proxyPass = "http://[::1]:${toString config.services.zigbee2mqtt.settings.frontend.port}";
+            proxyWebsockets = true;
+          };
+        };
+      };
+
+      zigbee2mqtt = {
+        enable = true;
+        package = pkgs.zigbee2mqtt;
+        settings = {
+          homeassistant = false;
+          permit_join = false;
+
+          mqtt = {
+            base_topic = "zigbee2mqtt";
+            server = "mqtt://[::1]";
+          };
+
+          serial = {
+            port = "/dev/zigbee0";
+            disable_led = true;
+          };
+
+          frontend = {
+            port = 8422;
+            host = "::1";
+          };
+
+          advanced = {
+            log_level = "info";
+            log_output = [ "console" ];
+            channel = 26;
+            network_key = "!${config.sops.secrets."zigbee2mqttSecrets.yaml".path} network_key";
+          };
+
+          device_options.retain = true;
+          devices = {
+            "0x84fd27fffe6b9ddd".friendly_name = "ikea_lamp_hallway";
+            "0x94deb8fffe52e639".friendly_name = "ikea_lamp_rgb";
+            "0x84fd27fffe44369e".friendly_name = "ikea_lamp_sleepingroom";
+            "0x84fd27fffea515fc".friendly_name = "ikea_lamp_livingroom";
+
+            "0xa4c138da0f6d23de".friendly_name = "tuya_led_stripe_desk";
+
+            "0xa4c1389d5f391891".friendly_name = "tuya_sensor_fridge";
+            "0xa4c13809f76bcdc2".friendly_name = "tuya_sensor_bathroom";
+            "0xa4c13882b76fa1ac".friendly_name = "tuya_sensor_sleepingroom";
+            "0xa4c138ebeae2efd2".friendly_name = "tuya_sensor_l2";
+          };
+        };
+      };
+    };
+  };
+
+}
diff --git a/config/nixos/modules/presets/zaphyra/syncthing.nix b/config/nixos/modules/presets/zaphyra/syncthing.nix
@@ -0,0 +1,176 @@
+{
+  pov,
+  pkgs,
+  lib,
+  config,
+  hostConfig,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath pov config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf (cfg.enable && cfg.syncthing.enable) (
+    let
+      syncthingDevices = {
+        #mobile devices
+        blechkasten.id = "HGPWBVY-RD4JKBQ-X3V53IB-KRVDXEQ-4YLN5F2-WPPSMYR-SOXGTY6-IDFOAAC";
+        coladose.id = "BNCAOEB-CYTYIBA-ZKFJKRB-DX4C3MT-SDH7IWQ-5EI35PJ-YUIJSYH-COCGUAW";
+        seifenkiste.id = "6YZT5PZ-EKXZBMV-C2MJL75-OCQ36LC-L3QIRPW-VJ5EU3C-2ICZDDO-IZ7IGAO";
+
+        iphone.id = "3SM3LJV-XMHYW2D-MU5WQ3T-KGYUJOI-LXOL6YI-BSVZ2B5-QJ6GVXN-MPWMKQ7";
+
+        #servers
+        hector.name = "hector.infra.katja.wtf";
+        hector.id = "MVGBPSX-YSZNBDO-E7HZFGJ-WULYWQ5-XDHVMJO-BKA4R37-GPPRLLS-Z5DQMQJ";
+        wanderduene.name = "wanderduene.infra.katja.wtf";
+        wanderduene.id = "WEFYARN-GY3WZXB-TIXBI56-ZZ77AHS-GFH5SH2-Q35NTBI-VPT3OEM-EQNAMQH";
+        briefkasten.name = "briefkasten.infra.katja.wtf";
+        briefkasten.id = "QI2EPUE-4VMZ3XV-LXX3GXP-RHCWTRY-AACLSGL-YG7MIYV-THST74N-KJGIBQ6";
+      };
+
+      enabledShares = {
+        briefkasten = [
+          "ctucx-music-orig"
+          "ctucx-media"
+        ];
+      };
+
+      defaultVersioning = {
+        type = "trashcan";
+        params = {
+          cleanoutDays = "3";
+        };
+      };
+
+      isCurrentHost = key: value: key != config.networking.hostName;
+
+      deviceNames = (syncthingDevices |> lib.filterAttrs isCurrentHost |> builtins.attrNames);
+
+      shareDeviceNames =
+        share:
+        (
+          enabledShares
+          |> lib.filterAttrs isCurrentHost
+          |> lib.filterAttrs (key: value: builtins.elem share value)
+          |> builtins.attrNames
+        );
+
+      isShareEnabled =
+        share:
+        (
+          if builtins.hasAttr config.networking.hostName enabledShares then
+            (if builtins.elem share enabledShares.${config.networking.hostName} then true else false)
+          else
+            false
+        );
+
+      devices = lib.filterAttrs isCurrentHost syncthingDevices;
+
+      folders =
+        let
+          dataDir = config.services.syncthing.dataDir;
+
+        in
+        {
+          "${dataDir}/Audiobooks" = {
+            enable = lib.mkDefault true;
+            id = "ctucx-audiobooks";
+            label = "Audiobooks";
+            devices = deviceNames;
+            versioning = lib.mkDefault defaultVersioning;
+          };
+
+          "${dataDir}/Documents" = {
+            enable = lib.mkDefault true;
+            id = "ctucx-documents";
+            label = "Documents";
+            devices = deviceNames;
+            versioning = lib.mkDefault defaultVersioning;
+          };
+
+          "${dataDir}/Music" = {
+            enable = lib.mkDefault true;
+            id = "ctucx-music";
+            label = "Music";
+            devices = deviceNames;
+            versioning = lib.mkDefault defaultVersioning;
+          };
+
+          "${dataDir}/Pictures" = {
+            enable = lib.mkDefault true;
+            id = "ctucx-pictures";
+            label = "Pictures";
+            devices = deviceNames;
+            versioning = lib.mkDefault defaultVersioning;
+          };
+
+          "${dataDir}/Videos" = {
+            enable = lib.mkDefault true;
+            id = "ctucx-videos";
+            label = "Videos";
+            devices = deviceNames;
+            versioning = lib.mkDefault defaultVersioning;
+          };
+
+          "${dataDir}/Bahn-Richtlinien" = {
+            enable = lib.mkDefault true;
+            id = "Bahn-Richtlinien";
+            label = "Bahn-Richtlinien";
+            devices = deviceNames;
+            versioning = lib.mkDefault defaultVersioning;
+          };
+
+          "${dataDir}/Music (Originals)" = rec {
+            enable = lib.mkDefault (isShareEnabled "${id}");
+            id = "ctucx-music-orig";
+            label = "Music (Originals)";
+            devices = shareDeviceNames "${id}";
+            versioning = lib.mkDefault defaultVersioning;
+          };
+
+          "${dataDir}/Media (legacy)" = rec {
+            enable = lib.mkDefault (isShareEnabled "${id}");
+            id = "ctucx-media";
+            label = "Media (legacy)";
+            devices = shareDeviceNames "${id}";
+            versioning = lib.mkDefault defaultVersioning;
+          };
+        };
+
+    in
+    {
+      sops.secrets = lib.genAttrs [ "syncthingCert" "syncthingKey" ] (name: {
+        owner = "zaphyra";
+        group = "users";
+      });
+
+      services.syncthing = {
+        enable = true;
+        openDefaultPorts = true;
+        guiAddress = "[::1]:8384";
+
+        user = lib.mkDefault "zaphyra";
+        group = lib.mkDefault "users";
+
+        cert = lib.mkDefault config.sops.secrets.syncthingCert.path;
+        key = lib.mkDefault config.sops.secrets.syncthingKey.path;
+
+        dataDir = lib.mkDefault "/home/zaphyra";
+        configDir = lib.mkDefault "/home/zaphyra/.config/syncthing";
+
+        settings.devices = devices;
+        settings.folders = folders;
+      };
+    }
+  );
+
+}
diff --git a/config/nixos/modules/users/katja.nix b/config/nixos/modules/users/katja.nix
@@ -1,109 +0,0 @@
-{
-  inputs,
-  povSelf,
-  config,
-  lib,
-  pkgs,
-  homeManagerModules,
-  ...
-}:
-let
-  inherit (lib) types;
-  cfg = lib.getAttrFromPath povSelf config;
-
-in
-{
-
-  options.enable = {
-    type = types.bool;
-    default = false;
-  };
-
-  config = lib.mkIf cfg.enable {
-    sops.secrets.katjaPassword = {
-      neededForUsers = true;
-      sopsFile = inputs.self.sopsSecrets.common;
-    };
-
-    programs.fuse.userAllowOther = lib.mkIf config.modules.filesystem.impermanence.home.enable (lib.mkDefault true);
-
-    users.users.katja = {
-      uid = 1001;
-      description = "Katja";
-      hashedPasswordFile = config.sops.secrets.katjaPassword.path;
-      isNormalUser = true;
-      extraGroups =
-        [
-          "ssh"
-          "wheel"
-        ]
-        ++ lib.optionals config.networking.networkmanager.enable [
-          "networkmanager"
-        ];
-      openssh.authorizedKeys.keys = [
-        (builtins.readFile "${pkgs.zaphyra-website}/ssh_pubkey.asc")
-      ];
-    };
-
-    home-manager.users.katja.imports = lib.concatLists [
-      [
-        homeManagerModules.katja.common
-      ]
-
-      (lib.optionals config.modules.filesystem.impermanence.home.enable [
-        inputs.impermanence.homeManagerModules.impermanence
-        homeManagerModules.katja.impermanence
-      ])
-      (lib.optionals config.modules.presets.graphical.enable (
-        with homeManagerModules.katja;
-        [
-          configure.xdg
-
-          programs.ghostty
-          programs.ssh
-          programs.git
-          programs.gpg
-
-          programs.yt-dlp
-          programs.phockup
-          programs.bitwarden-cli
-
-          programs.nautilus
-
-          programs.firefox
-          programs.thunderbird
-          programs.errands
-
-          programs.fractal
-          programs.tuba
-
-          programs.typst
-          programs.ocrmypdf
-          programs.papers
-          programs.pdfarranger
-          programs.libreoffice
-          programs.apostrophe
-
-          programs.celluloid
-
-          programs.javascript
-        ]
-      ))
-      (lib.optionals (config.modules.presets.graphical.type == "gnomeMinimal") (
-        with homeManagerModules.katja;
-        [
-          configure.gnome
-
-          gnomeExtensions.dash-to-dock
-          gnomeExtensions.just-perfection
-          gnomeExtensions.space-bar
-          gnomeExtensions.search-light
-          gnomeExtensions.emoji-copy
-          gnomeExtensions.pip-on-top
-          gnomeExtensions.bluetoothBatteryMeter
-        ]
-      ))
-    ];
-  };
-
-}
diff --git a/config/nixos/modules/users/zaphyra.nix b/config/nixos/modules/users/zaphyra.nix
@@ -0,0 +1,110 @@
+{
+  inputs,
+  povSelf,
+  config,
+  lib,
+  pkgs,
+  homeManagerModules,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options.enable = {
+    type = types.bool;
+    default = false;
+  };
+
+  config = lib.mkIf cfg.enable {
+    sops.secrets.zaphyraPassword = {
+      neededForUsers = true;
+      sopsFile = inputs.self.sopsSecrets.common;
+    };
+
+    programs.fuse.userAllowOther = lib.mkIf config.modules.filesystem.impermanence.home.enable (lib.mkDefault true);
+
+    users.users.zaphyra = {
+      uid = 1001;
+      description = "zaphyra";
+      hashedPasswordFile = config.sops.secrets.zaphyraPassword.path;
+      isNormalUser = true;
+      extraGroups =
+        [
+          "ssh"
+          "wheel"
+        ]
+        ++ lib.optionals config.networking.networkmanager.enable [
+          "networkmanager"
+        ];
+      openssh.authorizedKeys.keys = [
+        (builtins.readFile "${pkgs.zaphyra-website}/ssh_pubkey.asc")
+        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPnNyOCX+PopTHuNrfBwEmPM7FC6oM7nFgW/2tvW7ddT"
+      ];
+    };
+
+    home-manager.users.zaphyra.imports = lib.concatLists [
+      [
+        homeManagerModules.zaphyra.common
+      ]
+
+      (lib.optionals config.modules.filesystem.impermanence.home.enable [
+        inputs.impermanence.homeManagerModules.impermanence
+        homeManagerModules.zaphyra.impermanence
+      ])
+      (lib.optionals config.modules.presets.graphical.enable (
+        with homeManagerModules.zaphyra;
+        [
+          configure.xdg
+
+          programs.ghostty
+          programs.ssh
+          programs.git
+          programs.gpg
+
+          programs.yt-dlp
+          programs.phockup
+          programs.bitwarden-cli
+
+          programs.nautilus
+
+          programs.firefox
+          programs.thunderbird
+          programs.errands
+
+          programs.fractal
+          programs.tuba
+
+          programs.typst
+          programs.ocrmypdf
+          programs.papers
+          programs.pdfarranger
+          programs.libreoffice
+          programs.apostrophe
+
+          programs.celluloid
+
+          programs.javascript
+        ]
+      ))
+      (lib.optionals (config.modules.presets.graphical.type == "gnomeMinimal") (
+        with homeManagerModules.zaphyra;
+        [
+          configure.gnome
+
+          gnomeExtensions.dash-to-dock
+          gnomeExtensions.just-perfection
+          gnomeExtensions.space-bar
+          gnomeExtensions.search-light
+          gnomeExtensions.emoji-copy
+          gnomeExtensions.pip-on-top
+          gnomeExtensions.bluetoothBatteryMeter
+        ]
+      ))
+    ];
+  };
+
+}
diff --git a/hosts/huntii/default.nix b/hosts/huntii/default.nix
@@ -46,7 +46,7 @@
 
         presets = {
           base.enable = true;
-          katja.enable = true;
+          zaphyra.enable = true;
 
           graphical.enable = true;
           graphical.type = "gnomeMinimal";

@@ -57,7 +57,7 @@
           systemd-oomd.enable = true;
         };
 
-        users.katja.enable = true;
+        users.zaphyra.enable = true;
       };
 
       networking = {

@@ -85,7 +85,7 @@
       };
 
       system.stateVersion = "25.05";
-      home-manager.users.katja.home.stateVersion = "25.05";
+      home-manager.users.zaphyra.home.stateVersion = "25.05";
     };
 
 }
diff --git a/hosts/morio/default.nix b/hosts/morio/default.nix
@@ -64,7 +64,7 @@
         presets = {
           base.enable = true;
           netcup.enable = true;
-          katja = {
+          zaphyra = {
             enable = true;
             syncthing.enable = false;
             dnsServer.enable = true;

@@ -100,11 +100,11 @@
           "things.zaphyra.eu".enable = true;
         };
 
-        users.katja.enable = true;
+        users.zaphyra.enable = true;
       };
 
       system.stateVersion = "25.05";
-      home-manager.users.katja.home.stateVersion = "25.05";
+      home-manager.users.zaphyra.home.stateVersion = "25.05";
     };
 
 }
diff --git a/hosts/novus/default.nix b/hosts/novus/default.nix
@@ -71,7 +71,7 @@
         presets = {
           base.enable = true;
           netcup.enable = true;
-          katja = {
+          zaphyra = {
             enable = true;
             syncthing.enable = false;
             dnsServer.enable = true;

@@ -97,7 +97,7 @@
           "fedi.ctu.cx".enable = true;
         };
 
-        users.katja.enable = true;
+        users.zaphyra.enable = true;
       };
 
       networking.firewall = {

@@ -152,7 +152,7 @@
       };
 
       system.stateVersion = "24.11";
-      home-manager.users.katja.home.stateVersion = "24.11";
+      home-manager.users.zaphyra.home.stateVersion = "24.11";
     };
 
 }
diff --git a/hosts/polaris/default.nix b/hosts/polaris/default.nix
@@ -71,7 +71,7 @@
 
         presets = {
           base.enable = true;
-          katja = {
+          zaphyra = {
             enable = true;
             router.enable = true;
             smarthome.enable = true;

@@ -79,11 +79,11 @@
           };
         };
 
-        users.katja.enable = true;
+        users.zaphyra.enable = true;
       };
 
       system.stateVersion = "25.05";
-      home-manager.users.katja.home.stateVersion = "25.05";
+      home-manager.users.zaphyra.home.stateVersion = "25.05";
     };
 
 }
diff --git a/resources/katja/mqttWebUI/config.nix b/resources/katja/mqttWebUI/config.nix
@@ -1,217 +0,0 @@
-let
-
-  Switch = name: topic: {
-    title = name;
-    type = "switch";
-    icon = "icons/power_button.png";
-    topic.get = topic;
-    topic.set = "${topic}/set";
-    transform.get = "return (message.state == 'ON') ? true : false";
-    transform.set = "return JSON.stringify({state: (input) ? 'ON' : 'OFF'})";
-  };
-
-  BrighnessSlider = name: topic: {
-    title = name;
-    type = "slider";
-    icon = "icons/bulb.png";
-    sliderMinValue = 0;
-    sliderMaxValue = 254;
-    sliderStepValue = 1;
-    topic.get = topic;
-    topic.set = "${topic}/set";
-    transform.get = "return message.brightness";
-    transform.set = "return JSON.stringify({brightness: Number(input)})";
-  };
-
-  ColorTemperatureSlider = name: topic: {
-    title = name;
-    type = "slider";
-    icon = "icons/bulb.png";
-    sliderMinValue = 250;
-    sliderMaxValue = 454;
-    sliderStepValue = 1;
-    topic.get = topic;
-    topic.set = "${topic}/set";
-    transform.get = "return message.color_temp";
-    transform.set = "return JSON.stringify({color_temp: Number(input)})";
-  };
-
-  DimmableLamp = name: topic: {
-    title = name;
-    items = [
-      (Switch "Power" topic)
-      (BrighnessSlider "Brighness" topic)
-    ];
-  };
-
-  WhiteSpectrumLamp = name: topic: {
-    title = name;
-    items = [
-      (Switch "Power" topic)
-      (BrighnessSlider "Brighness" topic)
-      (ColorTemperatureSlider "Color Temperature" topic)
-    ];
-  };
-
-  ColorSpectrumLamp = name: topic: {
-    title = name;
-    items = [
-      (Switch "Power" topic)
-      (BrighnessSlider "Brighness" topic)
-      (ColorTemperatureSlider "Color Temperature" topic)
-
-      {
-        title = "Color";
-        type = "select";
-        icon = "icons/bulb.png";
-        topic.get = topic;
-        topic.set = "${topic}/set";
-        transform.get = "return message.color.x + ','+message.color.y";
-        transform.set = "return JSON.stringify({color: {x: input.split(',')[0], y: input.split(',')[1]}})";
-        selectOptions = [
-          {
-            label = "Red";
-            value = "0.71,0.26";
-          }
-          {
-            label = "Green";
-            value = "0.19,0.78";
-          }
-          {
-            label = "Blue";
-            value = "0.09,0.13";
-          }
-        ];
-      }
-    ];
-  };
-
-in
-{
-
-  appName = "Smart-Home";
-  extraCSS = "/extra.css";
-  disableAuth = true;
-  pages = [
-    {
-      id = "mainpage";
-      icon = "favicon-512x512.png";
-      title = "Smart-Home";
-      sections = [
-
-        (WhiteSpectrumLamp "Hallway" "zigbee2mqtt/ikea_lamp_hallway")
-
-        (WhiteSpectrumLamp "Living room" "zigbee2mqtt/ikea_lamp_livingroom")
-
-        (WhiteSpectrumLamp "Sleeping room" "zigbee2mqtt/ikea_lamp_sleepingroom")
-
-        (DimmableLamp "Desk" "zigbee2mqtt/tuya_led_stripe_desk")
-
-        (ColorSpectrumLamp "RGB Lamp" "zigbee2mqtt/ikea_lamp_rgb")
-
-        {
-          title = "Temperature-Sensors";
-          items = [
-            {
-              title = "Fridge";
-              type = "text";
-              topic = "zigbee2mqtt/tuya_sensor_fridge";
-              icon = "icons/temperature.png";
-              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
-            }
-            {
-              title = "Bathroom";
-              type = "text";
-              topic = "zigbee2mqtt/tuya_sensor_bathroom";
-              icon = "icons/temperature.png";
-              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
-            }
-
-            {
-              title = "Door";
-              type = "text";
-              topic = "zigbee2mqtt/tuya_sensor_l";
-              icon = "icons/temperature.png";
-              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
-            }
-            {
-              title = "Bed";
-              type = "text";
-              topic = "zigbee2mqtt/tuya_sensor_l2";
-              icon = "icons/temperature.png";
-              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
-            }
-
-          ];
-        }
-
-        {
-          items = [
-            {
-              title = "Departures";
-              type = "text";
-              icon = "icons/electric_range.png";
-              link = "#departures";
-            }
-            {
-              title = "Grafana-Dashboard";
-              type = "text";
-              icon = "icons/sun.png";
-              link = "https://grafana.infra.katja.wtf/d/FRDYqjEGz/smarthome-influx?orgId=1&refresh=5s";
-            }
-          ];
-        }
-
-      ];
-    }
-
-    {
-      id = "departures";
-      title = "Departures";
-      sections = [
-        {
-          items = [
-            {
-              type = "html";
-              topic = "departures2mqtt";
-              html = "<div class=\"loader\"></div>";
-              transform = ''
-                clearInterval(globalThis.departuresUpdater)
-                globalThis.departuresUpdater = setInterval(() => {
-                  let element = document.querySelector('[data-last-updated]');
-                  element.textContent = 'Last Update: ' + (Math.floor(Date.now() / 1000) - element.dataset.lastUpdated) + ' seconds ago';
-                }, 10000)
-
-                let output = "";
-
-                Object.entries(message.departures).forEach((data) => {
-                   output += '<div class="departures"><div class="table-column table-title">' + data[0] + '</div><div class="table">';
-
-                   output += '<div class="table-row line-column"><div class="table-column table-heading">Linie</div>';
-                   data[1].forEach((departure) => output += '<div class="table-column">' + departure.line + '</div>');
-                   output += '</div>';
-
-                   output += '<div class="table-row direction-column"><div class="table-column table-heading">Richtung</div>';
-                   data[1].forEach((departure) => output += '<div class="table-column">' + departure.direction + '</div>');
-                   output += '</div>';
-
-                   output += '<div class="table-row dep-column"><div class="table-column table-heading">Abfahrt</div>';
-                   data[1].forEach((departure) => output += '<div class="table-column">' + (Number(departure.departure_in) ? departure.departure_in + " min" : "sofort") + '</div>');
-                   output += '</div>';
-
-                   output += '</div></div>';
-                });
-
-                output += '<div class="lastUpdated" data-last-updated="' + message.lastUpdated + '">Last Update: ' + (Math.floor(Date.now() / 1000) - message.lastUpdated) + ' seconds ago</div>';
-
-                return output;
-              '';
-            }
-          ];
-        }
-      ];
-    }
-
-  ];
-
-}
diff --git a/resources/zaphyra/mqttWebUI/config.nix b/resources/zaphyra/mqttWebUI/config.nix
@@ -0,0 +1,217 @@
+let
+
+  Switch = name: topic: {
+    title = name;
+    type = "switch";
+    icon = "icons/power_button.png";
+    topic.get = topic;
+    topic.set = "${topic}/set";
+    transform.get = "return (message.state == 'ON') ? true : false";
+    transform.set = "return JSON.stringify({state: (input) ? 'ON' : 'OFF'})";
+  };
+
+  BrighnessSlider = name: topic: {
+    title = name;
+    type = "slider";
+    icon = "icons/bulb.png";
+    sliderMinValue = 0;
+    sliderMaxValue = 254;
+    sliderStepValue = 1;
+    topic.get = topic;
+    topic.set = "${topic}/set";
+    transform.get = "return message.brightness";
+    transform.set = "return JSON.stringify({brightness: Number(input)})";
+  };
+
+  ColorTemperatureSlider = name: topic: {
+    title = name;
+    type = "slider";
+    icon = "icons/bulb.png";
+    sliderMinValue = 250;
+    sliderMaxValue = 454;
+    sliderStepValue = 1;
+    topic.get = topic;
+    topic.set = "${topic}/set";
+    transform.get = "return message.color_temp";
+    transform.set = "return JSON.stringify({color_temp: Number(input)})";
+  };
+
+  DimmableLamp = name: topic: {
+    title = name;
+    items = [
+      (Switch "Power" topic)
+      (BrighnessSlider "Brighness" topic)
+    ];
+  };
+
+  WhiteSpectrumLamp = name: topic: {
+    title = name;
+    items = [
+      (Switch "Power" topic)
+      (BrighnessSlider "Brighness" topic)
+      (ColorTemperatureSlider "Color Temperature" topic)
+    ];
+  };
+
+  ColorSpectrumLamp = name: topic: {
+    title = name;
+    items = [
+      (Switch "Power" topic)
+      (BrighnessSlider "Brighness" topic)
+      (ColorTemperatureSlider "Color Temperature" topic)
+
+      {
+        title = "Color";
+        type = "select";
+        icon = "icons/bulb.png";
+        topic.get = topic;
+        topic.set = "${topic}/set";
+        transform.get = "return message.color.x + ','+message.color.y";
+        transform.set = "return JSON.stringify({color: {x: input.split(',')[0], y: input.split(',')[1]}})";
+        selectOptions = [
+          {
+            label = "Red";
+            value = "0.71,0.26";
+          }
+          {
+            label = "Green";
+            value = "0.19,0.78";
+          }
+          {
+            label = "Blue";
+            value = "0.09,0.13";
+          }
+        ];
+      }
+    ];
+  };
+
+in
+{
+
+  appName = "Smart-Home";
+  extraCSS = "/extra.css";
+  disableAuth = true;
+  pages = [
+    {
+      id = "mainpage";
+      icon = "favicon-512x512.png";
+      title = "Smart-Home";
+      sections = [
+
+        (WhiteSpectrumLamp "Hallway" "zigbee2mqtt/ikea_lamp_hallway")
+
+        (WhiteSpectrumLamp "Living room" "zigbee2mqtt/ikea_lamp_livingroom")
+
+        (WhiteSpectrumLamp "Sleeping room" "zigbee2mqtt/ikea_lamp_sleepingroom")
+
+        (DimmableLamp "Desk" "zigbee2mqtt/tuya_led_stripe_desk")
+
+        (ColorSpectrumLamp "RGB Lamp" "zigbee2mqtt/ikea_lamp_rgb")
+
+        {
+          title = "Temperature-Sensors";
+          items = [
+            {
+              title = "Fridge";
+              type = "text";
+              topic = "zigbee2mqtt/tuya_sensor_fridge";
+              icon = "icons/temperature.png";
+              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
+            }
+            {
+              title = "Bathroom";
+              type = "text";
+              topic = "zigbee2mqtt/tuya_sensor_bathroom";
+              icon = "icons/temperature.png";
+              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
+            }
+
+            {
+              title = "Door";
+              type = "text";
+              topic = "zigbee2mqtt/tuya_sensor_l";
+              icon = "icons/temperature.png";
+              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
+            }
+            {
+              title = "Bed";
+              type = "text";
+              topic = "zigbee2mqtt/tuya_sensor_l2";
+              icon = "icons/temperature.png";
+              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
+            }
+
+          ];
+        }
+
+        {
+          items = [
+            {
+              title = "Departures";
+              type = "text";
+              icon = "icons/electric_range.png";
+              link = "#departures";
+            }
+            {
+              title = "Grafana-Dashboard";
+              type = "text";
+              icon = "icons/sun.png";
+              link = "https://grafana.infra.zaphyra.eu/d/FRDYqjEGz/smarthome-influx?orgId=1&refresh=5s";
+            }
+          ];
+        }
+
+      ];
+    }
+
+    {
+      id = "departures";
+      title = "Departures";
+      sections = [
+        {
+          items = [
+            {
+              type = "html";
+              topic = "departures2mqtt";
+              html = "<div class=\"loader\"></div>";
+              transform = ''
+                clearInterval(globalThis.departuresUpdater)
+                globalThis.departuresUpdater = setInterval(() => {
+                  let element = document.querySelector('[data-last-updated]');
+                  element.textContent = 'Last Update: ' + (Math.floor(Date.now() / 1000) - element.dataset.lastUpdated) + ' seconds ago';
+                }, 10000)
+
+                let output = "";
+
+                Object.entries(message.departures).forEach((data) => {
+                   output += '<div class="departures"><div class="table-column table-title">' + data[0] + '</div><div class="table">';
+
+                   output += '<div class="table-row line-column"><div class="table-column table-heading">Linie</div>';
+                   data[1].forEach((departure) => output += '<div class="table-column">' + departure.line + '</div>');
+                   output += '</div>';
+
+                   output += '<div class="table-row direction-column"><div class="table-column table-heading">Richtung</div>';
+                   data[1].forEach((departure) => output += '<div class="table-column">' + departure.direction + '</div>');
+                   output += '</div>';
+
+                   output += '<div class="table-row dep-column"><div class="table-column table-heading">Abfahrt</div>';
+                   data[1].forEach((departure) => output += '<div class="table-column">' + (Number(departure.departure_in) ? departure.departure_in + " min" : "sofort") + '</div>');
+                   output += '</div>';
+
+                   output += '</div></div>';
+                });
+
+                output += '<div class="lastUpdated" data-last-updated="' + message.lastUpdated + '">Last Update: ' + (Math.floor(Date.now() / 1000) - message.lastUpdated) + ' seconds ago</div>';
+
+                return output;
+              '';
+            }
+          ];
+        }
+      ];
+    }
+
+  ];
+
+}
diff --git a/resources/katja/mqttWebUI/extra-css.css b/resources/zaphyra/mqttWebUI/extra-css.css
diff --git a/resources/katja/rootCA.crt b/resources/zaphyra/rootCA.crt
diff --git a/resources/katja/routerRuleset.nft b/resources/zaphyra/routerRuleset.nft
diff --git a/secrets/common.yaml b/secrets/common.yaml
@@ -1,4 +1,4 @@
-katjaPassword: ENC[AES256_GCM,data:j9RVyCH+TbemyCZng2SsppyblPQMxJtsWOAgDRIBoMS1tnV+XWHfd7YsdwOaV8yasQDy2A2i9EEuqE6F5VVwgURB5P3MYNvpnQ==,iv:6BshqPinpMI/ICMiQuM9OpFIY/j3Ir4U5jH7CX5k7JQ=,tag:cR1RnZWggJC/EG+NaN4Llg==,type:str]
+zaphyraPassword: ENC[AES256_GCM,data:rW2g6n71PA6R5+KZ9i4EZ8doC9JGCLMGf+29r+8zvPMgz2ndJ0Hltkq0I12AQ5GILhS2x6lOLTpTjZ4SkG5PM1FRN/3Vi0wrdQ==,iv:weyksZS/MnkZLlM5nScUD4NvX17XnRG0dmut6Lyjqoo=,tag:scrtArW3n69CDaAPxwbQ8Q==,type:str]
 resticEnv:
     novus: ENC[AES256_GCM,data:KTTd0UMQiOHrrFIbY9pIJWO9MVIFWs2pvjm4Vo46CE/CrgGfxJur5uYtxHvR94bwaoLXd8RpdlONSRzbShQlH0xE86C/MyRNWiZR5QLyWj6YwzFd+DSdHQD0h0AlRviZY/vFze1EJRPZ0d6XCMJBX+aTizVSxw==,iv:pSfa9Kgpwq/wqn6nOKozgEy2h9C22oVWSCA7X07aW1w=,tag:+aD8wh33mA9hqQ1TKT1m8w==,type:str]
 sops:

@@ -48,8 +48,8 @@ sops:
             NGJXZ3dnN0VvMkZ1YS9QcldRMFdTUW8KLyjsWVufSnhhNz/rzGRSU8ovJr/pQmMX
             Bh3EfJdvfw+ZhAY3KfMqzpiyf+En+uTP2dvctCbDfVmE/WZVaJ16Tg==
             -----END AGE ENCRYPTED FILE-----
-    lastmodified: "2025-06-06T16:51:05Z"
-    mac: ENC[AES256_GCM,data:djFJXjtMlYp13Fu4+28FvaZsr92Aci8edlXET8T0/e+n8pWe+84Q0SrFA6UPjTorBx2aVp53N2tK3RfPB+coWqfTosseXyZzBB8yTn3KU4qx1wZS7+JvfJs4xemtAVk/9Mc1ElAHukqXZjwlP0VszjZ7xmsmnuWgT9X+ST732A4=,iv:c55IPoOwR19NSmP++a5H0A5wFwID/SBh4PBU6rz24sg=,tag:lecykuH8RI/r9QNEr6QyRw==,type:str]
+    lastmodified: "2025-06-06T17:49:14Z"
+    mac: ENC[AES256_GCM,data:JEIPLK7altKMSGsRqb8YyL0OjvLKkHYAfBxqV46QHUJOgostIgelrdLostkKmZryqtS6i8GlyRbLT7yyOlKF/KhkgbHzL7fdoW/wL7UyVi3lTVPEo8VxNl3BBNb2LGqwRl+nA3vG5QIwtxFRqxo6OK//9lmraYmY/7WafRW9a6M=,iv:Gh8wQ2/N8dwxb7ZhbdRv0VJR61ynNR68ax9m/zhDF3M=,tag:yvWh4JakRh3/nMLBP8HXRg==,type:str]
     pgp:
         - created_at: "2025-06-04T20:02:58Z"
           enc: |-