KDE Plasma#

Minimal config to get a fully working Plasma 6 desktop, then the options you will actually tweak — fonts, HiDPI, Wayland, keyboard layout, and the declarative route for shortcuts, themes, and panels via plasma-manager.

In this page#

Minimal working Plasma 6#

{ pkgs, ... }:
{
  services.xserver.enable = true;
  services.desktopManager.plasma6.enable = true;
  services.displayManager.sddm.enable = true;
  services.displayManager.sddm.wayland.enable = true;

  # PipeWire for audio (KDE expects it)
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    jack.enable = true;
  };
  services.pulseaudio.enable = false;
  security.rtkit.enable = true;

  # XDG portal — needed for screen sharing, file pickers, Flatpak integration on Wayland
  xdg.portal = {
    enable = true;
    extraPortals = [ pkgs.kdePackages.xdg-desktop-portal-kde ];
  };
}

That is a bootable KDE. Everything below is refinement.

X11 vs Wayland#

SDDM supports both. Users pick the session on the login screen.

services.displayManager.sddm.wayland.enable = true;   # enable Wayland session
services.xserver.enable = true;                       # still needed for Xwayland + X11 fallback

Nvidia + Wayland: works with recent drivers but enable hardware.nvidia.modesetting.enable = true; and use a non-ancient nvidiaSettings. See the GPU snippet in snippets.md.

HiDPI / fractional scaling#

Plasma 6 supports fractional scaling natively in its Display settings. No config file needed — pick the scale in System Settings → Display.

For tty / early-boot HiDPI:

console.font = "Lat2-Terminus16";
boot.loader.systemd-boot.consoleMode = "max";  # larger boot menu text

Fonts#

fonts = {
  enableDefaultPackages = true;
  packages = with pkgs; [
    noto-fonts
    noto-fonts-emoji
    noto-fonts-cjk-sans
    liberation_ttf
    fira-code
    fira-code-symbols
    jetbrains-mono
    font-awesome
    nerd-fonts.fira-code
    nerd-fonts.jetbrains-mono
  ];
  fontconfig.defaultFonts = {
    serif     = [ "Noto Serif" ];
    sansSerif = [ "Noto Sans" ];
    monospace = [ "JetBrains Mono" ];
    emoji     = [ "Noto Color Emoji" ];
  };
};

Keyboard layout#

X11 session:

services.xserver.xkb = {
  layout = "fr";
  variant = "";
  options = "ctrl:nocaps";   # caps lock → control
};

Virtual console (tty):

console.keyMap = "fr";

Essentials on top of Plasma#

Two kinds of packages here: those that live under pkgs.kdePackages (the curated KDE 6 set) and everything else. The NixOS module system merges both into environment.systemPackages, so declare one combined list:

environment.systemPackages = with pkgs; [
  # KDE 6 applications
  kdePackages.kate
  kdePackages.kcalc
  kdePackages.kcolorchooser
  kdePackages.kolourpaint
  kdePackages.ksystemlog
  kdePackages.partitionmanager
  kdePackages.filelight          # disk-usage visualizer
  kdePackages.isoimagewriter     # USB writer with checksum verification

  # Supporting tools
  wl-clipboard                   # Wayland clipboard CLI
  kdePackages.qtstyleplugin-kvantum  # theming engine for Qt
];

If you prefer the shorter with pkgs.kdePackages; form for a block of KDE-only packages, use it in a separate imports = [ ./kde-apps.nix ] module rather than a second top-level environment.systemPackages assignment in the same file — two assignments in the same file merge fine but read confusingly.

Useful programs modules#

programs.kdeconnect.enable = true;    # phone ↔ desktop sync, opens firewall ports
programs.partition-manager.enable = true;
programs.kclock.enable = true;
programs.dconf.enable = true;         # needed by some GTK apps (VSCode theme, etc.)

KWin tweaks that matter#

Most KWin settings live in ~/.config/kwinrc and are edited via System Settings, not configuration.nix. A couple of exceptions:

# Touchpad gestures / libinput tuning
services.libinput = {
  enable = true;
  touchpad = {
    naturalScrolling = true;
    tapping = true;
    disableWhileTyping = true;
  };
};

# Baloo file indexer: it's a per-user service, so disable via the user's
# ~/.config/baloofilerc (easiest through home-manager home.file or
# programs.plasma.configFile), not at the system level.

For anything per-user (themes, wallpapers, panel layouts, keyboard shortcuts, Baloo), use home-manager with the plasma-manager module — see the next section. KDE Connect already lives under programs.kdeconnect.enable in the previous section, don’t re-enable it here.

Declarative Plasma config (plasma-manager)#

Plasma’s settings live in ~/.config/kglobalshortcutsrc, ~/.config/kwinrc, ~/.config/plasmarc, etc. You can override any of them declaratively via plasma-manager, a home-manager module. Keyboard shortcuts, panels, wallpapers, themes, cursor, icons, and arbitrary config-file keys are all supported.

Wire plasma-manager into your flake#

# flake.nix
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
    plasma-manager.url = "github:nix-community/plasma-manager";
    plasma-manager.inputs.nixpkgs.follows = "nixpkgs";
    plasma-manager.inputs.home-manager.follows = "home-manager";
  };

  outputs = { nixpkgs, home-manager, plasma-manager, ... }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ./configuration.nix
        home-manager.nixosModules.home-manager
        {
          home-manager.sharedModules = [ plasma-manager.homeManagerModules.plasma-manager ];
          home-manager.users.alice = import ./home.nix;
        }
      ];
    };
  };
}

Shortcut overrides — the ones from linux/kde.md#

# home.nix
{
  programs.plasma = {
    enable = true;

    shortcuts = {
      # Virtual desktops: ctrl+win+arrow to switch
      "kwin"."Switch One Desktop to the Left"  = "Meta+Ctrl+Left";
      "kwin"."Switch One Desktop to the Right" = "Meta+Ctrl+Right";
      "kwin"."Switch One Desktop Up"           = "Meta+Ctrl+Up";
      "kwin"."Switch One Desktop Down"         = "Meta+Ctrl+Down";

      # Move current window to other desktop
      "kwin"."Window One Desktop to the Left"  = "Meta+Ctrl+Shift+Left";
      "kwin"."Window One Desktop to the Right" = "Meta+Ctrl+Shift+Right";
      "kwin"."Window One Desktop Up"           = "Meta+Ctrl+Shift+Up";
      "kwin"."Window One Desktop Down"         = "Meta+Ctrl+Shift+Down";

      # Views
      "kwin"."ShowDesktopGrid"                 = "Meta+Tab";
      "kwin"."Overview"                        = "Meta+W";

      # Window stickiness
      "kwin"."Window On All Desktops"          = "Meta+X";

      # Clear a default you don't want (set to empty list)
      "kwin"."Walk Through Windows"            = [ ];
    };
  };
}

Each key is "<component>"."<action>". Component names are lowercase (kwin, plasmashell, kmix). Action names match what you see in System Settings → Shortcuts. If unsure, set the shortcut once via the GUI, then cat ~/.config/kglobalshortcutsrc to see the exact Component + Action strings to copy.

Custom shortcut → shell command#

programs.plasma.hotkeys.commands."launch-yazi" = {
  name = "Launch Yazi in Konsole";
  key = "Meta+E";
  command = "konsole -e yazi";
};

Theme, icons, cursor, wallpaper#

programs.plasma.workspace = {
  theme       = "breeze-dark";
  colorScheme = "BreezeDark";
  cursor = { theme = "Breeze_Snow"; size = 24; };
  iconTheme   = "Papirus-Dark";
  wallpaper   = /home/alice/Pictures/wall.jpg;
  # or: wallpaperSlideShow = { path = /home/alice/Pictures/walls; interval = 600; };
};

programs.plasma.fonts = {
  general  = { family = "Noto Sans";      pointSize = 10; };
  fixedWidth = { family = "JetBrains Mono"; pointSize = 10; };
};

KWin behavior (effects, virtual desktops count)#

programs.plasma.kwin = {
  virtualDesktops = {
    number = 4;
    rows   = 1;
    names  = [ "main" "web" "chat" "scratch" ];
  };
  effects = {
    blur.enable           = true;
    minimization.animation = "magiclamp";
    desktopSwitching.animation = "slide";
  };
  nightLight = {
    enable = true;
    mode   = "times";
    temperature.night = 3200;
    time = { evening = "20:00"; morning = "06:00"; };
  };
};

Panel layout#

programs.plasma.panels = [{
  location = "bottom";
  height = 40;
  widgets = [
    "org.kde.plasma.kickoff"
    "org.kde.plasma.pager"
    "org.kde.plasma.icontasks"
    "org.kde.plasma.marginsseparator"
    "org.kde.plasma.systemtray"
    "org.kde.plasma.digitalclock"
  ];
}];

Overriding any rc-file key (escape hatch)#

When plasma-manager doesn’t expose a setting, you can still write directly to any KDE config file via its configFile attr. Keys use the same FileName -> GroupName -> KeyName = value structure as the rc files:

programs.plasma.configFile = {
  "kwinrc" = {
    "Windows" = {
      "FocusPolicy" = "ClickToFocus";
      "DelayFocusInterval" = 300;
    };
    "Compositing" = {
      "OpenGLIsUnsafe" = false;
      "Backend" = "OpenGL";
    };
  };
  "kdeglobals" = {
    "KDE"."SingleClick" = false;
  };
};

This covers any setting Plasma stores — if you can change it in System Settings, you can pin it here.

Workflow tip#

To discover the exact key names for any setting:

  1. Change the setting via System Settings (GUI).

  2. diff your ~/.config/{kwinrc,kglobalshortcutsrc,plasmarc,kdeglobals} against a clean state (git your ~/.config in a throwaway repo, or compare to a fresh user account).

  3. Copy the changed [Section] Key=value into programs.plasma.configFile or the appropriate typed attr.

Desktop widgets and plasmoids#

Plasma widgets (also called plasmoids) live in two places:

  • Panel widgets — in the taskbar/dock. Clock, system tray, task switcher, notifications, media controls.

  • Desktop widgets — floating on the desktop background. Folder view, weather, comic strip, system monitor, sticky notes.

Adding a widget via the GUI#

  • Panel: right-click the panel → Add Widgets, or Edit Panel mode (right-click → Enter Edit Mode) and drag from the widget picker.

  • Desktop: right-click empty desktop → Add Widgets.

The dialog lists every installed widget. Drag to a panel or drop on the desktop. Right-click a placed widget → Configure for its options. Hover + drag the handle (appears when edit mode is on) to move or resize.

Getting more widgets from the KDE Store#

In the Add Widgets dialog, click Get New Widgets… to browse store.kde.org directly. Installs land in ~/.local/share/plasma/plasmoids/ — per-user, no root needed. This works on NixOS exactly like on any other distro.

Install a .plasmoid archive manually:

# install
kpackagetool6 -t Plasma/Applet -i ./my-widget.plasmoid

# list installed
kpackagetool6 -t Plasma/Applet -l

# remove
kpackagetool6 -t Plasma/Applet -r org.kde.plasma.my-widget

Widgets packaged in nixpkgs#

Some widgets are proper NixOS packages — system-wide install, survives reinstalls. Search:

nix search nixpkgs 'plasma.*applet'
nix search nixpkgs 'kdePackages.plasma'

Install examples:

environment.systemPackages = with pkgs.kdePackages; [
  plasma-systemmonitor     # modern system monitor
  plasma-workspace         # ships many built-in plasmoids
  plasma-browser-integration
];

Not every widget from store.kde.org is packaged. For those, fall back to the GUI install path — its files live in your home directory and are thus either backed up by impermanence (if you persist ~/.local/share/plasma/plasmoids) or declared in home-manager via xdg.dataFile.

Declarative panel widgets (plasma-manager)#

Panel widget layout is fully supported — each entry in the widgets list is the full applet name:

programs.plasma.panels = [{
  location = "bottom";
  height = 40;
  widgets = [
    "org.kde.plasma.kickoff"              # app launcher
    "org.kde.plasma.pager"                # virtual desktops
    "org.kde.plasma.icontasks"            # task switcher
    "org.kde.plasma.marginsseparator"
    "org.kde.plasma.systemtray"
    "org.kde.plasma.digitalclock"
    "org.kde.plasma.showdesktop"
  ];
}];

Declarative desktop widgets (harder, escape-hatch)#

Desktop widget placement is trickier because Plasma stores it in “containments” (one per screen/activity) with positional geometry. Plasma-manager’s first-class support is partial. The practical approach:

  1. Set up the layout once via the GUI — add widgets, position, configure.

  2. cat ~/.config/plasma-org.kde.plasma.desktop-appletsrc to see what Plasma wrote.

  3. Paste the relevant sections into programs.plasma.configFile.<rcfile>:

programs.plasma.configFile."plasma-org.kde.plasma.desktop-appletsrc" = {
  "Containments"."1"."plugin" = "org.kde.plasma.folder";
  "Containments"."1"."Applets"."2"."plugin" = "org.kde.plasma.systemmonitor";
  # ... position, geometry, per-applet config copied from the GUI-generated file
};

Messier than themes or shortcuts, but it locks the layout in git.

Useful built-ins (no install needed)#

  • Folder View — behave-like-a-folder desktop (classic KDE 3 feel).

  • System Monitor — CPU / RAM / network / disk graphs, inline on desktop or in the panel.

  • Comic — daily webcomic strip on the desktop.

  • Weather Report — current conditions + forecast.

  • Sticky Notes — scratchpad, supports markdown.

  • Clipboard — history picker (Meta+V).

  • Media Controller — MPRIS2 controls for whatever’s playing.

  • Pager — tiny view of your virtual desktops.

  • Activities — switch between Plasma “activities” (sets of windows / wallpaper / widgets).

All of these are already in your Add Widgets dialog after enabling Plasma 6.

Suspend, hibernate, lock#

services.logind = {
  lidSwitch = "suspend";
  lidSwitchExternalPower = "ignore";
  extraConfig = ''
    HandlePowerKey=suspend
    IdleAction=suspend
    IdleActionSec=15min
  '';
};

Hibernate needs a swap that is ≥ RAM and boot.resumeDevice set. See the swap snippet in snippets.md.

Flatpak integration on Wayland#

The minimum-working setup is already covered in packages.md (which enables services.flatpak and the KDE xdg portal in the same block). The KDE-specific note is that the portal must be the KDE one for file pickers, screen share, and theming to behave:

xdg.portal = {
  enable = true;
  extraPortals = [ pkgs.kdePackages.xdg-desktop-portal-kde ];
};

If you already enabled the generic xdg.portal.enable = true; for other reasons (GNOME apps, Electron), make sure extraPortals still includes the KDE one — missing that is the single most common cause of “file picker opens in GTK mode inside a KDE session”.

After a rebuild, add Flathub manually (one-time):

flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

Next#

  • home-manager-modes.md — plasma-manager lives on the home-manager side; this is where the module-vs-standalone trade-off matters.

  • multi-host-flake.md — sharing one kde.nix module across every host that runs Plasma.

  • dev-tools.md — developer tooling layered on top of KDE.

  • snippets.md — GPU, Bluetooth, printing, power management.