584 lines
19 KiB
Nix
584 lines
19 KiB
Nix
#
|
||
# 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;
|
||
})
|
||
|
||
];
|
||
}
|