commit 2930ff73dcc5da49d9a70fdcd58b74dcf05e7779
parent ad47266d4f5c14d99f026cb128f67d331b668fe7
Author: Katja (zaphyra) <git@ctu.cx>
Date: Fri, 6 Jun 2025 20:10:19 +0200
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
|
187
-------------------------------------------------------------------------------
D
|
317
-------------------------------------------------------------------------------
A
|
187
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R
config/home/katja/gnomeExtensions/space-bar.nix -> config/home/zaphyra/gnomeExtensions/space-bar.nix
|
0
A
|
317
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
|
133
-------------------------------------------------------------------------------
D
|
93
-------------------------------------------------------------------------------
D
|
246
-------------------------------------------------------------------------------
D
|
71
-----------------------------------------------------------------------
D
|
122
-------------------------------------------------------------------------------
D
|
176
-------------------------------------------------------------------------------
A
|
133
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
93
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
246
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
71
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
122
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
176
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
|
109
-------------------------------------------------------------------------------
A
|
110
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
|
217
-------------------------------------------------------------------------------
A
|
217
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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/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/apostrophe.nix b/config/home/zaphyra/programs/apostrophe.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/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/javascript.nix b/config/home/zaphyra/programs/javascript.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/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/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/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/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/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/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/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/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/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/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/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: |-