From abac67afb40dd956bfb3b925a94ce2db3d4b9ee7 Mon Sep 17 00:00:00 2001 From: alexion Date: Fri, 28 Aug 2026 08:40:15 -0400 Subject: [PATCH] refactor(modules): organize module tree --- AGENTS.md | 4 +- docs/install.md | 2 +- hosts/neogaia/default.nix | 12 ++-- hosts/pikachu/default.nix | 9 ++- lib/guests.nix | 6 +- modules/default.nix | 12 ++-- .../{terminal.nix => apps/alacritty.nix} | 4 +- modules/desktop/{ => apps}/firefox.nix | 4 +- modules/desktop/{ => apps}/obsidian.nix | 4 +- modules/desktop/{ => apps}/steam.nix | 4 +- modules/desktop/default.nix | 30 ++++++++++ modules/desktop/desktop.nix | 30 ---------- .../hyprland/default.nix} | 4 +- .../{ => session}/hyprland/hypridle.nix | 4 +- .../{ => session}/hyprland/hyprlock.nix | 4 +- modules/desktop/{ => session}/login.nix | 4 +- modules/desktop/{ => session}/mako.nix | 4 +- modules/desktop/{ => session}/portals.nix | 4 +- modules/desktop/{ => session}/rofi.nix | 4 +- modules/desktop/{ => session}/waybar.nix | 4 +- modules/desktop/{ => utilities}/audio.nix | 4 +- modules/desktop/{ => utilities}/clipboard.nix | 4 +- modules/desktop/{ => utilities}/osd.nix | 4 +- modules/desktop/{ => utilities}/recording.nix | 4 +- .../desktop/{ => utilities}/screenshot.nix | 4 +- modules/desktop/{ => utilities}/theming.nix | 4 +- modules/desktop/{ => utilities}/userdirs.nix | 4 +- modules/guest.nix | 4 +- modules/{ => network}/ssh.nix | 8 +-- modules/{network.nix => network/vlans.nix} | 56 +++++++++---------- modules/{ => shell}/direnv.nix | 4 +- modules/{ => shell}/fish/config.fish | 0 modules/{ => shell}/fish/fish.nix | 4 +- modules/{ => shell}/fish/functions/copy.fish | 0 .../{ => shell}/fish/functions/deploy-to.fish | 0 modules/{ => shell}/git.nix | 4 +- modules/{agents => shell}/herdr.nix | 4 +- modules/{ => shell}/nvim/config.lua | 0 modules/{ => shell}/nvim/nvim.nix | 4 +- modules/{ => shell}/tmux/extra.conf | 0 modules/{ => shell}/tmux/tmux.nix | 4 +- 41 files changed, 133 insertions(+), 140 deletions(-) rename modules/desktop/{terminal.nix => apps/alacritty.nix} (58%) rename modules/desktop/{ => apps}/firefox.nix (96%) rename modules/desktop/{ => apps}/obsidian.nix (58%) rename modules/desktop/{ => apps}/steam.nix (71%) create mode 100644 modules/desktop/default.nix delete mode 100644 modules/desktop/desktop.nix rename modules/desktop/{hyprland/hyprland.nix => session/hyprland/default.nix} (98%) rename modules/desktop/{ => session}/hyprland/hypridle.nix (94%) rename modules/desktop/{ => session}/hyprland/hyprlock.nix (94%) rename modules/desktop/{ => session}/login.nix (73%) rename modules/desktop/{ => session}/mako.nix (88%) rename modules/desktop/{ => session}/portals.nix (87%) rename modules/desktop/{ => session}/rofi.nix (92%) rename modules/desktop/{ => session}/waybar.nix (97%) rename modules/desktop/{ => utilities}/audio.nix (69%) rename modules/desktop/{ => utilities}/clipboard.nix (90%) rename modules/desktop/{ => utilities}/osd.nix (87%) rename modules/desktop/{ => utilities}/recording.nix (91%) rename modules/desktop/{ => utilities}/screenshot.nix (91%) rename modules/desktop/{ => utilities}/theming.nix (95%) rename modules/desktop/{ => utilities}/userdirs.nix (70%) rename modules/{ => network}/ssh.nix (97%) rename modules/{network.nix => network/vlans.nix} (58%) rename modules/{ => shell}/direnv.nix (87%) rename modules/{ => shell}/fish/config.fish (100%) rename modules/{ => shell}/fish/fish.nix (98%) rename modules/{ => shell}/fish/functions/copy.fish (100%) rename modules/{ => shell}/fish/functions/deploy-to.fish (100%) rename modules/{ => shell}/git.nix (89%) rename modules/{agents => shell}/herdr.nix (87%) rename modules/{ => shell}/nvim/config.lua (100%) rename modules/{ => shell}/nvim/nvim.nix (97%) rename modules/{ => shell}/tmux/extra.conf (100%) rename modules/{ => shell}/tmux/tmux.nix (84%) diff --git a/AGENTS.md b/AGENTS.md index 66bf32e..9281194 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,11 +18,11 @@ One flake builds every machine I own. ### Desktop -- When adding a graphical application, add a `window-rewrite` icon mapping in `modules/desktop/waybar.nix`. +- When adding a graphical application, add a `window-rewrite` icon mapping in `modules/desktop/session/waybar.nix`. The workspace indicator uses this mapping to show an application icon instead of the generic default glyph. Match the mapping on the window class. Run `hyprctl clients -j | jq -r '.[].class' | sort -u` to list classes in the running session. -- Set Hyprland session environment variables in `modules/desktop/hyprland/hyprland.nix` with `env = KEY,VALUE`. +- Set Hyprland session environment variables in `modules/desktop/session/hyprland/default.nix` with `env = KEY,VALUE`. `home.sessionVariables` do **not** reach the Hyprland session because UWSM does not source `hm-session-vars.sh`. Source cursor values from `config.stylix.cursor`. Set `XCURSOR_*` and `HYPRCURSOR_*` to the same theme for Bibata. diff --git a/docs/install.md b/docs/install.md index 5c411d9..3426334 100644 --- a/docs/install.md +++ b/docs/install.md @@ -171,7 +171,7 @@ Then populate that file, which needs no existing identity because encrypting onl $ nix run nixpkgs#sops -- secrets/newhost.yaml ``` -A host with `modules.ssh.enable` expects one entry per key type, named `ssh-host--key`, each holding a private key generated with `ssh-keygen -t -N "" -f /tmp/`. +A host with `modules.network.ssh.enable` expects one entry per key type, named `ssh-host--key`, each holding a private key generated with `ssh-keygen -t -N "" -f /tmp/`. The build fails at evaluation if a declared secret is absent from the file, so a host that enables the daemon without these will not install. Commit the matching public halves beside the host's configuration in plaintext, since publishing them is their purpose. diff --git a/hosts/neogaia/default.nix b/hosts/neogaia/default.nix index b73669a..41d0d9e 100644 --- a/hosts/neogaia/default.nix +++ b/hosts/neogaia/default.nix @@ -36,9 +36,9 @@ # So setup can be driven over the network. # The matching host public keys sit beside this file in plaintext, since # publishing them is their purpose. - modules.ssh.enable = true; - modules.ssh.hostKeys.sopsFile = ../../secrets/neogaia.yaml; - modules.ssh.userKey.sopsFile = ../../secrets/neogaia.yaml; + modules.network.ssh.enable = true; + modules.network.ssh.hostKeys.sopsFile = ../../secrets/neogaia.yaml; + modules.network.ssh.userKey.sopsFile = ../../secrets/neogaia.yaml; # The walking-skeleton guest, enabled like any module: proves the guest path # end to end through this host's `nix flake check`. @@ -60,13 +60,13 @@ tasksMax = 512; }; - modules.agents.herdr.enable = true; + modules.shell.herdr.enable = true; modules.agents.tools.gitea-axi.enable = true; modules.agents.pi.enable = true; modules.desktop.enable = true; - modules.desktop.obsidian.enable = true; - modules.desktop.steam.enable = true; + modules.desktop.apps.obsidian.enable = true; + modules.desktop.apps.steam.enable = true; time.timeZone = "America/New_York"; i18n.defaultLocale = "en_GB.UTF-8"; diff --git a/hosts/pikachu/default.nix b/hosts/pikachu/default.nix index 724de55..21908b5 100644 --- a/hosts/pikachu/default.nix +++ b/hosts/pikachu/default.nix @@ -62,7 +62,7 @@ }; networking.useDHCP = false; - modules.network.vlans = [ 20 ]; + modules.network.vlans.ids = [ 20 ]; boot.zfs.forceImportRoot = false; @@ -74,11 +74,10 @@ registry.address.pikachu.self = "10.23.10.102"; - modules.ssh.enable = true; - modules.ssh.hostKeys.sopsFile = ../../secrets/pikachu.yaml; - modules.ssh.userKey.sopsFile = ../../secrets/pikachu.yaml; + modules.network.ssh.enable = true; + modules.network.ssh.hostKeys.sopsFile = ../../secrets/pikachu.yaml; + modules.network.ssh.userKey.sopsFile = ../../secrets/pikachu.yaml; - modules.git.enable = true; guests.actualbudget = { enable = true; vlan = 20; diff --git a/lib/guests.nix b/lib/guests.nix index ba1a78f..6822f3b 100644 --- a/lib/guests.nix +++ b/lib/guests.nix @@ -108,7 +108,7 @@ let The tagged VLAN this guest lives on. The guest attaches to its host's `br-vlan` bridge for that VLAN. Left null, the guest keeps a private network with no bridge attachment. The id must be one of the - host's `modules.network.vlans`. + host's `modules.network.vlans.ids`. ''; }; mac = lib.mkOption { @@ -301,9 +301,9 @@ let ''; } { - assertion = !networked || lib.elem cfg.vlan config.modules.network.vlans; + assertion = !networked || lib.elem cfg.vlan config.modules.network.vlans.ids; message = '' - guests.${name}.vlan = ${toString cfg.vlan} is not among its host's modules.network.vlans (${lib.concatMapStringsSep ", " toString config.modules.network.vlans}). Declare the VLAN on the host or correct the guest's placement. + guests.${name}.vlan = ${toString cfg.vlan} is not among its host's modules.network.vlans.ids (${lib.concatMapStringsSep ", " toString config.modules.network.vlans.ids}). Declare the VLAN on the host or correct the guest's placement. ''; } ]; diff --git a/modules/default.nix b/modules/default.nix index d5910ba..1c1310a 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -116,11 +116,11 @@ in cleanup = "sudo nix-collect-garbage -d"; }; - modules.fish.enable = lib.mkDefault true; - modules.fish.defaultShell = lib.mkDefault true; - modules.tmux.enable = lib.mkDefault true; - modules.nvim.enable = lib.mkDefault true; - modules.git.enable = lib.mkDefault true; - modules.direnv.enable = lib.mkDefault true; + modules.shell.fish.enable = lib.mkDefault true; + modules.shell.fish.defaultShell = lib.mkDefault true; + modules.shell.tmux.enable = lib.mkDefault true; + modules.shell.nvim.enable = lib.mkDefault true; + modules.shell.git.enable = lib.mkDefault true; + modules.shell.direnv.enable = lib.mkDefault true; }; } diff --git a/modules/desktop/terminal.nix b/modules/desktop/apps/alacritty.nix similarity index 58% rename from modules/desktop/terminal.nix rename to modules/desktop/apps/alacritty.nix index 58074bc..589d498 100644 --- a/modules/desktop/terminal.nix +++ b/modules/desktop/apps/alacritty.nix @@ -6,11 +6,11 @@ }: # Alacritty as the desktop terminal. let - cfg = config.modules.desktop.terminal; + cfg = config.modules.desktop.apps.alacritty; user = config.user.name; in { - options.modules.desktop.terminal.enable = lib.mkEnableOption "Alacritty as the desktop terminal"; + options.modules.desktop.apps.alacritty.enable = lib.mkEnableOption "Alacritty as the desktop terminal"; config = lib.mkIf cfg.enable { home-manager.users.${user}.home.packages = [ pkgs.alacritty ]; diff --git a/modules/desktop/firefox.nix b/modules/desktop/apps/firefox.nix similarity index 96% rename from modules/desktop/firefox.nix rename to modules/desktop/apps/firefox.nix index 227dc82..801ecbc 100644 --- a/modules/desktop/firefox.nix +++ b/modules/desktop/apps/firefox.nix @@ -7,12 +7,12 @@ }: # Firefox as the desktop browser: stock mainline, hardened and de-monetized by policy. let - cfg = config.modules.desktop.firefox; + cfg = config.modules.desktop.apps.firefox; user = config.user.name; firefoxAddons = inputs.firefox-addons.packages.${pkgs.stdenv.hostPlatform.system}; in { - options.modules.desktop.firefox.enable = lib.mkEnableOption "Firefox as the desktop browser"; + options.modules.desktop.apps.firefox.enable = lib.mkEnableOption "Firefox as the desktop browser"; config = lib.mkIf cfg.enable { home-manager.users.${user} = hm: { diff --git a/modules/desktop/obsidian.nix b/modules/desktop/apps/obsidian.nix similarity index 58% rename from modules/desktop/obsidian.nix rename to modules/desktop/apps/obsidian.nix index 90fdd52..46b38da 100644 --- a/modules/desktop/obsidian.nix +++ b/modules/desktop/apps/obsidian.nix @@ -6,11 +6,11 @@ }: # Obsidian as the desktop note-taking vault. let - cfg = config.modules.desktop.obsidian; + cfg = config.modules.desktop.apps.obsidian; user = config.user.name; in { - options.modules.desktop.obsidian.enable = lib.mkEnableOption "Obsidian as the desktop note-taking vault"; + options.modules.desktop.apps.obsidian.enable = lib.mkEnableOption "Obsidian as the desktop note-taking vault"; config = lib.mkIf cfg.enable { home-manager.users.${user}.home.packages = [ pkgs.obsidian ]; diff --git a/modules/desktop/steam.nix b/modules/desktop/apps/steam.nix similarity index 71% rename from modules/desktop/steam.nix rename to modules/desktop/apps/steam.nix index 3a3e179..78a86a1 100644 --- a/modules/desktop/steam.nix +++ b/modules/desktop/apps/steam.nix @@ -6,10 +6,10 @@ }: # Steam game launcher and runtime integration. let - cfg = config.modules.desktop.steam; + cfg = config.modules.desktop.apps.steam; in { - options.modules.desktop.steam.enable = lib.mkEnableOption "Steam game launcher"; + options.modules.desktop.apps.steam.enable = lib.mkEnableOption "Steam game launcher"; config = lib.mkIf cfg.enable { programs.steam = { diff --git a/modules/desktop/default.nix b/modules/desktop/default.nix new file mode 100644 index 0000000..c997371 --- /dev/null +++ b/modules/desktop/default.nix @@ -0,0 +1,30 @@ +{ config, lib, ... }: +# The desktop aggregator: one flag brings up the whole graphical session. +let + cfg = config.modules.desktop; +in +{ + options.modules.desktop.enable = lib.mkEnableOption "the keyboard-driven Hyprland desktop"; + + # Each piece is turned on at default priority, so a host can still override + # any one of them while the single flag above enables the whole desktop. + config = lib.mkIf cfg.enable { + modules.desktop.apps.alacritty.enable = lib.mkDefault true; + modules.desktop.apps.firefox.enable = lib.mkDefault true; + modules.desktop.session.hyprland.enable = lib.mkDefault true; + modules.desktop.session.hyprland.hypridle.enable = lib.mkDefault true; + modules.desktop.session.hyprland.hyprlock.enable = lib.mkDefault true; + modules.desktop.session.login.enable = lib.mkDefault true; + modules.desktop.session.mako.enable = lib.mkDefault true; + modules.desktop.session.portals.enable = lib.mkDefault true; + modules.desktop.session.rofi.enable = lib.mkDefault true; + modules.desktop.session.waybar.enable = lib.mkDefault true; + modules.desktop.utilities.audio.enable = lib.mkDefault true; + modules.desktop.utilities.clipboard.enable = lib.mkDefault true; + modules.desktop.utilities.osd.enable = lib.mkDefault true; + modules.desktop.utilities.recording.enable = lib.mkDefault true; + modules.desktop.utilities.screenshot.enable = lib.mkDefault true; + modules.desktop.utilities.theming.enable = lib.mkDefault true; + modules.desktop.utilities.userdirs.enable = lib.mkDefault true; + }; +} diff --git a/modules/desktop/desktop.nix b/modules/desktop/desktop.nix deleted file mode 100644 index 78c3d5d..0000000 --- a/modules/desktop/desktop.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ config, lib, ... }: -# The desktop aggregator: one flag brings up the whole graphical session. -let - cfg = config.modules.desktop; -in -{ - options.modules.desktop.enable = lib.mkEnableOption "the keyboard-driven Hyprland desktop"; - - # Each piece is turned on at default priority, so a host can still override - # any one of them while the single flag above enables the whole desktop. - config = lib.mkIf cfg.enable { - modules.desktop.clipboard.enable = lib.mkDefault true; - modules.desktop.firefox.enable = lib.mkDefault true; - modules.desktop.hyprland.enable = lib.mkDefault true; - modules.desktop.hyprland.hyprlock.enable = lib.mkDefault true; - modules.desktop.hyprland.hypridle.enable = lib.mkDefault true; - modules.desktop.login.enable = lib.mkDefault true; - modules.desktop.mako.enable = lib.mkDefault true; - modules.desktop.portals.enable = lib.mkDefault true; - modules.desktop.recording.enable = lib.mkDefault true; - modules.desktop.rofi.enable = lib.mkDefault true; - modules.desktop.screenshot.enable = lib.mkDefault true; - modules.desktop.terminal.enable = lib.mkDefault true; - modules.desktop.userdirs.enable = lib.mkDefault true; - modules.desktop.theming.enable = lib.mkDefault true; - modules.desktop.waybar.enable = lib.mkDefault true; - modules.desktop.audio.enable = lib.mkDefault true; - modules.desktop.osd.enable = lib.mkDefault true; - }; -} diff --git a/modules/desktop/hyprland/hyprland.nix b/modules/desktop/session/hyprland/default.nix similarity index 98% rename from modules/desktop/hyprland/hyprland.nix rename to modules/desktop/session/hyprland/default.nix index 38ab7a9..a2ac9d6 100644 --- a/modules/desktop/hyprland/hyprland.nix +++ b/modules/desktop/session/hyprland/default.nix @@ -6,7 +6,7 @@ }: # The Hyprland compositor. let - cfg = config.modules.desktop.hyprland; + cfg = config.modules.desktop.session.hyprland; user = config.user.name; cursor = config.stylix.cursor; @@ -27,7 +27,7 @@ let ''; in { - options.modules.desktop.hyprland = { + options.modules.desktop.session.hyprland = { enable = lib.mkEnableOption "the Hyprland compositor"; blur = lib.mkEnableOption '' diff --git a/modules/desktop/hyprland/hypridle.nix b/modules/desktop/session/hyprland/hypridle.nix similarity index 94% rename from modules/desktop/hyprland/hypridle.nix rename to modules/desktop/session/hyprland/hypridle.nix index 61acc9c..96411e3 100644 --- a/modules/desktop/hyprland/hypridle.nix +++ b/modules/desktop/session/hyprland/hypridle.nix @@ -6,7 +6,7 @@ }: # hypridle: idle-triggered locking and display power management. let - cfg = config.modules.desktop.hyprland.hypridle; + cfg = config.modules.desktop.session.hyprland.hypridle; user = config.user.name; hyprctl = "${config.programs.hyprland.package}/bin/hyprctl"; @@ -17,7 +17,7 @@ let lockCmd = "${pkgs.procps}/bin/pidof hyprlock || ${hyprlock}"; in { - options.modules.desktop.hyprland.hypridle = { + options.modules.desktop.session.hyprland.hypridle = { enable = lib.mkEnableOption "hypridle idle management"; lockTimeout = lib.mkOption { diff --git a/modules/desktop/hyprland/hyprlock.nix b/modules/desktop/session/hyprland/hyprlock.nix similarity index 94% rename from modules/desktop/hyprland/hyprlock.nix rename to modules/desktop/session/hyprland/hyprlock.nix index 3656648..c7e58ed 100644 --- a/modules/desktop/hyprland/hyprlock.nix +++ b/modules/desktop/session/hyprland/hyprlock.nix @@ -6,7 +6,7 @@ }: # The lock screen: a hyprlock session-lock surface the compositor owns. let - cfg = config.modules.desktop.hyprland.hyprlock; + cfg = config.modules.desktop.session.hyprland.hyprlock; user = config.user.name; # The hyprlock this module installs, used by the lock keybind below. @@ -45,7 +45,7 @@ let ''; in { - options.modules.desktop.hyprland.hyprlock.enable = lib.mkEnableOption "the hyprlock lock screen"; + options.modules.desktop.session.hyprland.hyprlock.enable = lib.mkEnableOption "the hyprlock lock screen"; config = lib.mkIf cfg.enable { home-manager.users.${user} = { diff --git a/modules/desktop/login.nix b/modules/desktop/session/login.nix similarity index 73% rename from modules/desktop/login.nix rename to modules/desktop/session/login.nix index a5551c0..ec9e4c5 100644 --- a/modules/desktop/login.nix +++ b/modules/desktop/session/login.nix @@ -7,10 +7,10 @@ # Text login: greetd running the tuigreet greeter, which starts the session # through the universal Wayland session manager. let - cfg = config.modules.desktop.login; + cfg = config.modules.desktop.session.login; in { - options.modules.desktop.login.enable = lib.mkEnableOption "greetd with the tuigreet text greeter"; + options.modules.desktop.session.login.enable = lib.mkEnableOption "greetd with the tuigreet text greeter"; config = lib.mkIf cfg.enable { services.greetd = { diff --git a/modules/desktop/mako.nix b/modules/desktop/session/mako.nix similarity index 88% rename from modules/desktop/mako.nix rename to modules/desktop/session/mako.nix index cf0d90a..fc1829f 100644 --- a/modules/desktop/mako.nix +++ b/modules/desktop/session/mako.nix @@ -6,13 +6,13 @@ }: # mako as the notification daemon: toasts, a do-not-disturb mode, and history recall. let - cfg = config.modules.desktop.mako; + cfg = config.modules.desktop.session.mako; user = config.user.name; makoctl = "${pkgs.mako}/bin/makoctl"; in { - options.modules.desktop.mako.enable = lib.mkEnableOption "the mako notification daemon"; + options.modules.desktop.session.mako.enable = lib.mkEnableOption "the mako notification daemon"; config = lib.mkIf cfg.enable { home-manager.users.${user} = { diff --git a/modules/desktop/portals.nix b/modules/desktop/session/portals.nix similarity index 87% rename from modules/desktop/portals.nix rename to modules/desktop/session/portals.nix index a2124a6..cd156a8 100644 --- a/modules/desktop/portals.nix +++ b/modules/desktop/session/portals.nix @@ -1,10 +1,10 @@ { config, lib, ... }: # XDG desktop portal routing for in-app screen sharing and file dialogs. let - cfg = config.modules.desktop.portals; + cfg = config.modules.desktop.session.portals; in { - options.modules.desktop.portals.enable = + options.modules.desktop.session.portals.enable = lib.mkEnableOption "XDG desktop portals for in-app screen sharing and file dialogs"; config = lib.mkIf cfg.enable { diff --git a/modules/desktop/rofi.nix b/modules/desktop/session/rofi.nix similarity index 92% rename from modules/desktop/rofi.nix rename to modules/desktop/session/rofi.nix index 6e4b8cd..8a62c56 100644 --- a/modules/desktop/rofi.nix +++ b/modules/desktop/session/rofi.nix @@ -6,7 +6,7 @@ }: # rofi as the desktop launcher and dmenu-style menu frontend. let - cfg = config.modules.desktop.rofi; + cfg = config.modules.desktop.session.rofi; user = config.user.name; # A session menu built on the same themed rofi, so the power actions look @@ -24,7 +24,7 @@ let ''; in { - options.modules.desktop.rofi.enable = lib.mkEnableOption "the rofi launcher"; + options.modules.desktop.session.rofi.enable = lib.mkEnableOption "the rofi launcher"; config = lib.mkIf cfg.enable { home-manager.users.${user} = { diff --git a/modules/desktop/waybar.nix b/modules/desktop/session/waybar.nix similarity index 97% rename from modules/desktop/waybar.nix rename to modules/desktop/session/waybar.nix index 9dfd721..85581d5 100644 --- a/modules/desktop/waybar.nix +++ b/modules/desktop/session/waybar.nix @@ -6,7 +6,7 @@ }: # Waybar: a top status bar reading system state at a glance. let - cfg = config.modules.desktop.waybar; + cfg = config.modules.desktop.session.waybar; user = config.user.name; # A Nerd Font Private-Use-Area codepoint as a literal character, decoded @@ -49,7 +49,7 @@ let ''; in { - options.modules.desktop.waybar.enable = lib.mkEnableOption "the Waybar status bar"; + options.modules.desktop.session.waybar.enable = lib.mkEnableOption "the Waybar status bar"; config = lib.mkIf cfg.enable { # A symbols font backs the module glyphs, so pango falls back to it for the diff --git a/modules/desktop/audio.nix b/modules/desktop/utilities/audio.nix similarity index 69% rename from modules/desktop/audio.nix rename to modules/desktop/utilities/audio.nix index 82ff4c1..0412bc9 100644 --- a/modules/desktop/audio.nix +++ b/modules/desktop/utilities/audio.nix @@ -1,10 +1,10 @@ { config, lib, ... }: # PipeWire as the desktop audio server. let - cfg = config.modules.desktop.audio; + cfg = config.modules.desktop.utilities.audio; in { - options.modules.desktop.audio.enable = lib.mkEnableOption "the PipeWire audio server"; + options.modules.desktop.utilities.audio.enable = lib.mkEnableOption "the PipeWire audio server"; config = lib.mkIf cfg.enable { # Realtime scheduling for the audio threads, so playback survives load. diff --git a/modules/desktop/clipboard.nix b/modules/desktop/utilities/clipboard.nix similarity index 90% rename from modules/desktop/clipboard.nix rename to modules/desktop/utilities/clipboard.nix index d993abf..4eae7af 100644 --- a/modules/desktop/clipboard.nix +++ b/modules/desktop/utilities/clipboard.nix @@ -6,7 +6,7 @@ }: # Clipboard history: cliphist records every copy, picked back through rofi. let - cfg = config.modules.desktop.clipboard; + cfg = config.modules.desktop.utilities.clipboard; user = config.user.name; cliphist = "${pkgs.cliphist}/bin/cliphist"; @@ -25,7 +25,7 @@ let ''; in { - options.modules.desktop.clipboard.enable = lib.mkEnableOption "cliphist clipboard history"; + options.modules.desktop.utilities.clipboard.enable = lib.mkEnableOption "cliphist clipboard history"; config = lib.mkIf cfg.enable { home-manager.users.${user} = { diff --git a/modules/desktop/osd.nix b/modules/desktop/utilities/osd.nix similarity index 87% rename from modules/desktop/osd.nix rename to modules/desktop/utilities/osd.nix index bf97bc7..6e231eb 100644 --- a/modules/desktop/osd.nix +++ b/modules/desktop/utilities/osd.nix @@ -6,11 +6,11 @@ }: # SwayOSD: a transient on-screen popup for volume and brightness changes. let - cfg = config.modules.desktop.osd; + cfg = config.modules.desktop.utilities.osd; user = config.user.name; in { - options.modules.desktop.osd.enable = lib.mkEnableOption "the SwayOSD volume and brightness popup"; + options.modules.desktop.utilities.osd.enable = lib.mkEnableOption "the SwayOSD volume and brightness popup"; config = lib.mkIf cfg.enable { environment.systemPackages = [ pkgs.swayosd ]; diff --git a/modules/desktop/recording.nix b/modules/desktop/utilities/recording.nix similarity index 91% rename from modules/desktop/recording.nix rename to modules/desktop/utilities/recording.nix index 0493836..f35b2d3 100644 --- a/modules/desktop/recording.nix +++ b/modules/desktop/utilities/recording.nix @@ -6,7 +6,7 @@ }: # Keybound screen recording: pick a region, then toggle a video-only capture. let - cfg = config.modules.desktop.recording; + cfg = config.modules.desktop.utilities.recording; user = config.user.name; slurp = "${pkgs.slurp}/bin/slurp"; @@ -41,7 +41,7 @@ let ''; in { - options.modules.desktop.recording.enable = lib.mkEnableOption "wf-recorder screen recording"; + options.modules.desktop.utilities.recording.enable = lib.mkEnableOption "wf-recorder screen recording"; config = lib.mkIf cfg.enable { home-manager.users.${user} = { diff --git a/modules/desktop/screenshot.nix b/modules/desktop/utilities/screenshot.nix similarity index 91% rename from modules/desktop/screenshot.nix rename to modules/desktop/utilities/screenshot.nix index 8d6a346..44134d7 100644 --- a/modules/desktop/screenshot.nix +++ b/modules/desktop/utilities/screenshot.nix @@ -7,7 +7,7 @@ # Keyboard-driven screenshots that open in satty for annotation, then land in # both the clipboard and a dated file. let - cfg = config.modules.desktop.screenshot; + cfg = config.modules.desktop.utilities.screenshot; user = config.user.name; grimblast = "${pkgs.grimblast}/bin/grimblast"; @@ -32,7 +32,7 @@ let ''; in { - options.modules.desktop.screenshot.enable = lib.mkEnableOption "screenshots via grimblast and satty"; + options.modules.desktop.utilities.screenshot.enable = lib.mkEnableOption "screenshots via grimblast and satty"; config = lib.mkIf cfg.enable { home-manager.users.${user} = { diff --git a/modules/desktop/theming.nix b/modules/desktop/utilities/theming.nix similarity index 95% rename from modules/desktop/theming.nix rename to modules/desktop/utilities/theming.nix index ea03729..6c7768d 100644 --- a/modules/desktop/theming.nix +++ b/modules/desktop/utilities/theming.nix @@ -6,7 +6,7 @@ }: # Nord theming for the graphical layer, driven from one base16 scheme by Stylix. let - cfg = config.modules.desktop.theming; + cfg = config.modules.desktop.utilities.theming; user = config.user.name; # A single static Nord wallpaper, drawn as a vertical gradient across the @@ -18,7 +18,7 @@ let ''; in { - options.modules.desktop.theming.enable = + options.modules.desktop.utilities.theming.enable = lib.mkEnableOption "Nord theming of the graphical layer via Stylix"; config = lib.mkIf cfg.enable { diff --git a/modules/desktop/userdirs.nix b/modules/desktop/utilities/userdirs.nix similarity index 70% rename from modules/desktop/userdirs.nix rename to modules/desktop/utilities/userdirs.nix index 6d10a8b..7909f10 100644 --- a/modules/desktop/userdirs.nix +++ b/modules/desktop/utilities/userdirs.nix @@ -2,11 +2,11 @@ # Declares the XDG user directories, so a tool that queries them lands in a # well-known folder a host can relocate from one place. let - cfg = config.modules.desktop.userdirs; + cfg = config.modules.desktop.utilities.userdirs; user = config.user.name; in { - options.modules.desktop.userdirs.enable = lib.mkEnableOption "XDG user directories"; + options.modules.desktop.utilities.userdirs.enable = lib.mkEnableOption "XDG user directories"; config = lib.mkIf cfg.enable { # Write ~/.config/user-dirs.dirs from the option defaults. diff --git a/modules/guest.nix b/modules/guest.nix index 57b1070..b778b80 100644 --- a/modules/guest.nix +++ b/modules/guest.nix @@ -8,7 +8,7 @@ in config = lib.mkIf cfg.enable { system.stateVersion = "26.05"; - modules.ssh.enable = lib.mkDefault true; - modules.ssh.hostKeys.restore = lib.mkDefault false; + modules.network.ssh.enable = lib.mkDefault true; + modules.network.ssh.hostKeys.restore = lib.mkDefault false; }; } diff --git a/modules/ssh.nix b/modules/network/ssh.nix similarity index 97% rename from modules/ssh.nix rename to modules/network/ssh.nix index 68f8757..cb86f8a 100644 --- a/modules/ssh.nix +++ b/modules/network/ssh.nix @@ -6,7 +6,7 @@ }: # SSH on this machine, in both directions. let - cfg = config.modules.ssh; + cfg = config.modules.network.ssh; user = config.user.name; inherit (lib) @@ -153,7 +153,7 @@ let ); in { - options.modules.ssh = { + options.modules.network.ssh = { enable = lib.mkEnableOption "the OpenSSH daemon, with host keys restored from secrets"; hosts = { @@ -226,7 +226,7 @@ in default = null; description = '' Complete override for client public keys admitted by this host. - Leave null to derive access from `modules.ssh.hosts` and `modules.ssh.targets`. + Leave null to derive access from `modules.network.ssh.hosts` and `modules.network.ssh.targets`. ''; }; @@ -304,7 +304,7 @@ in assertions = [ { assertion = cfg.hostKeys.sopsFile != null; - message = "modules.ssh.hostKeys.restore requires modules.ssh.hostKeys.sopsFile to name the encrypted host keys."; + message = "modules.network.ssh.hostKeys.restore requires modules.network.ssh.hostKeys.sopsFile to name the encrypted host keys."; } ]; diff --git a/modules/network.nix b/modules/network/vlans.nix similarity index 58% rename from modules/network.nix rename to modules/network/vlans.nix index f7e872e..cc2c929 100644 --- a/modules/network.nix +++ b/modules/network/vlans.nix @@ -6,30 +6,26 @@ }: # The host networking foundation: per-VLAN bridges over a tagged trunk. let - cfg = config.modules.network; + cfg = config.modules.network.vlans; - # Each tagged VLAN materializes as a bridge named for its id, by the shared - # convention. inherit (my) bridgeName; - # The tagged sub-interface stacked on the trunk that feeds one bridge. vlanName = id: "${cfg.trunk}.${toString id}"; in { - options.modules.network = { - enable = - lib.mkEnableOption "the host trunk, its tagged-VLAN bridges, and the host management address"; + options.modules.network.vlans = { + enable = lib.mkEnableOption "host VLAN bridges over a tagged trunk"; trunk = lib.mkOption { type = lib.types.str; example = "enp1s0"; description = '' - The physical interface carrying 802.1Q-tagged traffic for every VLAN. - Each declared VLAN is stacked on it and enslaved to its own bridge. + Physical interface that carries 802.1Q-tagged traffic for every VLAN. + Each declared VLAN attaches to its own bridge. ''; }; - vlans = lib.mkOption { + ids = lib.mkOption { type = lib.types.listOf (lib.types.ints.between 1 4094); default = [ ]; example = [ @@ -38,8 +34,8 @@ in 30 ]; description = '' - The tagged VLAN ids to materialize. Each id N emits exactly one bridge - named `br-vlanN`, and guests on VLAN N attach to it. + Tagged VLAN ids to materialize. + Each id N creates one bridge named `br-vlanN`. ''; }; @@ -48,9 +44,9 @@ in type = lib.types.nullOr (lib.types.ints.between 1 4094); default = null; description = '' - The VLAN whose bridge carries the host's own management address; must - be one of `vlans`. Left null, the host takes no address on any bridge - and the bridges serve guests alone. + VLAN whose bridge carries the host's own management address. + The value must be one of `ids`. + Left null, the host takes no address on any bridge. ''; }; @@ -59,8 +55,8 @@ in default = null; example = "10.0.10.2/24"; description = '' - The host's static management address, in CIDR form, on the management - VLAN's bridge. Left null, the host takes its address there by DHCP. + Host static management address in CIDR form. + Left null, the host takes its management address by DHCP. ''; }; }; @@ -69,21 +65,20 @@ in config = lib.mkIf cfg.enable { assertions = [ { - assertion = cfg.management.vlan == null || lib.elem cfg.management.vlan cfg.vlans; - message = "modules.network.management.vlan (${toString cfg.management.vlan}) must name one of modules.network.vlans."; + assertion = cfg.management.vlan == null || lib.elem cfg.management.vlan cfg.ids; + message = "modules.network.vlans.management.vlan (${toString cfg.management.vlan}) must name one of modules.network.vlans.ids."; } { assertion = cfg.management.address == null || cfg.management.vlan != null; - message = "modules.network.management.address needs modules.network.management.vlan to say which bridge carries it."; + message = "modules.network.vlans.management.address needs modules.network.vlans.management.vlan to say which bridge carries it."; } ]; - # networkd owns the trunk, its VLAN sub-interfaces, and the bridges, so a host - # also running NetworkManager leaves them to networkd rather than contending. + # networkd owns these interfaces so NetworkManager does not contend for them. networking.networkmanager.unmanaged = [ "interface-name:${cfg.trunk}" ] - ++ map (id: "interface-name:${bridgeName id}") cfg.vlans - ++ map (id: "interface-name:${vlanName id}") cfg.vlans; + ++ map (id: "interface-name:${bridgeName id}") cfg.ids + ++ map (id: "interface-name:${vlanName id}") cfg.ids; systemd.network = { enable = true; @@ -103,19 +98,18 @@ in }; vlanConfig.Id = id; }; - }) cfg.vlans + }) cfg.ids ); networks = lib.mkMerge ( [ - # The trunk carries only tagged frames up to the sub-interfaces and - # takes no address of its own. + # The trunk carries only tagged frames and takes no address. { "30-${cfg.trunk}" = { matchConfig.Name = cfg.trunk; networkConfig.LinkLocalAddressing = "no"; linkConfig.RequiredForOnline = "no"; - vlan = map vlanName cfg.vlans; + vlan = map vlanName cfg.ids; }; } ] @@ -126,8 +120,8 @@ in networkConfig.Bridge = bridgeName id; linkConfig.RequiredForOnline = "no"; }; - # The management VLAN's bridge carries the host address; every other - # bridge is a plain L2 segment for guests. + # The management bridge carries the host address. + # Other bridges provide L2 segments for guests. "40-${bridgeName id}" = lib.mkMerge [ { matchConfig.Name = bridgeName id; @@ -140,7 +134,7 @@ in { address = [ cfg.management.address ]; } )) ]; - }) cfg.vlans + }) cfg.ids ); }; }; diff --git a/modules/direnv.nix b/modules/shell/direnv.nix similarity index 87% rename from modules/direnv.nix rename to modules/shell/direnv.nix index 38738ca..acff31d 100644 --- a/modules/direnv.nix +++ b/modules/shell/direnv.nix @@ -5,11 +5,11 @@ }: # direnv for the primary user, configured through home-manager. let - cfg = config.modules.direnv; + cfg = config.modules.shell.direnv; user = config.user.name; in { - options.modules.direnv.enable = + options.modules.shell.direnv.enable = lib.mkEnableOption "direnv for the primary user, with nix-direnv shell caching"; config = lib.mkIf cfg.enable { diff --git a/modules/fish/config.fish b/modules/shell/fish/config.fish similarity index 100% rename from modules/fish/config.fish rename to modules/shell/fish/config.fish diff --git a/modules/fish/fish.nix b/modules/shell/fish/fish.nix similarity index 98% rename from modules/fish/fish.nix rename to modules/shell/fish/fish.nix index 67fbcd8..c5063b4 100644 --- a/modules/fish/fish.nix +++ b/modules/shell/fish/fish.nix @@ -6,13 +6,13 @@ }: # fish for the primary user, configured through home-manager. let - cfg = config.modules.fish; + cfg = config.modules.shell.fish; user = config.user.name; shortcuts = config.registry.shell-shortcut.${config.networking.hostName}; commandsOf = shortcuts: lib.mapAttrs (_name: shortcut: shortcut.command) shortcuts; in { - options.modules.fish = { + options.modules.shell.fish = { enable = lib.mkEnableOption "fish as the user's shell, configured via home-manager"; defaultShell = lib.mkOption { diff --git a/modules/fish/functions/copy.fish b/modules/shell/fish/functions/copy.fish similarity index 100% rename from modules/fish/functions/copy.fish rename to modules/shell/fish/functions/copy.fish diff --git a/modules/fish/functions/deploy-to.fish b/modules/shell/fish/functions/deploy-to.fish similarity index 100% rename from modules/fish/functions/deploy-to.fish rename to modules/shell/fish/functions/deploy-to.fish diff --git a/modules/git.nix b/modules/shell/git.nix similarity index 89% rename from modules/git.nix rename to modules/shell/git.nix index bce1c24..88b6bcf 100644 --- a/modules/git.nix +++ b/modules/shell/git.nix @@ -5,11 +5,11 @@ }: # git for the primary user, configured through home-manager. let - cfg = config.modules.git; + cfg = config.modules.shell.git; user = config.user.name; in { - options.modules.git.enable = + options.modules.shell.git.enable = lib.mkEnableOption "git for the primary user, carrying the operator's commit identity"; config = lib.mkIf cfg.enable { diff --git a/modules/agents/herdr.nix b/modules/shell/herdr.nix similarity index 87% rename from modules/agents/herdr.nix rename to modules/shell/herdr.nix index 6669b26..bd965df 100644 --- a/modules/agents/herdr.nix +++ b/modules/shell/herdr.nix @@ -6,11 +6,11 @@ }: # Herdr, a terminal multiplexer for coding agents. let - cfg = config.modules.agents.herdr; + cfg = config.modules.shell.herdr; user = config.user.name; in { - options.modules.agents.herdr.enable = lib.mkEnableOption "Herdr, a terminal multiplexer for coding agents"; + options.modules.shell.herdr.enable = lib.mkEnableOption "Herdr, a terminal multiplexer for coding agents"; config = lib.mkIf cfg.enable { registry.shell-shortcut.${config.networking.hostName}.hs = "herdr --session"; diff --git a/modules/nvim/config.lua b/modules/shell/nvim/config.lua similarity index 100% rename from modules/nvim/config.lua rename to modules/shell/nvim/config.lua diff --git a/modules/nvim/nvim.nix b/modules/shell/nvim/nvim.nix similarity index 97% rename from modules/nvim/nvim.nix rename to modules/shell/nvim/nvim.nix index a2e3d96..fdcb34d 100644 --- a/modules/nvim/nvim.nix +++ b/modules/shell/nvim/nvim.nix @@ -7,11 +7,11 @@ }: # Neovim for the primary user, configured declaratively through nixvim. let - cfg = config.modules.nvim; + cfg = config.modules.shell.nvim; user = config.user.name; in { - options.modules.nvim.enable = lib.mkEnableOption "Neovim, configured declaratively via nixvim"; + options.modules.shell.nvim.enable = lib.mkEnableOption "Neovim, configured declaratively via nixvim"; config = lib.mkIf cfg.enable { registry.shell-shortcut.${config.networking.hostName} = { diff --git a/modules/tmux/extra.conf b/modules/shell/tmux/extra.conf similarity index 100% rename from modules/tmux/extra.conf rename to modules/shell/tmux/extra.conf diff --git a/modules/tmux/tmux.nix b/modules/shell/tmux/tmux.nix similarity index 84% rename from modules/tmux/tmux.nix rename to modules/shell/tmux/tmux.nix index 925fca8..1ff81d3 100644 --- a/modules/tmux/tmux.nix +++ b/modules/shell/tmux/tmux.nix @@ -6,11 +6,11 @@ # tmux for the primary user, configured through home-manager. # Settings without a home-manager option are read from ./extra.conf. let - cfg = config.modules.tmux; + cfg = config.modules.shell.tmux; user = config.user.name; in { - options.modules.tmux.enable = lib.mkEnableOption "tmux, configured via home-manager"; + options.modules.shell.tmux.enable = lib.mkEnableOption "tmux, configured via home-manager"; config = lib.mkIf cfg.enable { registry.shell-shortcut.${config.networking.hostName}.tmx = "tmux new-session -A -s"; -- 2.47.3