nixos configuration

so. doll is finally a nixer. oh boy. you wanna know what would make this even worse? if doll literated this bitch up!!!!!!!!!!!! ayyyyyyyyyyyyyyyyyyyyyyyyyyyyy

Goals

Documentation

the whole entire reason doll is doing a literate configuration in the first place is to increase the ratio of documentation vs code.

a big problem with writing code is that eventually you get to a point where you look back at your code and go "wait. what the fuck. why did i do that. why did i do any of this." now imagine having that problem with the code that runs your entire computer. that. would be bad.

thus, in making our nixos config literate, we literally write down paragraphs about all of our decisions so that in the nebulous near future in which we come back to our config not knowing what the hell we were doing, we can look back on those paragraphs and remember what the hell we were doing. which, of course, was witchcraft. it was always witchcraft.

Minimalism

the benefit of having to lay out every single program that you are installing is that it is very easy to know all of the programs you have installed… and think about whether they really need to be there.

doll notices that over time, as it uses its computer, it gets into a habit of installing a bunch of programs in order to solve some sort of issue (whether technical, practical, or fantastical) and then never going back through to remove said programs that are left over in the aftermath. this innevitably creates bloat, and since it usually runs machines that are limited in storage (both this machine nyxtrix and its previous machine crimson were only 256 gb,,,,), that bloat can add up fast.

the declarative process of nixos means that in order to change the programs one has installed, they are required to see all of the applications they have installed. every time one changes their system, the consequences of their actions are laid out in front of them, and one always has the opportunity to look upon the march of progress and make judgement calls on what new daemons are no longer of use within their COMP. and doll thinks that's pretty neat.

Hardware

this is the automatically generated hardware configuration from nixos-generate-config. It doesn't contain much. Most of the real goodies are in a dependency doll will talk about later.

{ config, lib, pkgs, modulesPath, ... }:

{
  imports =
    [ (modulesPath + "/installer/scan/not-detected.nix")
    ];

  boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ "kvm-intel" ];
  boot.extraModulePackages = [ ];

  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
  hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

Main Configuration

this is the main configuration file for nixos. later on, doll will try to split this up into multiple files, but for now, just one is fine.

# ========== configuration.nix - main configuration - © 2026 millicent ==========

Design

currently, our nixos config is firmly in channel land. as a beginner to nixos, it is recommended that we start with channels and then move our way to flakes once we are comfortable with channels. thus, our config is currently in /etc/nixos/configuration.nix and not ~/nixos/flake.nix for example.

Beginning Boilerplate & Imports

{ config, lib, pkgs, ... }:

{
  imports =
    [ # Include tweaks from NixOS-Hardware.
      <nixos-hardware/lenovo/thinkpad/t480s>
      # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];

Boot


# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;

# Use ZFS filesystem
boot.supportedFilesystems = [ "zfs" ];
boot.initrd.systemd.enable = true;
boot.zfs.forceImportRoot = false;

Filesystem


# Configure filesystem paths

## Root
fileSystems."/" = {
  device = "door/root";
  fsType = "zfs";
  };
## Nix Configuration
fileSystems."/nix" = {
  device = "door/nix";
  fsType = "zfs";
  };
## Var
fileSystems."/var" = {
  device = "door/var";
  fsType = "zfs";
  };
## Home
fileSystems."/home" = {
  device = "door/home";
  fsType = "zfs";
  };
## Boot Partition
fileSystems."/boot" = {
  device = "/dev/disk/by-uuid/C605-9D58"; # UUID for /dev/sda1
  fsType = "vfat";
  options = [ "fmask=0077" "dmask=0077" ];
  };

## ZFS shenanigans
## - TODO huh???
services.zfs = {
  autoScrub.enable = true;
  trim.enable = true;
};


Swap


# Swap
# - ZFS does not like swap partitions very much. We have made one /just/ in case, but we
#   will mostly use ZRAM for swap instead.
## Swap Partition
swapDevices = [
  {
    device = "dev/disk/by-partuuid/b974352a-22c7-4601-85da-bf6df7feb7d7"; # UUID for /dev/sda3
    randomEncryption.enable = true; # no swap skimming today, buckeroo
  }
];
## ZRAM
zramSwap = {
  enable = true;
  algorithm = "zstd";
};

Networking


# Networking
networking = {
  hostId = "3b86203e"; # head -c 8 /etc/machine-id
  hostName = "nyxtrix";
  nftables.enable = true;
  firewall.enable = false;
  networkmanager.enable = true;
};

Core System

Settings


# System Settings
system.stateVersion = "26.05"; # latest stable as of 2026-08-20
time.timeZone = "America/Chicago"; # eh close enough
console.keyMap = "us";
i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = {
  LC_ADDRESS = "en_US.UTF-8";
  LC_IDENTIFICATION = "en_US.UTF-8";
  LC_MEASUREMENT = "en_US.UTF-8";
  LC_MONETARY = "en_US.UTF-8";
  LC_NAME = "en_US.UTF-8";
  LC_NUMERIC = "en_US.UTF-8";
  LC_PAPER = "en_US.UTF-8";
  LC_TELEPHONE = "en_US.UTF-8";
  LC_TIME = "en_US.UTF-8";
};

Services


# System Services
services = {
  libinput.enable = true; # libinput is based
  fwupd.enable = true; # LVFS firmware updates
  printing.enable = true; # CUPS!
  flatpak.enable = true; # unfortunately, flatpak is based
  tailscale.enable = true; # unfortunately, tailscale is based

  power-profiles-daemon.enable = true; # performance & power saving profiles
  upower.enable = true; # being able to see battery status


  ## OpenSSH
  ## - basically, allow SSH'ing into this, but REQUIRE use of a key
  openssh = {
    enable = true;
    settings = {
      PasswordAuthentication = false;
      KbdInteractiveAuthentication = false;
      PermitRootLogin = "no";
    };
  };
};

Graphical Environment

# Graphical Environment
## - awwwwww you know what it isssssss
##   wayland niri wayland niri wayland niri wayland niri
services.xserver = {
  enable = true; # BUT IT SAYS XSE- ssshhhhhhhhh
  ## keyboard language
  xkb = {
    layout = "us";
    variant = "";
  };
  ## silly: just. yeet x11. only wayland.
  excludePackages = [ pkgs.xterm ];
};

## niri
programs.niri.enable = true;

## display manager: greetd (for now)
services.greetd = {
  enable = true;
  settings = {
    default_session = {
      command = "${config.programs.niri.package}/bin/niri-session";
      user = "millicent";
    };
  };
};

## By default, NixOS strips out part of the path given to the niri.service unit.
## That's silly. We're gonna let niri have the whole path because it's a good girl
systemd.user.services.niri.enableDefaultPath = false;

## for defaults sake, we are installing polkit, gnome-keyring, and alacritty.
## we will edit this later, don't worry
security.polkit.enable = true;
services.gnome.gnome-keyring.enable = true;

## TODO add systemPackages [ ... alacritty ... ]

Sound

insert joke here.

# Sound
services.pulseaudio.enable = false; # FUC U
security.rtkit.enable = true;
services.pipewire = { # YEAAAAA
  enable = true;
  alsa.enable = true; # for maximum compatability
  alsa.support32Bit = true; # "
  pulse.enable = true; # pipewire-pulse it think
  jack.enable = true; # pipewire-jack it think 2
};

Packages

System Packages

 # Packages
 ## enabling unstable
 nixpkgs.config = {
   allowUnfree = true;
   packageOverrides = pkgs: {
     unstable = import <nixos-unstable> {
       config = config.nixpkgs.config;
     };
   };
 };

 ## system packages
 environment.systemPackages = with pkgs; [
   ## the duhs
   zip
   unzip
   wget
   lm_sensors # for additional hw support
   whois
   dig # forget what this is for, think DNS?
   gnupg # unfortunately, GPG is still used sometimes
   wireguard-tools
   reaction # dependency for wireguard-tools
   git
   doas # sudo but better
   ## programming languages
   python314
   python314Packages.pip
   gcc
   gdb
   valgrind
   go
   cargo
   rustc
   ## shell & DE
   unstable.noctalia # chill shell
   kdePackages.dolphin # file manager
   pwvucontrol # for audio management
   ## extras
   kitty # cute terminal with pictures
   chromium # for handshake specifically
   librewolf # LET THE BROWSER. BE TRANS!!!!!
   neovim # vim. but slightly cooler
   vesktop # discord. but slightly cooler
   vscode # boooooooo
   signal-desktop #mom,,,
   mixxx # untzuntzuntzuntzuntz
];

Fonts

## fonts!
fonts.packages = with pkgs; [
  atkinson-hyperlegible-next # sans
  ioskeley-mono.normal-NF # mono
  drafting-mono # fancy mono
];

Emacs

## emacs
## - the default emacs given by stable is a fairly outdated version.
## - thus, we are using a community overlay to grab the latest
## - tagged version and make sure it is the pure GTK version for wayland.
services.emacs = {
  enable = true;
  defaultEditor = true;
  package = pkgs.emacs-unstable-pgtk;
};

nixpkgs.overlays = [
  (import (builtins.fetchTarball {
    url = "https://github.com/nix-community/emacs-overlay/archive/master.tar.gz";
  }))
];

Docker

## docker (rootless)
virtualisation.docker = {
  # Consider disabling the system wide Docker daemon
  enable = false;

  rootless = {
    enable = true;
    setSocketVariable = true;
    # Optionally customize rootless Docker daemon settings
    daemon.settings = {
      dns = [ "1.1.1.1" "8.8.8.8" ];
      registry-mirrors = [ "https://mirror.gcr.io" ];
    };
  };
};

Flakes?

# NixOS Flakes
# - for now, we are keeping this /off/, just so we can get used to
# - configuring our system the nix way. once we are more settled in,
# - then we will enable flakes.
# nix.settings.experimental-features = [ "nix-command" "flakes" ];

User Account

  # User Account
  users.users.millicent = {
    isNormalUser = true;
    description = "Millicent Kasanova";
    extraGroups = [ "networkmanager" "wheel" "docker" ];
  };
}