create users desktop module

This commit is contained in:
2026-04-25 10:20:16 +02:00
parent 5fb7ab4ee0
commit 62b68a333f
7 changed files with 704 additions and 260 deletions

583
modules/desktop/default.nix Normal file
View File

@@ -0,0 +1,583 @@
#
# Desktop module — import this instead of manual WM/virtualisation imports.
#
# Usage in hosts/<hostname>/default.nix:
#
# imports = [
# ./hardware-configuration.nix
# ../../modules/desktop
# ];
#
# myDesktop.windowManager = "niri"; # niri (default) | hyprland | sway | kde | gnome
# 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, pkgs-stable, 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" "hyprland" "sway" "kde" "gnome" ];
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";
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
]
++ (with pkgs-stable; [ 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
];
services = {
mako.enable = true;
polkit-gnome.enable = true;
};
programs = {
fuzzel.enable = true;
noctalia-shell = {
enable = true;
systemd.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";
};
};
})
# ── Hyprland ───────────────────────────────────────────────────────────
(lib.mkIf (cfg.windowManager == "hyprland") {
hardware.opengl.enable = true;
environment = {
loginShellInit = ''
if [ -z $DISPLAY ] && [ $UID != 0 ] && [ "$(tty)" = "/dev/tty1" ]; then
exec Hyprland
fi
'';
variables = {
MOZ_ENABLE_WAYLAND = "1";
MOZ_WEBRENDER = "1";
MOZ_USE_XINPUT2 = "2";
MOZ_DBUS_REMOTE = "1";
XDG_SESSION_TYPE = "wayland";
XDG_CURRENT_DESKTOP = "Unity";
GST_VAAPI_ALL_DRIVERS = "1";
GTK_THEME = "Arc";
_JAVA_AWT_WM_NONREPARENTING = "1";
};
systemPackages = with pkgs; [
xdg-desktop-portal-wlr
swaylock
swayidle
slurp
grim
];
};
programs.hyprland.enable = true;
xdg.portal.wlr.enable = true;
home-manager.users.${user}.imports = [ ../wm/hyprland/home.nix ];
})
# ── 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 ];
})
# ── GNOME ──────────────────────────────────────────────────────────────
(lib.mkIf (cfg.windowManager == "gnome") {
hardware.pulseaudio.enable = lib.mkForce false;
environment.systemPackages = with pkgs; [
gnome.gnome-terminal
gnomeExtensions.dash-to-dock
gnomeExtensions.appindicator
rocmPackages.clr.icd
rocmPackages.clr
clinfo
];
services = {
xserver = {
enable = true;
desktopManager.gnome.enable = true;
displayManager = {
gdm.wayland = true;
gdm.enable = true;
gdm.autoLogin.delay = 5;
gdm.settings.security.DisallowTCP = true;
defaultSession = "gnome";
autoLogin.enable = true;
autoLogin.user = user;
};
};
udev.packages = with pkgs; [ gnome.gnome-settings-daemon ];
};
home-manager.users.${user}.imports = [ ../wm/gnome/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;
})
];
}