# Nomarchy — reusable system layer (NixOS 26.05). # # This module is the distro: import it from any host (see # nixosModules.nomarchy in flake.nix) and layer your machine specifics # (bootloader, hostname, users, hardware) on top. Host concerns are # deliberately NOT set here. Everything user-facing (Hyprland config, # Waybar, Ghostty, theming) lives in modules/home. { config, lib, pkgs, ... }: let cfg = config.nomarchy.system; in { imports = [ ./options.nix ]; config = { # Unfree allowed distro-wide: pragmatic-desktop territory (claude-code # for the menu's ask-Claude module, vendor drivers, …). The custom # nixpkgs-config type can't carry a nested mkDefault; disagree with # `nixpkgs.config = lib.mkForce { allowUnfree = false; }`. nixpkgs.config.allowUnfree = true; # ── Wayland session: Hyprland ──────────────────────────────────── # Installs the binary, registers the session, wires up # xdg-desktop-portal-hyprland. Configuration is Home Manager's job. programs.hyprland.enable = lib.mkDefault true; xdg.portal = { enable = lib.mkDefault true; extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; # file pickers, etc. }; services.greetd = lib.mkIf cfg.greeter.enable { enable = lib.mkDefault true; settings = { default_session = { # start-hyprland is Hyprland 0.55's watchdog launcher; running # the bare binary makes every session print a warning. command = lib.mkDefault "${pkgs.tuigreet}/bin/tuigreet --time --remember --cmd start-hyprland"; user = "greeter"; }; # Boot straight into the session once; logout → normal greeter. initial_session = lib.mkIf (cfg.greeter.autoLogin != null) { command = "start-hyprland"; user = cfg.greeter.autoLogin; }; }; }; # ── Audio: Pipewire ────────────────────────────────────────────── security.rtkit.enable = lib.mkDefault cfg.audio.enable; services.pulseaudio.enable = lib.mkDefault false; services.pipewire = lib.mkIf cfg.audio.enable { enable = lib.mkDefault true; alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; wireplumber.enable = true; }; # ── Desktop services ───────────────────────────────────────────── security.polkit.enable = lib.mkDefault true; services.gnome.gnome-keyring.enable = lib.mkDefault true; services.dbus.enable = lib.mkDefault true; services.upower.enable = lib.mkDefault true; networking.networkmanager.enable = lib.mkDefault true; hardware.bluetooth.enable = lib.mkDefault cfg.bluetooth.enable; services.blueman.enable = lib.mkDefault cfg.bluetooth.enable; # ── Firmware ───────────────────────────────────────────────────── # Blobs for in-kernel drivers: wifi (iwlwifi/ath/rtw/brcm), SOF # audio, Bluetooth. Drivers ship with the kernel, but without these # a real machine can boot with no wifi — QEMU never catches it. # nixos-generate-config also keys CPU microcode off this flag. hardware.enableRedistributableFirmware = lib.mkDefault true; # ── BTRFS timeline snapshots (ported from the previous iteration) ─ # Guarded on the actual filesystem so enabling it on an ext4 machine # is a clean no-op rather than a failing timer. services.snapper.configs = lib.mkIf (cfg.snapper.enable && (config.fileSystems."/".fsType or "") == "btrfs") { root = { SUBVOLUME = "/"; TIMELINE_CREATE = true; TIMELINE_CLEANUP = true; TIMELINE_LIMIT_HOURLY = "5"; TIMELINE_LIMIT_DAILY = "7"; TIMELINE_LIMIT_WEEKLY = "0"; TIMELINE_LIMIT_MONTHLY = "0"; TIMELINE_LIMIT_YEARLY = "0"; }; }; # ── Fonts ──────────────────────────────────────────────────────── # The ten most popular Nerd Fonts ship by default, so any of them # can be named in the theme state's fonts.mono and actually resolve # (nomarchy-theme-sync warns when a configured font is missing). fonts = { packages = with pkgs; [ nerd-fonts.jetbrains-mono nerd-fonts.fira-code nerd-fonts.caskaydia-cove nerd-fonts.hack nerd-fonts.sauce-code-pro nerd-fonts.meslo-lg nerd-fonts.roboto-mono nerd-fonts.ubuntu-mono # iosevka would be next by popularity, but its package is 1.1 GB # (every weight × variant) — too heavy for the ISO and closures. nerd-fonts.mononoki nerd-fonts.inconsolata inter noto-fonts noto-fonts-color-emoji ]; fontconfig.defaultFonts = { monospace = lib.mkDefault [ "JetBrainsMono Nerd Font" ]; sansSerif = lib.mkDefault [ "Inter" ]; emoji = lib.mkDefault [ "Noto Color Emoji" ]; }; }; # ── Essential packages ─────────────────────────────────────────── environment.systemPackages = with pkgs; [ nomarchy-theme-sync # provided by overlays.default git vim wget curl jq brightnessctl playerctl pamixer wl-clipboard grim slurp ] ++ lib.optional (cfg.snapper.enable && (config.fileSystems."/".fsType or "") == "btrfs") # Snapshot, then rebuild — rollback material for system changes # (theme changes don't need it; HM generations already roll back). (pkgs.writeShellScriptBin "nixos-rebuild-snap" '' if [ "$(id -u)" -ne 0 ]; then echo "This script must be run as root (use sudo)" >&2 exit 1 fi echo "Creating pre-rebuild snapshot..." ${pkgs.snapper}/bin/snapper -c root create \ -d "Pre-rebuild $(date +'%Y-%m-%d %H:%M:%S')" \ --cleanup-algorithm number echo "Rebuilding..." nixos-rebuild switch --flake /etc/nixos#default "$@" ''); # ── Nix itself ─────────────────────────────────────────────────── nix = { settings = { experimental-features = [ "nix-command" "flakes" ]; auto-optimise-store = lib.mkDefault true; }; gc = { automatic = lib.mkDefault true; dates = lib.mkDefault "weekly"; options = lib.mkDefault "--delete-older-than 14d"; }; }; }; }