diff --git a/README.md b/README.md index 08a9aa1..fcc04cf 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ Personal NixOS configuration using the [den](https://github.com/vic/den) framewo |------------|----------------------|--------| | `desktop` | Gaming + development | Nvidia | | `notebook` | Portable development | Intel | -| `work` | Portable development | AMD + Nvidia (PRIME) | ## Prerequisites @@ -44,64 +43,6 @@ just gc just diff ``` -## Installing on a new machine (notebook) - -Only the `notebook` host supports automated installation via the installer ISO. -No hardware-specific preparation is needed beforehand — the installer detects the -hardware automatically using `nixos-generate-config`. - -### 1. Build and flash the ISO - -The ISO embeds the flake at build time, so **all changes must be committed first**. - -```bash -# Commit any pending changes — the ISO only includes git-tracked files -git add -A && git commit -m "pre-install snapshot" - -just iso -sudo dd if=result/iso/*.iso of=/dev/sdX bs=4M status=progress && sync -``` - -### 2. Boot and install - -Boot the ISO on the target machine. The installer logs in as root automatically. - -**If you need Wi-Fi**, the script will prompt you to connect via `nmtui` before proceeding. - -Run the installer: -```bash -nixos-install-host -``` - -The script will: -1. Prompt to set up network (Wi-Fi via `nmtui` if needed) -2. Ask which host to install (`notebook`) -3. **Auto-detect hardware** with `nixos-generate-config` and inject the result into the flake -4. Show available disks and confirm the target -5. Ask for the age key (`keys.txt`) — copy it to a USB or provide the path manually -6. Partition the disk with LUKS + btrfs via disko (prompts for LUKS passphrase) -7. Run `nixos-install` -8. Copy the flake (with detected hardware config) to `~/repos/nixos` on the new system - -### 3. Age key - -The age key used to encrypt `secrets/secrets.yaml` must be available during installation. -Bring it on a USB drive — the installer will find it automatically at `/run/media/*/keys.txt`. - -### 4. After the first boot - -Commit the auto-detected hardware config so future ISO builds include it: - -```bash -cd ~/repos/nixos -git add modules/_hardware/notebook-hardware.nix -git commit -m "add notebook hardware config" -git push -``` - -> **Note:** GRUB will ask for the LUKS passphrase once during boot, and the initrd will ask -> again to mount the root filesystem. This is expected behavior with `enableCryptodisk`. - ## Secrets (SOPS + age) Secrets are stored encrypted in `secrets/secrets.yaml` and decrypted at boot by [sops-nix](https://github.com/Mic92/sops-nix). diff --git a/flake.nix b/flake.nix index 9d8a7d7..f9f448a 100644 --- a/flake.nix +++ b/flake.nix @@ -33,15 +33,11 @@ outputs = inputs: let - system = "x86_64-linux"; - pkgs = inputs.nixpkgs.legacyPackages.${system}; - pkgs-unstable = import inputs.nixpkgs-unstable { - inherit system; - config.allowUnfree = true; - }; + system = "x86_64-linux"; + pkgs = inputs.nixpkgs.legacyPackages.${system}; flake = (inputs.nixpkgs.lib.evalModules { modules = [ (inputs.import-tree ./modules) ]; - specialArgs = { inherit inputs pkgs-unstable; }; + specialArgs.inputs = inputs; }).config.flake; in flake // { nixosConfigurations = flake.nixosConfigurations // { diff --git a/installer/default.nix b/installer/default.nix index ae11a1f..ea525df 100644 --- a/installer/default.nix +++ b/installer/default.nix @@ -14,71 +14,23 @@ let warn() { echo -e "''${YELLOW}[warn]''${NC} $1"; } die() { echo -e "''${RED}[error]''${NC} $1"; exit 1; } - # ------------------------------------------------------------------ # - # Network # - # ------------------------------------------------------------------ # - - header "Network" - echo "An internet connection is required to download packages during installation." - echo "If you need Wi-Fi, connect now with: nmtui" - echo "" - read -p "Press Enter when the network is ready (or Ctrl-C to abort)..." - - # ------------------------------------------------------------------ # - # Host selection # - # ------------------------------------------------------------------ # + FLAKE="path:/etc/nixos-config" header "NixOS Installer" - echo "Evaluating flake..." - HOSTS_JSON=$(nix eval "path:/etc/nixos-config#nixosConfigurations" \ - --apply builtins.attrNames --json) \ - || die "Failed to evaluate the flake at /etc/nixos-config." - echo "Available hosts:" - echo "$HOSTS_JSON" | ${pkgs.jq}/bin/jq -r '.[]' | grep -v installer | sed 's/^/ /' + nix eval "$FLAKE#nixosConfigurations" --apply builtins.attrNames --json 2>/dev/null \ + | ${pkgs.jq}/bin/jq -r '.[]' | grep -v installer | sed 's/^/ /' echo "" read -p "Host to install: " HOST [ -z "$HOST" ] && die "No host specified." - # Verify the selected host has disko configured before touching anything. - # local.notebook.disk is only defined for hosts that include notebook-disko.nix. - echo "Checking that '$HOST' supports automated installation..." - nix eval "path:/etc/nixos-config#nixosConfigurations.$HOST.config.local.notebook.disk" \ - --raw > /dev/null 2>&1 \ - || die "Host '$HOST' does not have a disko configuration. Only 'notebook' is supported." - ok "Host '$HOST' is supported." - - # ------------------------------------------------------------------ # - # Hardware detection # - # ------------------------------------------------------------------ # - - header "Detecting hardware" - echo "Running nixos-generate-config..." - DETECTED_HW=$(nixos-generate-config --no-filesystems --show-hardware-config 2>/dev/null) \ - || die "Failed to detect hardware. Is nixos-generate-config available?" - ok "Hardware detected." - - # Build a writable copy of the embedded flake and inject the detected - # hardware config so both disko and nixos-install use the right modules. - echo "Preparing installation flake..." - rm -rf /tmp/nixos-flake - cp -rL /etc/nixos-config /tmp/nixos-flake - echo "$DETECTED_HW" > /tmp/nixos-flake/modules/_hardware/notebook-hardware.nix - ok "Hardware config written to flake." - - FLAKE="path:/tmp/nixos-flake" - - # ------------------------------------------------------------------ # - # Disk selection # - # ------------------------------------------------------------------ # - header "Available disks" lsblk -d -o NAME,SIZE,MODEL --noheadings | grep -v loop echo "" - CONFIGURED_DISK=$(nix eval "$FLAKE#nixosConfigurations.$HOST.config.local.notebook.disk" \ - --raw 2>/dev/null || echo "/dev/nvme0n1") + CONFIGURED_DISK=$(nix eval "$FLAKE#nixosConfigurations.$HOST.config.local.notebook.disk" --raw 2>/dev/null \ + || echo "/dev/nvme0n1") echo -e "Disk configured for this host: ''${BOLD}$CONFIGURED_DISK''${NC}" read -p "Target disk [$CONFIGURED_DISK]: " DISK_INPUT DISK="''${DISK_INPUT:-$CONFIGURED_DISK}" @@ -87,23 +39,13 @@ let if [ "$DISK" != "$CONFIGURED_DISK" ]; then warn "Disk $DISK differs from configured $CONFIGURED_DISK." - warn "The disko config will use $DISK regardless, but update local.notebook.disk in" - warn "modules/_hardware/notebook-disko.nix and commit it after installation." + warn "Edit modules/_hardware/-disko.nix and rebuild the ISO if it doesn't match." fi - # ------------------------------------------------------------------ # - # Age key # - # ------------------------------------------------------------------ # - header "Age key (secrets decryption)" KEYS_PATH="" - # Search already-mounted media (standard auto-mount paths) - for candidate in \ - /run/media/nixos/*/keys.txt \ - /run/media/*/keys.txt \ - /run/media/*/*/keys.txt \ - /tmp/keys.txt; do + for candidate in /run/media/nixos/*/keys.txt /run/media/*/keys.txt /tmp/keys.txt; do if [ -f "$candidate" ]; then KEYS_PATH="$candidate" ok "Found at $KEYS_PATH" @@ -111,48 +53,16 @@ let fi done - # When booting via Ventoy the USB data partition (label "Ventoy") is not - # auto-mounted in the live environment — only the ISO loop device is set up. - # Detect it by label, mount read-only, copy keys.txt to /tmp, then unmount. - if [ -z "$KEYS_PATH" ]; then - VENTOY_DEV=$(${pkgs.util-linux}/bin/blkid -t LABEL="Ventoy" -o device 2>/dev/null | head -1 || true) - if [ -n "$VENTOY_DEV" ]; then - warn "keys.txt not found in mounted media. Trying Ventoy partition ($VENTOY_DEV)..." - VENTOY_MNT=$(mktemp -d) - if mount -o ro "$VENTOY_DEV" "$VENTOY_MNT" 2>/dev/null; then - if [ -f "$VENTOY_MNT/keys.txt" ]; then - cp "$VENTOY_MNT/keys.txt" /tmp/keys.txt - chmod 600 /tmp/keys.txt - KEYS_PATH="/tmp/keys.txt" - ok "Found on Ventoy USB — copied to /tmp/keys.txt" - else - warn "Ventoy partition mounted but no keys.txt found at its root." - echo "Contents of Ventoy root:" - ls "$VENTOY_MNT" | sed 's/^/ /' - fi - umount "$VENTOY_MNT" 2>/dev/null || true - rm -rf "$VENTOY_MNT" - else - warn "Could not mount Ventoy partition $VENTOY_DEV." - fi - fi - fi - if [ -z "$KEYS_PATH" ]; then warn "Age key not found automatically." echo "Options:" - echo " 1. Place keys.txt at the root of the Ventoy USB (alongside the .iso)" - echo " 2. Mount another USB and it will be found at /run/media/*" - echo " 3. Enter the path manually below" + echo " 1. Copy keys.txt to a USB, mount it, and it will be found at /run/media/*" + echo " 2. Enter the path manually below" read -p "Path to keys.txt: " KEYS_PATH fi [ ! -f "$KEYS_PATH" ] && die "Age key not found at $KEYS_PATH" - # ------------------------------------------------------------------ # - # Confirmation # - # ------------------------------------------------------------------ # - header "Confirmation" echo -e " Host : ''${BOLD}$HOST''${NC}" echo -e " Disk : ''${BOLD}$DISK''${NC} (ALL DATA WILL BE ERASED)" @@ -161,10 +71,6 @@ let read -p "Type 'yes' to continue: " CONFIRM [ "$CONFIRM" != "yes" ] && { echo "Aborted."; exit 1; } - # ------------------------------------------------------------------ # - # Installation # - # ------------------------------------------------------------------ # - header "Partitioning and formatting" echo "(You will be prompted to set the LUKS passphrase.)" disko --mode destroy,format,mount --flake "$FLAKE#$HOST" @@ -177,41 +83,14 @@ let header "Installing NixOS" nixos-install --root /mnt --flake "$FLAKE#$HOST" --no-root-passwd - # ------------------------------------------------------------------ # - # Post-install: save config to the new system # - # ------------------------------------------------------------------ # - - header "Saving configuration" - # Copy the flake (including the detected hardware config) to the user's - # working directory on the installed system so they can commit it. - mkdir -p /mnt/home/zoty/repos - cp -r /tmp/nixos-flake /mnt/home/zoty/repos/nixos - # UID 1000 is the first normal user, matching the zoty account. - chown -R 1000:1000 /mnt/home/zoty/repos/nixos - ok "Configuration saved to ~/repos/nixos on the installed system." - echo "" ok "Installation complete! Remove the USB drive and reboot." - echo "" - echo "After the first boot, commit the detected hardware config:" - echo " cd ~/repos/nixos" - echo " git add modules/_hardware/notebook-hardware.nix" - echo " git commit -m 'add notebook hardware config'" - echo " git push" ''; in { imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" ]; - # Ventoy presents the ISO as a virtual CDROM without the filesystem label - # that NixOS stage-1 expects (nixos-minimal-*). Stage-1 cannot find the - # loop device for nix-store.squashfs, causing "unable to read id index table". - # copytoram loads the entire ISO into RAM before the squashfs mount, removing - # the dependency on the Ventoy device remaining accessible during boot. - # See: https://github.com/NixOS/nixpkgs/issues/245101 - boot.kernelParams = [ "copytoram" ]; - services.getty.autologinUser = lib.mkForce "root"; nix.settings = { @@ -233,9 +112,7 @@ in { pkgs.neovim ]; - # Embed the flake source so the install script can copy it at install time. - # The script copies it to /tmp/nixos-flake (writable) and injects the - # detected hardware config before running disko and nixos-install. + # Embed the flake source so the install script can reference it at path:/etc/nixos-config environment.etc."nixos-config".source = ../.; documentation.enable = lib.mkForce false; diff --git a/modules/_hardware/notebook-hardware.nix b/modules/_hardware/notebook-hardware.nix index 14e109c..2775cc9 100644 --- a/modules/_hardware/notebook-hardware.nix +++ b/modules/_hardware/notebook-hardware.nix @@ -1,28 +1,17 @@ -# Notebook hardware configuration. -# -# This file is REPLACED automatically during installation. -# The installer runs: -# nixos-generate-config --no-filesystems --show-hardware-config -# and writes the output here before calling nixos-install. -# -# After installation, commit the generated file: -# git add modules/_hardware/notebook-hardware.nix -# git commit -m "add notebook hardware config" -# -# To regenerate on the installed system: -# nixos-generate-config --no-filesystems --show-hardware-config \ -# > ~/repos/nixos/modules/_hardware/notebook-hardware.nix -{ lib, modulesPath, ... }: +# Hardware-specific configuration for the notebook. +# fileSystems and swap are declared by disko (notebook-disko.nix). +# Regenerate this file with: nixos-generate-config --no-filesystems --show-hardware-config +{ config, lib, modulesPath, ... }: { imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; - # Filled in by the installer. These are placeholder values that allow - # the flake to evaluate before the real hardware is detected. - boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; - boot.kernelModules = []; + boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "ums_realtek" "sd_mod" "sr_mod" ]; + boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = []; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + networking.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/modules/_hardware/work-hardware.nix b/modules/_hardware/work-hardware.nix index 830fe29..7a65b27 100644 --- a/modules/_hardware/work-hardware.nix +++ b/modules/_hardware/work-hardware.nix @@ -9,7 +9,7 @@ ]; boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ "amdgpu" ]; + boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-amd" ]; boot.extraModulePackages = [ ]; diff --git a/modules/creative.nix b/modules/creative.nix index b72b999..5c4da02 100644 --- a/modules/creative.nix +++ b/modules/creative.nix @@ -1,5 +1,11 @@ -{ den, pkgs-unstable, ... }: { - den.aspects.creative.nixos = { ... }: { +{ den, inputs, ... }: { + den.aspects.creative.nixos = { pkgs, ... }: + let + pkgs-unstable = import inputs.nixpkgs-unstable { + system = pkgs.stdenv.hostPlatform.system; + config.allowUnfree = true; + }; + in { environment.systemPackages = with pkgs-unstable; [ # 3D blender diff --git a/modules/den.nix b/modules/den.nix index 90a8079..faf9bf8 100644 --- a/modules/den.nix +++ b/modules/den.nix @@ -68,10 +68,10 @@ in { den.aspects.dev den.aspects.creative den.aspects.secrets - den.aspects.gaming + den.aspects.steam + den.aspects.prismlauncher den.aspects.androidcam den.aspects.winvm - den.aspects.leisure ]; nixos = { system.stateVersion = "25.11"; diff --git a/modules/dev.nix b/modules/dev.nix index 82dc2c0..abc0693 100644 --- a/modules/dev.nix +++ b/modules/dev.nix @@ -1,8 +1,14 @@ -{ den, pkgs-unstable, config, ... }: +{ den, inputs, config, ... }: let username = config.local.identity.username; in { - den.aspects.dev.nixos = { pkgs, ... }: { + den.aspects.dev.nixos = { pkgs, ... }: + let + pkgs-unstable = import inputs.nixpkgs-unstable { + system = pkgs.stdenv.hostPlatform.system; + config.allowUnfree = true; + }; + in { environment.systemPackages = with pkgs-unstable; [ # CLI utilities gcc @@ -65,9 +71,8 @@ in { }; virtualisation.docker = { - enable = true; - enableOnBoot = false; - package = pkgs-unstable.docker_29; + enable = true; + package = pkgs-unstable.docker_29; }; users.users.${username}.extraGroups = [ "docker" ]; }; diff --git a/modules/leisure.nix b/modules/leisure.nix deleted file mode 100644 index 51f93c7..0000000 --- a/modules/leisure.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ den, pkgs-unstable, ... }: { - den.aspects.leisure.nixos = { ... }: { - environment.systemPackages = with pkgs-unstable; [ - # Streaming - stremio-linux-shell - - # Torrenting - qbittorrent - - # Media playback - mpv - yt-dlp - - # Social - discord - ]; - }; -} diff --git a/modules/notebook.nix b/modules/notebook.nix index af645cf..6b90a5a 100644 --- a/modules/notebook.nix +++ b/modules/notebook.nix @@ -14,11 +14,10 @@ services.thermald.enable = true; boot = { - # Hardware-specific modules (kvm-intel/kvm-amd, nvme, etc.) come from - # modules/_hardware/notebook-hardware.nix, generated during installation - # by nixos-generate-config --no-filesystems --show-hardware-config. - initrd.kernelModules = [ "dm-crypt" ]; - initrd.compressor = "zstd"; + initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "sd_mod" ]; + initrd.kernelModules = [ "dm-crypt" ]; + kernelModules = [ "kvm-intel" ]; + initrd.compressor = "zstd"; loader = { grub = { diff --git a/modules/prismlauncher.nix b/modules/prismlauncher.nix new file mode 100644 index 0000000..f6feb3f --- /dev/null +++ b/modules/prismlauncher.nix @@ -0,0 +1,14 @@ +{ den, ...}: { + den.aspects.prismlauncher.nixos = { pkgs, ... }: { + environment.systemPackages = with pkgs; [ + (prismlauncher.override { + jdks = [ + temurin-bin-8 + temurin-bin-17 + temurin-bin-21 + temurin-bin-25 + ]; + }) + ]; + }; +} diff --git a/modules/gaming.nix b/modules/steam.nix similarity index 50% rename from modules/gaming.nix rename to modules/steam.nix index 1ce0e7e..6faa1e3 100644 --- a/modules/gaming.nix +++ b/modules/steam.nix @@ -1,13 +1,7 @@ -{ den, pkgs-unstable, ... }: { - den.aspects.gaming.nixos = { pkgs, ... }: { - hardware.graphics = { - enable = true; - enable32Bit = true; - }; - +{ den, ... }: { + den.aspects.steam.nixos = { pkgs, ... }: { programs.steam = { enable = true; - package = pkgs-unstable.steam; remotePlay.openFirewall = false; dedicatedServer.openFirewall = false; @@ -18,19 +12,23 @@ extraCompatPackages = with pkgs; [ proton-ge-bin ]; + + # Extra packages that steam might need + extraPackages = with pkgs; [ + xorg.libXcursor + xorg.libXi + xorg.libXinerama + xorg.libXScrnSaver + libpng + libpulseaudio + libvorbis + stdenv.cc.cc.lib + libkrb5 + keyutils + ]; }; - environment.systemPackages = with pkgs; [ - (prismlauncher.override { - jdks = [ - temurin-bin-8 - temurin-bin-17 - temurin-bin-21 - temurin-bin-25 - ]; - }) - ]; - + # Fonts for better game text rendering fonts.packages = with pkgs; [ liberation_ttf wqy_zenhei