NixOS config for workstations

{
  lib,
  config,
  pkgs,
  ...
}:
let
  cfg = config.mjm.desktop;
in
{
  imports = [
    ../../common/desktop.nix

    ./autologin.nix
    ./boot.nix
    ./chrysalis.nix
    ./cosmic.nix
    ./fonts.nix
    ./network.nix
    ./niri.nix
    ./plasma.nix
    ./sound.nix
    ./ssh-tpm.nix
    ./virtualisation.nix
  ];

  config = lib.mkIf cfg.enable {
    <<config>>
  };

  _class = "nixos";
}

I have three different NixOS workstations, and they all use the same overall configuration for their desktops. It's big enough to be broken down into several submodules.

=> autologin
=> network
=> niri

TODO document the other submodules

Config

The options set here in the main file are kind of a grab bag of small things that don't make sense to split into other files.

documentation.enable = true;

In the base module, I disable documentation to save space and build time. But it's useful, so I reenable it on workstations.

time.timeZone = "America/Denver";

Workstations should show the local time rather than UTC.

It would probably make sense to set this to null on laptops, since they can move between time zones. Setting the time zone imperatively might make more sense there.

mjm.deploy.targetHost = lib.mkOverride 900 null;

Workstations should be excluded from automated deploys, which is done by setting their target host to null. The override makes it take precedence over mkDefault, but still be lower priority than a normal setting of the option.

services.displayManager.plasma-login-manager.enable = true;

Regardless of desktop environment or compositor, I am using plasma-login-manager as the display manager. It's the evolution of sddm, and based on my experience it is the least janky one. In particular, NixOS does some pretty weird things to set up gdm, so I'm avoiding that.

services.displayManager.hiddenUsers = [ "matt" ];

When I first set up several of my machines, I used the username "matt", but now I use "mjm" across the board. Because I'm using userborn to set up users and groups, deleting a user once it is created is not trivial. This old user is inactive, but without this configuration, it will still show up in login prompts.

systemd.oomd = {
  enableRootSlice = true;
  enableUserSlices = true;
};

systemd-oomd is enabled by default on NixOS, but it doesn't take action unless you configure slices to act based on memory pressure. These options enable the same defaults Fedora uses, which will kill processes in the root slice and user slices when they exceed 80% memory pressure for 20 seconds.

programs.steam.enable = pkgs.stdenv.isx86_64;

I don't really have a Windows PC anymore: when I do PC gaming, it's on Linux. So I install Steam on any x86_64 workstation. Technically, Steam can be made to work on Asahi Linux, but I don't think it's well-integrated into NixOS, and I haven't put in the effort to set it up.

services.ratbagd.enable = true;

ratbagd is a service that can be used to configure the mouse buttons on gaming mice. I have a Logitech G600 from when I used to regularly play FFXIV, so I have this installed to be able to work with that.

hardware.bluetooth.enable = true;

All of my workstations are capable of using Bluetooth (uranus needs a dongle) so enable it across the board.

services.printing.enable = true;
services.system-config-printer.enable = true;
services.avahi.enable = true;

Much to my dismay, there is in fact a printer in my home. It's an evil thing, but when it wants to cooperate, it is nice to be able to use it.

programs.kdeconnect.enable = true;

It's nice to be able to use KDE Connect to get notifications from my phone or send text messages from my computer. Note that this only installs the program: there's a user service needed that for some reason NixOS does not have an option to install. Instead, I use home-manager to enable it, so that happens in my desktop module for home-manager.

services.udev.extraRules = ''
  ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c24a", ATTR{power/wakeup}="enabled"
'';

For some reason, the Logitech G600 mouse that I use when gaming isn't able to wake up the system by default. I don't have this problem with my Kinesis Advantage 2 keyboard or my Kensington Trackball, which are my primary peripherals at my desk. Maybe it's connected to the wrong port or something. This udev rule fixes the issue. I keep it in the desktop module in the event that I ever plug another machine into the displays at my desk.

programs.nix-ld.enable = true;

nix-ld makes it possible to run binaries on NixOS that expect libraries to be in more normal FHS locations. I avoided it for a long time, but eventually caved due to issues with compiling Zed extensions that this fixes.

boot.binfmt.emulatedSystems =
  let
    inherit (pkgs.stdenv.hostPlatform) system;
  in
  lib.mkMerge [
    (lib.mkIf (system == "x86_64-linux") [ "aarch64-linux" ])
    (lib.mkIf (system == "aarch64-linux") [ "x86_64-linux" ])
  ];

It's really easy to make a NixOS machine be able to build and run binaries for another architecture. It uses qemu-user, which means it's by no means fast, but it can be useful in a pinch, especially when you manage machines for multiple architectures. Since I have both x86_64 and aarch64 machines, I configure my workstations to emulate whichever architecture they are not.

Proxy Information
Original URL
gemini://midna.dev/homelab/modules/nixos/desktop/
Status Code
Success (20)
Meta
text/gemini;lang=en-US
Capsule Response Time
19.533827 milliseconds
Gemini-to-HTML Time
0.464859 milliseconds

This content has been proxied by September (UNKNO).