# # Desktop module — import this instead of manual WM/virtualisation imports. # # Usage in hosts//default.nix: # # imports = [ # ./hardware-configuration.nix # ../../modules/desktop # ]; # # myDesktop.windowManager = "niri"; # niri (default) | sway | kde # myDesktop.cpu = "amd"; # amd | intel | none (default) # # myDesktop.virtualisation.enable = true; # # myDesktop.syncthing.enable = true; # myDesktop.syncthing.devices = { "jupiter.home.example.de" = { id = "XXXXX-..."; }; }; # myDesktop.syncthing.folders = { "Sync" = { path = "/home/user/Sync"; devices = [...]; }; }; # # myDesktop.openrgb.enable = true; # myDesktop.openrgb.motherboard = "amd"; # or "intel" # # myDesktop.laptop.enable = true; # myDesktop.laptop.lidSwitch = "suspend-then-hibernate"; # myDesktop.laptop.hibernateDelaySec = "1h"; # # myDesktop.nitrokey.enable = true; # # myDesktop.extraSystemPackages = with pkgs; [ some-tool ]; # { config, lib, pkgs, inputs, user, ... }: let cfg = config.myDesktop; in { # Hardware modules that are always useful on desktops (bluetooth, …) imports = (import ../hardware); # ── Options ────────────────────────────────────────────────────────────── options.myDesktop = with lib; { windowManager = mkOption { type = types.enum [ "niri" "sway" "kde" ]; default = "niri"; description = "Window manager / desktop environment for this host."; }; cpu = mkOption { type = types.enum [ "amd" "intel" "none" ]; default = "none"; description = "CPU type — selects the matching KVM kernel parameters."; }; virtualisation.enable = mkEnableOption "virtualisation stack (podman/docker-compat, qemu/libvirt, virt-manager)"; syncthing = { enable = mkEnableOption "syncthing continuous file synchronisation"; devices = mkOption { type = types.attrs; default = {}; example = literalExpression ''{ "jupiter.home.example.de" = { id = "XXXXX-XXXXX-XXXXX-..."; }; }''; description = "Syncthing peer devices."; }; folders = mkOption { type = types.attrs; default = {}; example = literalExpression ''{ "Sync" = { path = "/home/user/Sync"; devices = [ "jupiter" ]; ignorePerms = false; }; }''; description = "Syncthing shared folders."; }; }; openrgb = { enable = mkEnableOption "OpenRGB RGB motherboard control"; motherboard = mkOption { type = types.str; default = "amd"; description = "Motherboard vendor string passed to OpenRGB (amd or intel)."; }; }; laptop = { enable = mkEnableOption "laptop-specific settings (lid-switch, hibernate delay)"; lidSwitch = mkOption { type = types.str; default = "suspend-then-hibernate"; description = "systemd-logind action on lid close."; }; hibernateDelaySec = mkOption { type = types.str; default = "1h"; description = "Delay before transitioning from suspend to hibernate."; }; }; nitrokey.enable = mkEnableOption "Nitrokey hardware security key support"; niri.hotkeyVariant = mkOption { type = types.enum [ "default" "lifebook" ]; default = "default"; description = "Niri hotkey variant to deploy — selects binds/.kdl."; }; git.signingKey = mkOption { type = types.str; default = "/home/${user}/.ssh/id_ed25519_sk_rk_red"; description = "SSH key used for git commit signing on this host."; }; extraSystemPackages = mkOption { type = types.listOf types.package; default = []; description = "Additional system packages specific to this host."; }; }; # ── Configuration ──────────────────────────────────────────────────────── config = lib.mkMerge [ # ── Base desktop config (replaces configuration_desktop.nix) ─────────── { users.users.${user} = { isNormalUser = true; uid = 2000; extraGroups = [ "wheel" "video" "audio" "camera" "networkmanager" "lp" "kvm" "libvirtd" "adb" "dialout" "tss" ]; }; security = { pam.services.login.enableGnomeKeyring = true; # swaylock PAM is harmless on non-sway WMs pam.services.swaylock = {}; rtkit.enable = true; }; environment.systemPackages = with pkgs; [ file powertop cpufrequtils lm_sensors libva-utils at-spi2-core qmk-udev-rules gptfdisk age-plugin-yubikey pwgen sbctl ausweisapp e2fsprogs orca-slicer ] ++ cfg.extraSystemPackages; nixpkgs.config.permittedInsecurePackages = [ "mbedtls-2.28.10" ]; services = { pipewire = { enable = true; alsa.enable = true; pulse.enable = true; wireplumber.enable = true; }; pcscd.enable = true; yubikey-agent.enable = true; udev.packages = with pkgs; [ yubikey-personalization nitrokey-udev-rules ]; flatpak.enable = true; gvfs.enable = true; fwupd.enable = true; blueman.enable = true; avahi = { enable = true; nssmdns4 = true; publish = { enable = true; addresses = true; userServices = true; }; }; }; programs.dconf.enable = true; system.autoUpgrade.enable = false; home-manager.users.${user}.programs.git.signing.key = cfg.git.signingKey; } # ── Niri ─────────────────────────────────────────────────────────────── (lib.mkIf (cfg.windowManager == "niri") { environment = { systemPackages = with pkgs; [ alacritty xdg-desktop-portal-gnome xdg-desktop-portal-gtk swaylock swayidle slurp grim lxqt.lxqt-openssh-askpass clinfo glib brightnessctl playerctl xwayland-satellite breeze-hacked-cursor-theme pwvucontrol ]; loginShellInit = '' export GTK_IM_MODULE="simple" export ELECTRON_OZONE_PLATFORM_HINT="auto" export NIXOS_OZONE_WL="1" export WLR_RENDERER="vulkan" export _JAVA_AWT_WM_NONREPARENTING="1" ''; }; services = { iio-niri.enable = false; greetd = { enable = true; useTextGreeter = true; settings.default_session.command = "${pkgs.tuigreet}/bin/tuigreet --time --cmd niri-session"; }; tuned.enable = true; upower.enable = true; }; programs = { niri.enable = true; ssh.enableAskPassword = true; ssh.askPassword = "${pkgs.lxqt.lxqt-openssh-askpass}/bin/lxqt-openssh-askpass"; }; # Noctalia shell + niri home config via home-manager home-manager.users.${user} = { imports = [ inputs.noctalia.homeModules.default ../wm/niri/home.nix ]; xdg.configFile."niri/binds.kdl".source = ../wm/niri/binds/${cfg.niri.hotkeyVariant}.kdl; services = { mako.enable = true; polkit-gnome.enable = true; }; programs = { fuzzel.enable = true; noctalia-shell = { enable = true; settings = { appLauncher.terminalCommand = "alacritty -e"; bar = { density = "compact"; position = "top"; showCapsule = false; widgets = { left = [ { id = "ControlCenter"; useDistroLogo = true; } { hideUnoccupied = false; id = "Workspace"; labelMode = "index"; showApplications = true; } { id = "ActiveWindow"; } ]; center = [ { formatHorizontal = "HH:mm\\ndd-MM-yy"; formatVertical = "HH mm"; id = "Clock"; useMonospacedFont = true; usePrimaryColor = true; } ]; right = [ { id = "MediaMini"; } { id = "SystemMonitor"; showNetworkStats = true; compactMode = false; } { id = "WiFi"; } { id = "Bluetooth"; } { id = "Battery"; displayMode = "icon-always"; hideIfNotDetected = true; } { id = "Volume"; displayMode = "alwaysShow"; } { id = "NotificationHistory"; hideWhenZero = true; } { id = "Tray"; } ]; }; }; colorSchemes.predefinedScheme = "Catppuccin"; general = { avatarImage = "/home/${user}/.face"; radiusRatio = 0.2; lockOnSusepnd = true; }; location = { monthBeforeDay = true; name = "Munich, Germany"; showWeekNumberInCalendar = true; firstDayOfWeek = 0; }; wallpaper = { enabled = true; overviewEnabled = false; directory = "/home/${user}/.setup/modules/themes/"; }; brightness = { enforceMinimum = true; brightnessStep = 5; }; controlCenter.shortcuts.left = [ { id = "WiFi"; } { id = "Bluetooth"; } { id = "ScreenRecorder"; } { id = "PowerProfile"; } { id = "KeepAwake"; } ]; dock.enabled = false; sessionMenu.enableCountdown = false; templates = { fuzzel = true; alacritty = true; qt = true; gtk = true; discord = true; code = true; telegram = true; niri = true; firefox = true; }; }; }; }; home.file.".cache/noctalia/wallpapers.json".text = builtins.toJSON { defaultWallpaper = "/home/${user}/.setup/modules/themes/wall.jpg"; }; }; }) # ── Sway ─────────────────────────────────────────────────────────────── (lib.mkIf (cfg.windowManager == "sway") { environment = { loginShellInit = '' if [ -z $DISPLAY ] && [ $UID != 0 ] && [ "$(tty)" = "/dev/tty1" ]; then exec sway fi ''; systemPackages = with pkgs; [ xdg-desktop-portal-wlr sway swaylock swayidle slurp grim bemenu lxqt.lxqt-openssh-askpass clinfo waybar glib ]; }; programs = { sway = { enable = true; extraSessionCommands = '' export MOZ_ENABLE_WAYLAND="1" export MOZ_WEBRENDER="1" export WLR_RENDERER="vulkan" export XDG_SESSION_TYPE="wayland" export GTK_THEME="Arc" export _JAVA_AWT_WM_NONREPARENTING="1" ''; }; ssh.enableAskPassword = true; ssh.askPassword = "${pkgs.lxqt.lxqt-openssh-askpass}/bin/lxqt-openssh-askpass"; }; xdg.portal = { enable = true; wlr.enable = true; extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; }; home-manager.users.${user}.imports = [ ../wm/sway/home.nix ../wm/waybar.nix # sway uses waybar for the bar ]; }) # ── KDE Plasma ───────────────────────────────────────────────────────── (lib.mkIf (cfg.windowManager == "kde") { environment.systemPackages = with pkgs; [ kdePackages.discover maliit-keyboard maliit-framework kdePackages.ksshaskpass ]; programs.ssh = { enableAskPassword = true; askPassword = lib.mkDefault "${pkgs.kdePackages.ksshaskpass}/bin/ksshaskpass"; }; services = { packagekit.enable = true; desktopManager.plasma6.enable = true; udev.packages = with pkgs; [ gnome-settings-daemon ]; }; qt.platformTheme = "kde"; home-manager.users.${user}.imports = [ ../wm/kde/home.nix ]; }) # ── Virtualisation (podman/docker-compat + qemu/libvirt) ─────────────── (lib.mkIf cfg.virtualisation.enable { users.groups = { docker.members = [ user ]; libvirtd.members = [ "root" user ]; }; virtualisation = { podman = { enable = true; autoPrune.enable = true; dockerCompat = true; }; libvirtd = { enable = true; onShutdown = "shutdown"; qemu.runAsRoot = false; }; spiceUSBRedirection.enable = true; }; environment.systemPackages = with pkgs; [ virt-manager virt-viewer qemu OVMF OVMF-cloud-hypervisor gvfs cloud-hypervisor ]; }) # ── KVM – AMD ────────────────────────────────────────────────────────── (lib.mkIf (cfg.virtualisation.enable && cfg.cpu == "amd") { boot.extraModprobeConfig = '' options kvm_amd nested=0 avic=1 npt=1 ''; }) # ── KVM – Intel ──────────────────────────────────────────────────────── (lib.mkIf (cfg.virtualisation.enable && cfg.cpu == "intel") { boot.extraModprobeConfig = '' options kvm_intel nested=1 options kvm_intel emulate_invalid_guest_state=0 options kvm ignore_nsrs=1 ''; }) # ── Syncthing ────────────────────────────────────────────────────────── (lib.mkIf cfg.syncthing.enable { services.syncthing = { enable = true; group = "users"; user = user; dataDir = "/home/${user}/Sync"; configDir = "/home/${user}/.config/syncthing"; overrideDevices = true; overrideFolders = true; openDefaultPorts = true; settings = { devices = cfg.syncthing.devices; folders = cfg.syncthing.folders; }; }; }) # ── OpenRGB ──────────────────────────────────────────────────────────── (lib.mkIf cfg.openrgb.enable { services.hardware.openrgb = { enable = true; motherboard = cfg.openrgb.motherboard; }; }) # ── Laptop ───────────────────────────────────────────────────────────── (lib.mkIf cfg.laptop.enable { systemd.sleep.extraConfig = "HibernateDelaySec=${cfg.laptop.hibernateDelaySec}"; services.logind.settings.Login.HandleLidSwitch = cfg.laptop.lidSwitch; }) # ── Nitrokey ─────────────────────────────────────────────────────────── (lib.mkIf cfg.nitrokey.enable { hardware.nitrokey.enable = true; }) ]; }