refactor(modules): organize module tree
This commit was merged in pull request #72.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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-<type>-key`, each holding a private key generated with `ssh-keygen -t <type> -N "" -f /tmp/<type>`.
|
||||
A host with `modules.network.ssh.enable` expects one entry per key type, named `ssh-host-<type>-key`, each holding a private key generated with `ssh-keygen -t <type> -N "" -f /tmp/<type>`.
|
||||
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.
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -108,7 +108,7 @@ let
|
||||
The tagged VLAN this guest lives on. The guest attaches to its host's
|
||||
`br-vlan<id>` 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.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 ];
|
||||
@@ -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: {
|
||||
@@ -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 ];
|
||||
@@ -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 = {
|
||||
30
modules/desktop/default.nix
Normal file
30
modules/desktop/default.nix
Normal file
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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 ''
|
||||
@@ -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 {
|
||||
@@ -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} = {
|
||||
@@ -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 = {
|
||||
@@ -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} = {
|
||||
@@ -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 {
|
||||
@@ -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} = {
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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} = {
|
||||
@@ -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 ];
|
||||
@@ -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} = {
|
||||
@@ -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} = {
|
||||
@@ -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 {
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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.";
|
||||
}
|
||||
];
|
||||
|
||||
@@ -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
|
||||
);
|
||||
};
|
||||
};
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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";
|
||||
@@ -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} = {
|
||||
@@ -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";
|
||||
Reference in New Issue
Block a user