From ebc845792488e69d4de8c8fbd22b3a4c0771fcc9 Mon Sep 17 00:00:00 2001 From: Nimmo Date: Sun, 25 Jan 2026 10:49:45 +0000 Subject: [PATCH] feat: Add detailed hardware configuration for Lena and comprehensive installation and host-specific documentation. --- INSTALL.md | 71 +++++++++++++++++ README.md | 156 ++++++-------------------------------- common/default.nix | 1 + hosts/electra/README.md | 98 ++++++++++++++++++++++++ hosts/electra/default.nix | 98 +++++++++++++++++------- hosts/lena/README.md | 46 +++++++++++ hosts/lena/default.nix | 47 +++++++++++- 7 files changed, 354 insertions(+), 163 deletions(-) create mode 100644 INSTALL.md create mode 100644 hosts/electra/README.md create mode 100644 hosts/lena/README.md diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..e475290 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,71 @@ +# Installation Guide + +This guide covers the standard process for installing this NixOS configuration on any host. + +## 1. Boot & Partitioning +Boot the **NixOS Unstable ISO**. + +### Disk Layout +Consult the machine-specific README for the recommended partition and subvolume layout: +* [Electra Setup Specifics](hosts/electra/README.md) +* [Lena Setup Specifics](hosts/lena/README.md) + +### Mounting Example (Assuming Btrfs) +```bash +# Mount your root to /mnt and create subvolumes as needed +# Ensure your EFI partition is mounted at /mnt/boot +``` + +--- + +## 2. Installation Steps + +### Step 1: Clone the Repository +Clone this repo into the installation environment so the installer can access the flake. +```bash +nix-shell -p git --run "git clone https://git.nimmog.uk/nimmo/nixos-config.git /mnt/etc/nixos" +``` + +### Step 2: Generate Hardware Configuration +NixOS needs to know about your physical drive IDs and modules. +```bash +nixos-generate-config --root /mnt +``` + +### Step 3: Organize Configuration +Move the generated file into the host-specific directory. +```bash +# Replace HOSTNAME with electra or lena +mv /mnt/etc/nixos/hardware-configuration.nix /mnt/etc/nixos/hosts/HOSTNAME/hardware-configuration.nix +``` + +### Step 4: Execute Install +```bash +# Replace HOSTNAME with electra or lena +nixos-install --flake /mnt/etc/nixos#HOSTNAME +``` + +### Step 5: Finalize +Set your user password before rebooting. +```bash +nixos-enter --passwd nimmo +reboot +``` + +--- + +## 3. Post-Installation + +Once logged into your new system, move the configuration to its permanent home for easier management. + +```bash +mkdir -p ~/Scripts +sudo mv /etc/nixos ~/Scripts/nixos-config +sudo chown -R nimmo:users ~/Scripts/nixos-config +``` + +### Applying Changes +From now on, any changes made to the files in `~/Scripts/nixos-config` can be applied with: +```bash +sudo nixos-rebuild switch --flake .#HOSTNAME +``` diff --git a/README.md b/README.md index 511a27e..a1b98cc 100644 --- a/README.md +++ b/README.md @@ -1,147 +1,35 @@ -# Nimmo's NixOS Configurations (Electra & Lena) +# Nimmo's NixOS Configurations -This repository manages the NixOS configurations for multiple machines using **Flakes**. +## The Philosophy +The goal of this repository is to maintain a unified, reproducible computing environment across multiple high-performance machines. By leveraging **NixOS Flakes**, I ensure that my workflow—from development tools to desktop aesthetics—remains consistent whether I'm on my primary workstation or a mobile 2-in-1. -* **Electra:** Framework 16 (Strix Point + RTX 5070) - High Performance / Gaming. -* **Lena:** Secondary Laptop - Standard / Light Use. - -## 1. Directory Structure - -* `common/`: Shared configuration (Users, GUI Apps, CLI Tools, Fonts, Plasma Settings). -* `hosts/electra/`: Electra-specific hardware config, kernel parameters, and strict boot modes. -* `hosts/lena/`: Lena-specific hardware config. -* `flake.nix`: Entry point defining both hosts. +### Core Intentions +1. **Reproducibility**: Use Flakes and specific Git pins to ensure that "it works on my machine" means it works on *every* machine. +2. **Shared Experience**: The `common/` directory defines a single source of truth for my user account, Plasma 6 desktop environment, and application suite. +3. **Hardware Optimization**: While the experience is unified, the configuration is not generic. Each host contains specific tuning for its hardware (e.g., Framework 16 specialisations vs. Lenovo 2-in-1 sensor support). +4. **Security & Accessibility**: Integrating hardware-level security (Fingerprint) with daily convenience (SDDM Numlock, Plasma 6 Wayland) for a "premium" Linux experience. --- -## 2. Initial Setup (Electra Only - BIOS) +## The Fleet -**Crucial:** Before booting NixOS on Electra, you must configure the BIOS to handle the memory split for LLMs. - -1. Reboot and enter BIOS (F2 or Del). -2. Find **Graphics Memory**, **UMA Frame Buffer**, or **iGPU Memory**. -3. Set this to **16G** (or "Game Optimized"). +| Host | Status | Intent | +| :--- | :--- | :--- | +| **[Electra](hosts/electra/README.md)** | Active | **Powerhouse.** Used for gaming, LLM development, and high-performance tasks. Features deep NVIDIA integration and Strix Point optimizations. | +| **[Lena](hosts/lena/README.md)** | Deploying | **Versatility.** A convertible 2-in-1 for travel and tablet use. Optimized for battery life and touch interaction. | --- -## 3. Installation Guide +## Documentation Index -Once you have booted the **NixOS Unstable ISO**: - -### Step 1: Disk Partitioning & Mounting - -Follow standard NixOS procedure (or see previous version of this README for BTRFS subvolume layout). Mount your root to `/mnt`. - -### Step 2: Clone Configuration - -We will clone the repo into the user's Scripts folder (persistent location), but for installation we can clone it temporarily or directly to the target. - -**Recommended approach for Install:** - -1. **Clone to /mnt/etc/nixos (Temporary):** - - ```bash - # Replace USERNAME with your git user - nix-shell -p git --run "git clone https://git.nimmog.uk/nimmo/nixos-config.git /mnt/etc/nixos" - ``` - -2. **Generate Hardware Config:** - - ```bash - nixos-generate-config --root /mnt - ``` - -3. **Move Hardware Config to Correct Host Folder:** - - **For Electra:** - ```bash - mv /mnt/etc/nixos/hardware-configuration.nix /mnt/etc/nixos/hosts/electra/hardware-configuration.nix - ``` - - **For Lena:** - ```bash - mv /mnt/etc/nixos/hardware-configuration.nix /mnt/etc/nixos/hosts/lena/hardware-configuration.nix - ``` - -### Step 3: Install & Set Password - -1. **Run the Installer:** - - **For Electra:** - ```bash - nixos-install --flake /mnt/etc/nixos#electra - ``` - - **For Lena:** - ```bash - nixos-install --flake /mnt/etc/nixos#lena - ``` - -2. **Set User Password:** - Do not reboot yet! - - ```bash - nixos-enter - passwd nimmo - exit - ``` - -3. **Reboot:** `reboot` +- **[Installation Guide](INSTALL.md)**: The "How-To" for setting up a new machine or re-installing a host. +- **[Host Documentation](hosts/)**: Specific quirks, BIOS settings, and hardware identifiers for each machine. +- **`common/`**: The heart of the config. If you want to add an app or change a setting globally, look here. --- -## 4. Post-Installation & Management - -After rebooting, move your config to your home folder for easier management. - -1. **Move Config:** - ```bash - mkdir -p ~/Scripts - sudo mv /etc/nixos ~/Scripts/nixos-config - sudo chown -R nimmo:users ~/Scripts/nixos-config - ``` - -2. **Apply Changes:** - From now on, edit files in `~/Scripts/nixos-config`. - - * **Edit:** `nano ~/Scripts/nixos-config/common/user-apps.nix` (or other files) - * **Rebuild (Electra):** - ```bash - sudo nixos-rebuild switch --flake ~/Scripts/nixos-config/#electra - ``` - * **Rebuild (Lena):** - ```bash - sudo nixos-rebuild switch --flake ~/Scripts/nixos-config/#lena - ``` - -3. **Adding Apps:** - * **CLI Tools:** Edit `common/system-utils.nix` - * **GUI Apps:** Edit `common/user-apps.nix` - ---- - -## 5. Electra Specifics - -### Boot Modes -Electra has specialized boot modes selectable at startup: - -1. **NixOS Default:** NVIDIA + Balanced Power (Use when GPU module is inserted). -2. **Gaming-Zen:** NVIDIA + Zen Kernel + Max Performance. -3. **Eco-Battery:** NVIDIA + TLP (Max Saver). -4. **No-dGPU:** **iGPU Only**. Use this when the GPU module is physically replaced with the Expansion Shell. - -### Bus IDs -* **NVIDIA:** 193 (`c1:00.0`) -* **AMD:** 194 (`c2:00.0`) - ---- - -## 6. Docker -Docker is installed in Rootless mode. -```bash -docker run hello-world -``` - -## 7. Fingerprint Reader -* **Login:** Password only (required for KWallet). -* **Sudo/Unlock:** Fingerprint enabled. +## Key Technologies +* **Desktop**: KDE Plasma 6 (Wayland) +* **Filesystem**: Btrfs with ZSTD compression +* **Virtualization**: Rootless Docker +* **Shell/Tools**: Standardized CLI utilities across all nodes. diff --git a/common/default.nix b/common/default.nix index 1ebb903..76487ee 100644 --- a/common/default.nix +++ b/common/default.nix @@ -84,6 +84,7 @@ services.xserver.enable = true; services.displayManager.sddm.enable = true; services.displayManager.sddm.wayland.enable = true; + services.displayManager.sddm.autoNumlock = true; services.desktopManager.plasma6.enable = true; services.xserver.xkb.layout = "gb"; diff --git a/hosts/electra/README.md b/hosts/electra/README.md new file mode 100644 index 0000000..1c9d3ac --- /dev/null +++ b/hosts/electra/README.md @@ -0,0 +1,98 @@ +# Electra Setup Specifics + +**Machine:** Framework 16 (Ryzen 7940HS + RTX 7700S / RTX 5070) + +## 1. BIOS Configuration (Crucial) +Before booting NixOS, you must configure the BIOS to handle the memory split for LLMs and performance: + +1. Reboot and enter BIOS (F2 or Del). +2. Find **Graphics Memory**, **UMA Frame Buffer**, or **iGPU Memory**. +3. Set this to **16G** (or "Game Optimized"). + +## 2. Disk Partitioning (Btrfs) +Electra uses a 2TB NVMe with a dedicated boot partition and a flat Btrfs subvolume layout. + +### Step 1: Subvolume Creation (If Reinstalling) +```bash +# Mount the main partition (nvme0n1p2) +mount /dev/nvme0n1p2 /mnt + +# Standard subvolumes +btrfs subvolume create /mnt/@ +btrfs subvolume create /mnt/@home +btrfs subvolume create /mnt/@nix +btrfs subvolume create /mnt/@log +btrfs subvolume create /mnt/@cache +btrfs subvolume create /mnt/@tmp +btrfs subvolume create /mnt/@srv + +umount /mnt +``` + +### Step 2: Mount with Optimizations +```bash +# Mount Root +mount -o subvol=@,compress=zstd,noatime /dev/nvme0n1p2 /mnt + +# Create mount points +mkdir -p /mnt/{home,nix,var/log,var/cache,var/tmp,srv,boot} + +# Mount subvolumes +mount -o subvol=@home,compress=zstd,noatime /dev/nvme0n1p2 /mnt/home +mount -o subvol=@nix,compress=zstd,noatime /dev/nvme0n1p2 /mnt/nix +mount -o subvol=@log,compress=zstd,noatime /dev/nvme0n1p2 /mnt/var/log +mount -o subvol=@cache,compress=zstd,noatime /dev/nvme0n1p2 /mnt/var/cache +mount -o subvol=@tmp,compress=zstd,noatime /dev/nvme0n1p2 /mnt/var/tmp +mount -o subvol=@srv,compress=zstd,noatime /dev/nvme0n1p2 /mnt/srv + +# Mount Boot (8GB partition) +mount /dev/nvme0n1p1 /mnt/boot +``` + +## 3. Boot Specialisations +Electra has specialized boot modes selectable at startup (systemd-boot menu): + +### With dGPU (Graphics Module Installed) +1. **NixOS Default:** NVIDIA + Balanced Power (Standard mode). +2. **Gaming-Zen:** NVIDIA + Zen Kernel + Max Performance (Lower latency/Stutter reduction). +3. **dGPU-Battery:** NVIDIA + TLP (Max energy saving while using dGPU). + +### Without dGPU (Expansion Shell Installed) +4. **No-dGPU:** **iGPU Only** + Balanced Power. +5. **No-dGPU-Battery:** **iGPU Only** + TLP Power Saving. + +**Note:** The `dgpu-guard` service is active on modes 1-3 to prevent black screens if the hardware is missing. + +## 4. Long-Term dGPU Removal (Expansion Shell Mode) +If you plan to leave the dGPU module out for an extended period, you have two options to make the boot process seamless: + +### Option A: The "Sticky" Default (Recommended) +You don't need to change any code. +1. Reboot Electra. +2. At the **systemd-boot** menu, use the arrow keys to highlight the `No-dGPU` (or `No-dGPU-Battery`) entry. +3. Press **'d'** (for Default). +4. The bootloader will now automatically highlight and boot this entry every time until you change it back. + +### Option B: The Physical Swap Workflow +1. **Shutdown** and unplug the charger. +2. Move the lock switches on the back of the Framework 16 and pull the dGPU module out. +3. Slide the **Expansion Shell** (the empty fan-only module) in and lock it. +4. **Boot**: The system will attempt to boot the Default (Nvidia) mode, hit the `dgpu-guard`, and stop at the console. +5. **Reboot** and perform **Option A** to set your new long-term default. + +## 5. Hardware Identifiers & PCI Shift +**Important:** On the Framework 16, PCI Bus IDs shift depending on whether the dGPU is physically installed. + +| Component | dGPU Installed (ID) | dGPU Removed (ID) | +| :--- | :--- | :--- | +| **NVIDIA dGPU** | `PCI:193:0:0` (c1) | *N/A* | +| **AMD iGPU** | `PCI:194:0:0` (c2) | `PCI:193:0:0` (c1) | + +### Impact on Boot Modes: +* **Default / Gaming-Zen / Eco-Battery**: These modes **require** the dGPU to be physically installed. Booting them without the dGPU may cause the Nvidia driver to conflict with the iGPU. +* **No-dGPU**: Use this mode whenever the Expansion Bay is removed. It ignores Bus IDs and works regardless of the shift. + +## 5. Fingerprint Reader +* **Login:** Password required (KWallet compatibility). +* **Sudo / Lock Screen:** Fingerprint enabled. +* **Enrollment:** `fprintd-enroll nimmo` diff --git a/hosts/electra/default.nix b/hosts/electra/default.nix index c43f823..d6b13dd 100644 --- a/hosts/electra/default.nix +++ b/hosts/electra/default.nix @@ -1,3 +1,32 @@ +let + # Common Power Saving Config (TLP) + powerSaving = { + services.power-profiles-daemon.enable = lib.mkForce false; + services.tlp = { + enable = lib.mkForce true; + settings = { + CPU_SCALING_GOVERNOR_ON_BAT = "powersave"; + CPU_ENERGY_PERF_POLICY_ON_BAT = "power"; + CPU_BOOST_ON_BAT = 0; + PLATFORM_PROFILE_ON_BAT = "low-power"; + }; + }; + }; + + # Common No-dGPU Config (Expansion Shell) + noDgpuBase = { + systemd.services.dgpu-guard.enable = false; + services.xserver.videoDrivers = lib.mkForce [ "modesetting" ]; + boot.blacklistedKernelModules = [ "nvidia" "nvidia_modeset" "nvidia_uvm" "nvidia_drm" ]; + hardware.nvidia = { + modesetting.enable = lib.mkForce false; + powerManagement.enable = lib.mkForce false; + open = lib.mkForce false; + nvidiaSettings = lib.mkForce false; + prime.offload.enable = lib.mkForce false; + }; + }; +in { config, pkgs, lib, ... }: { @@ -56,43 +85,60 @@ }; # ========================================== - # 3. SPECIALISATIONS (Gaming / Eco / No-dGPU) + # 3. HARDWARE GUARD (dGPU Check) + # ========================================== + # This prevents a black-screen hang if you boot into an NVIDIA mode + # but have the dGPU physically removed. + systemd.services.dgpu-guard = { + description = "Check for dGPU presence before starting display manager"; + before = [ "display-manager.service" ]; + wantedBy = [ "display-manager.service" ]; + script = '' + # Check if device 01:00.0 is NVIDIA (Vendor 10de) + if ! ${pkgs.pciutils}/bin/lspci -d 10de: -s 01:00.0 | grep -q "NVIDIA"; then + echo "ERROR: NVIDIA dGPU not found at expected Bus ID!" + echo "You are likely in a dGPU-enabled boot mode but the module is removed." + echo "Falling back to console to prevent black screen hang." + exit 1 + fi + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + # Only run this check if the NVIDIA driver is actually requested + unitConfig.ConditionPathExists = "/proc/modules"; # Basic sanity check + }; + + # ========================================== + # 4. SPECIALISATIONS # ========================================== specialisation = { - # Option 1: Gaming Mode (Zen Kernel + Max Performance) + + # --- WITH dGPU MODES --- + + # 1. Gaming Mode (Zen Kernel + Max Performance) gaming-zen.configuration = { system.nixos.tags = [ "Gaming-Zen" ]; boot.kernelPackages = lib.mkForce pkgs.linuxPackages_zen; hardware.nvidia.powerManagement.finegrained = lib.mkForce false; }; - # Option 2: Eco/Battery Mode (TLP + No Turbo) - battery-saver.configuration = { - system.nixos.tags = [ "Eco-Battery" ]; - services.power-profiles-daemon.enable = lib.mkForce false; - services.tlp = { - enable = lib.mkForce true; - settings = { - CPU_SCALING_GOVERNOR_ON_BAT = "powersave"; - CPU_ENERGY_PERF_POLICY_ON_BAT = "power"; - CPU_BOOST_ON_BAT = 0; - PLATFORM_PROFILE_ON_BAT = "low-power"; - }; - }; + # 2. dGPU Battery Mode (NVIDIA + TLP) + dgpu-battery.configuration = lib.recursiveUpdate powerSaving { + system.nixos.tags = [ "dGPU-Battery" ]; }; - # Option 3: Expansion Shell (Physically Removed GPU) - no-dgpu.configuration = { + # --- WITHOUT dGPU MODES --- + + # 3. No dGPU Mode (Expansion Shell + Balanced) + no-dgpu.configuration = lib.recursiveUpdate noDgpuBase { system.nixos.tags = [ "No-dGPU" ]; - services.xserver.videoDrivers = lib.mkForce [ "modesetting" ]; - boot.blacklistedKernelModules = [ "nvidia" "nvidia_modeset" "nvidia_uvm" "nvidia_drm" ]; - hardware.nvidia = { - modesetting.enable = lib.mkForce false; - powerManagement.enable = lib.mkForce false; - open = lib.mkForce false; - nvidiaSettings = lib.mkForce false; - prime.offload.enable = lib.mkForce false; - }; + }; + + # 4. No dGPU Battery Mode (Expansion Shell + TLP) + no-dgpu-battery.configuration = lib.recursiveUpdate (lib.recursiveUpdate noDgpuBase powerSaving) { + system.nixos.tags = [ "No-dGPU-Battery" ]; }; }; } diff --git a/hosts/lena/README.md b/hosts/lena/README.md new file mode 100644 index 0000000..3d60300 --- /dev/null +++ b/hosts/lena/README.md @@ -0,0 +1,46 @@ +# Lena Setup Specifics + +**Machine:** Lenovo Ideapad 5 2-in-1 (Ryzen 7 8845HS) + +## 1. Disk Partitioning (Btrfs) +Lena uses a Btrfs subvolume layout with ZSTD compression. Use these steps in the installer: + +### Step 1: Subvolume Creation +```bash +# Mount the main partition (nvme0n1p3) +mount /dev/nvme0n1p3 /mnt + +# Create subvolumes +btrfs subvolume create /mnt/@ +btrfs subvolume create /mnt/@home +btrfs subvolume create /mnt/@nix +btrfs subvolume create /mnt/@log + +umount /mnt +``` + +### Step 2: Mount with Optimizations +```bash +# Mount Root +mount -o subvol=@,compress=zstd,noatime /dev/nvme0n1p3 /mnt + +# Create mount points +mkdir -p /mnt/{home,nix,var/log,boot} + +# Mount others +mount -o subvol=@home,compress=zstd,noatime /dev/nvme0n1p3 /mnt/home +mount -o subvol=@nix,compress=zstd,noatime /dev/nvme0n1p3 /mnt/nix +mount -o subvol=@log,compress=zstd,noatime /dev/nvme0n1p3 /mnt/var/log + +# Mount EFI (nvme0n1p1) +mount /dev/nvme0n1p1 /mnt/boot +``` + +## 2. 2-in-1 / Tablet Features +* **Auto-Rotation:** Enabled via `hardware.sensor.iio`. KDE Plasma 6 should handle rotation automatically. +* **Fingerprint:** Enabled for `sudo` and lock screen. + * **Enrollment:** `fprintd-enroll nimmo` +* **Numlock:** Forced 'On' at boot via SDDM. + +## 3. Post-Install Check +If the screen rotation is inverted, verify orientation settings in Plasma Display Configuration. diff --git a/hosts/lena/default.nix b/hosts/lena/default.nix index ead22aa..a8e694a 100644 --- a/hosts/lena/default.nix +++ b/hosts/lena/default.nix @@ -8,8 +8,49 @@ ]; networking.hostName = "lena"; - - # Basic hardware support (Microcode updates appropriate for Intel/AMD depending on what Lena is) - # Assuming Lena is standard, we enable firmware. Update if Lena is ancient. + + # ========================================== + # 1. HARDWARE SPECIFICS (Lenovo Ideapad 5 2-in-1) + # ========================================== hardware.enableAllFirmware = true; + hardware.cpu.amd.updateMicrocode = true; + + # Graphics (AMD Radeon 780M / RDNA3) + hardware.graphics = { + enable = true; + enable32Bit = true; + }; + + # Ensure the amdgpu driver is used + boot.initrd.kernelModules = [ "amdgpu" ]; + services.xserver.videoDrivers = [ "amdgpu" ]; + + # ========================================== + # 2. 2-IN-1 / TABLET FEATURES + # ========================================== + # Accelerometer for screen rotation + hardware.sensor.iio.enable = true; + + # Touchpad/Touchscreen support (Libinput is usually default, but good to ensure) + services.libinput.enable = true; + + # BIOS/Firmware Updates + services.fwupd.enable = true; + + # ========================================== + # 3. FINGERPRINT SCANNER + # ========================================== + services.fprintd.enable = true; + + # Matching Electra's PAM settings for consistency + security.pam.services.sudo.fprintAuth = true; + security.pam.services.kde.fprintAuth = true; + security.pam.services.sddm.fprintAuth = false; # Keep SDDM password-only to avoid unlock loops + + # ========================================== + # 4. POWER MANAGEMENT + # ========================================== + # Using power-profiles-daemon (default in common) is fine, + # but for a laptop, we ensure it's prioritized over TLP for now. + services.power-profiles-daemon.enable = lib.mkDefault true; }