diff --git a/README.md b/README.md index af5566a..7b991e8 100644 --- a/README.md +++ b/README.md @@ -1 +1,228 @@ -# nixos \ No newline at end of file +# NixOS Dual-Configuration Setup + +A NixOS system with **two fully isolated configurations**: + +1. **Dev** - Latest stable kernel, web development tooling (Docker, Node.js, direnv) +2. **Gaming** - Zen kernel, Steam, Lutris, performance tools + +Both share a common base: MangoWC (Wayland compositor) + Noctalia Shell, AMD RDNA 4 GPU support, and a shared `/home` directory with mutable dotfiles. + +## Target Hardware + +| Component | Model | Notes | +|-----------|-------|-------| +| CPU | AMD Ryzen 7 5700G | Zen 3, iGPU available | +| GPU | AMD RX 9060 XT | RDNA 4, requires Kernel 6.14+, Mesa 25.0+ | +| Motherboard | MSI B550 Tomahawk | Excellent IOMMU groups | + +## Directory Structure + +``` +nixos-config/ +├── flake.nix # Main flake definition +├── flake.lock # Auto-generated after first build +├── hosts/ +│ └── / +│ └── hardware-configuration.nix # Copy from /etc/nixos/ +└── modules/ + ├── common.nix # Shared configuration + ├── dev.nix # Development profile + └── gaming.nix # Gaming profile +``` + +## Prerequisites + +1. NixOS installed (minimal install is fine) +2. Flakes enabled in existing config or via: `nix-shell -p nixFlakes` +3. Know your hostname, username, timezone, and locale + +## Quick Setup + +### 1. Clone and Prepare + +```bash +# Clone this repo to your config directory +git clone ~/nixos-config +cd ~/nixos-config + +# Create the host directory (replace with your actual hostname) +mkdir -p hosts/ + +# Replace the placeholder hardware-configuration.nix with your actual one +cp /etc/nixos/hardware-configuration.nix hosts// +``` + +### 2. Replace Placeholders + +Edit the following files and replace these placeholders: + +| Placeholder | Example Value | Files | +|-------------|---------------|-------| +| `` | `desktop` | `flake.nix`, `modules/common.nix` | +| `` | `john` | `modules/common.nix`, `modules/dev.nix`, `modules/gaming.nix` | +| `` | `America/New_York` | `modules/common.nix` | +| `` | `en_US.UTF-8` | `modules/common.nix` | + +Also rename the `hosts/hostname/` directory to match your actual hostname, and ensure the same hostname is used for all `` placeholders (including in `flake.nix`). + +### 3. Stage Files in Git + +**IMPORTANT:** Flakes require all files to be tracked by git before building. + +```bash +cd ~/nixos-config +git add . +``` + +### 4. Verify Flake + +```bash +nix flake check +nix flake show +``` + +### 5. Build and Switch + +**IMPORTANT:** Ensure all files are staged in git (step 3) before building. + +```bash +# Build and switch to dev config as main system profile +sudo nixos-rebuild switch --flake .#dev + +# (Optional) Test gaming config without committing it as a boot option +sudo nixos-rebuild test --flake .#gaming + +# Build gaming config as separate boot profile (available after next reboot) +sudo nixos-rebuild boot --profile-name gaming --flake .#gaming +``` + +### 6. Reboot and Verify + +Boot menu should show: +- `NixOS (dev)` - Default boot +- `NixOS (gaming, zen)` - Gaming profile + +## Updating + +**IMPORTANT:** Always update both profiles together to avoid kernel/Mesa version drift. + +### After Configuration Changes + +```bash +cd ~/nixos-config +git add . # Stage your configuration changes +sudo nixos-rebuild switch --flake .#dev +sudo nixos-rebuild boot --profile-name gaming --flake .#gaming +``` + +### Updating Flake Inputs Only + +```bash +nix flake update +git add flake.lock # Only stage the lock file, not other changes +sudo nixos-rebuild switch --flake .#dev +sudo nixos-rebuild boot --profile-name gaming --flake .#gaming +``` + +## Configuration Summary + +| Config | Kernel | Key Features | +|--------|--------|--------------| +| `dev` | Latest | Docker, Node.js, direnv, dev CLI tools | +| `gaming` | Zen | Steam, Lutris, MangoHUD, Gamemode, CoreCtrl | +| **Shared** | - | MangoWC, Noctalia, AMD GPU, PipeWire, Firefox | + +## Post-Installation + +### Change Password + +Generate a password hash and update `modules/common.nix`: +```bash +mkpasswd -m sha-512 +# Copy the output and replace in common.nix +``` + +### Setup MangoWC + +MangoWC is configured to auto-start via greetd. To customize it: + +```bash +mkdir -p ~/.config/mango +cp /etc/mango/config.conf ~/.config/mango/config.conf + +# Create autostart script for Noctalia shell +cat > ~/.config/mango/autostart.sh << 'EOF' +#!/bin/bash +# Ensure quickshell is in PATH (it should be as a user package) +qs -c noctalia-shell & +EOF +chmod +x ~/.config/mango/autostart.sh +``` + +Add to `~/.config/mango/config.conf`: +``` +exec-once="~/.config/mango/autostart.sh" +``` + +### Dev Profile: Docker Access + +After switching to the dev profile for the first time, you must log out and log back in (or reboot) for Docker group membership to take effect. + +### Auto-start MangoWC from TTY (Alternative) + +If not using greetd, add to `~/.bash_profile` or `~/.zprofile`: +```bash +if [[ -z $WAYLAND_DISPLAY ]] && [[ $(tty) == /dev/tty1 ]]; then + exec mango +fi +``` + +## GPU Verification + +```bash +# Verify firmware loaded +dmesg | grep -i "amdgpu" | grep -i "firmware" + +# Check GPU detected +lspci | grep VGA + +# Verify Vulkan +vulkaninfo | head -30 + +# Check ray tracing support +vulkaninfo | grep VK_KHR_ray_tracing_pipeline + +# Verify OpenCL +clinfo | head -20 +``` + +## Troubleshooting + +### Flake can't find files +```bash +git add . # Flakes require files to be tracked by git +``` + +### MangoWC doesn't start +```bash +systemctl status seatd +groups # Ensure user is in 'seat' group +``` + +### RDNA 4 black screen +```bash +dmesg | grep -i "amdgpu" | grep -i "firmware" +uname -r # Should be 6.14+ +``` + +### Steam doesn't launch +Ensure `hardware.graphics.enable32Bit = true;` in common.nix. + +### Games won't launch +```bash +cat /proc/sys/vm/max_map_count # Should be 2147483642 on gaming profile +``` + +## License + +MIT \ No newline at end of file diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..49664cc --- /dev/null +++ b/flake.nix @@ -0,0 +1,58 @@ +{ + description = "NixOS - Isolated Gaming & Dev configurations"; + + # SECURITY NOTE: After first build, commit flake.lock to pin inputs to specific + # commits. Update via `nix flake update` only from trusted sources. + # This protects against supply-chain attacks from upstream changes. + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + mango = { + url = "github:DreamMaoMao/mango"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + quickshell = { + url = "github:outfoxxed/quickshell"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + noctalia = { + url = "github:noctalia-dev/noctalia-shell"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.quickshell.follows = "quickshell"; + }; + }; + + outputs = { self, nixpkgs, mango, quickshell, noctalia, ... }@inputs: + let + system = "x86_64-linux"; + lib = nixpkgs.lib; + specialArgs = { inherit inputs system; }; + + # Verify mango flake exports the expected module + mangoModule = assert lib.hasAttrByPath [ "nixosModules" "mango" ] mango; + mango.nixosModules.mango; + + # IMPORTANT: Replace with actual hostname + commonModules = [ + ./hosts//hardware-configuration.nix + ./modules/common.nix + mangoModule + ]; + in { + nixosConfigurations = { + # Development configuration + dev = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = commonModules ++ [ ./modules/dev.nix ]; + }; + + # Gaming configuration + gaming = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = commonModules ++ [ ./modules/gaming.nix ]; + }; + }; + }; +} diff --git a/hosts/hostname/hardware-configuration.nix b/hosts/hostname/hardware-configuration.nix new file mode 100644 index 0000000..e75fc5b --- /dev/null +++ b/hosts/hostname/hardware-configuration.nix @@ -0,0 +1,44 @@ +# This is a placeholder hardware-configuration.nix file. +# +# IMPORTANT: Replace this file with your actual hardware-configuration.nix +# generated during NixOS installation, typically found at: +# /etc/nixos/hardware-configuration.nix +# +# To generate a new hardware configuration, run: +# sudo nixos-generate-config --show-hardware-config > hardware-configuration.nix +# +# This placeholder will NOT work for actual system builds - the UUIDs below +# are placeholders that must be replaced with your actual disk UUIDs. + +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + # Example boot configuration (replace with your actual hardware) + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + # IMPORTANT: Replace these UUIDs with your actual disk UUIDs + # Find your UUIDs with: lsblk -f + fileSystems."/" = { + device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-ROOT-UUID"; + fsType = "ext4"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-BOOT-UUID"; + fsType = "vfat"; + }; + + swapDevices = [ + { device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-SWAP-UUID"; } + ]; + + # CPU microcode updates for AMD + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/modules/common.nix b/modules/common.nix new file mode 100644 index 0000000..47c4eb7 --- /dev/null +++ b/modules/common.nix @@ -0,0 +1,182 @@ +{ config, pkgs, inputs, system, ... }: + +{ + # -------------------------------------------------------------------------- + # BOOT + # -------------------------------------------------------------------------- + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + # -------------------------------------------------------------------------- + # SYSTEM + # -------------------------------------------------------------------------- + # IMPORTANT: Replace with actual values + networking.hostName = ""; + time.timeZone = ""; + i18n.defaultLocale = ""; + + networking.networkmanager.enable = true; + + # -------------------------------------------------------------------------- + # AMD GPU - RDNA 4 (RX 9060 XT) + Zen 3 CPU (5700G) + # -------------------------------------------------------------------------- + + # RDNA 4 requires navi44 firmware blobs (included in redistributable firmware) + hardware.enableRedistributableFirmware = true; + + # Use the modern amdgpu NixOS module (cleaner than manual initrd config) + hardware.amdgpu.initrd.enable = true; + + hardware.graphics = { + enable = true; + enable32Bit = true; # Required for Steam/Wine + extraPackages = with pkgs; [ + rocmPackages.clr.icd # OpenCL support for RDNA 4 + ]; + # NOTE: AMDVLK intentionally omitted + # Some games auto-select AMDVLK over RADV, causing performance issues + # RADV (Mesa) is the default and performs better for gaming + }; + + # RADV is already the default Vulkan driver + # This variable is optional but makes it explicit + environment.variables.AMD_VULKAN_ICD = "RADV"; + + # -------------------------------------------------------------------------- + # CPU - Zen 3 Optimizations (Ryzen 7 5700G) + # -------------------------------------------------------------------------- + boot.kernelParams = [ + "amd_pstate=active" # Better power/performance scaling on Zen 3 + ]; + + # -------------------------------------------------------------------------- + # MOTHERBOARD - MSI B550 Tomahawk Sensors + # -------------------------------------------------------------------------- + boot.kernelModules = [ "nct6775" ]; # B550 hardware monitoring + + # -------------------------------------------------------------------------- + # MANGOWC + NOCTALIA + # -------------------------------------------------------------------------- + programs.mango.enable = true; + + # Required for screen sharing, file dialogs + xdg.portal = { + enable = true; + wlr.enable = true; + extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + }; + + # Enable seatd for session management + services.seatd.enable = true; + + # Use greetd to automatically start a MangoWC session on login + # Note: 'mango' binary is provided by programs.mango.enable above + services.greetd = { + enable = true; + settings.default_session = { + command = "mango"; + # IMPORTANT: Replace with actual username + user = ""; + }; + }; + + # -------------------------------------------------------------------------- + # USER ACCOUNT + # -------------------------------------------------------------------------- + # IMPORTANT: Replace with actual username + users.users. = { + isNormalUser = true; + extraGroups = [ "wheel" "networkmanager" "video" "seat" ]; + # IMPORTANT: Generate a password hash with: mkpasswd -m sha-512 + # Then replace the placeholder below with the generated hash + hashedPassword = ""; + packages = with pkgs; [ + # -- Noctalia Shell -- + inputs.quickshell.packages.${system}.default + inputs.noctalia.packages.${system}.default + brightnessctl + cliphist + wlsunset + + # -- MangoWC Ecosystem -- + foot # Terminal + wmenu # Launcher + wl-clipboard # Clipboard + grim # Screenshot + slurp # Region selection + swaybg # Wallpaper + + # -- Applications -- + firefox + ]; + }; + + # -------------------------------------------------------------------------- + # SYSTEM PACKAGES + # -------------------------------------------------------------------------- + environment.systemPackages = with pkgs; [ + vim + wget + curl + htop + git + unzip + file + + # GPU verification tools + clinfo # Verify OpenCL: clinfo + vulkan-tools # Verify Vulkan: vulkaninfo + pciutils # lspci for hardware info + ]; + + # -------------------------------------------------------------------------- + # FONTS + # -------------------------------------------------------------------------- + fonts.packages = with pkgs; [ + # Nerd fonts: current syntax for nixos-unstable and NixOS >= 24.05 + # For older nixpkgs (before this change), use: + # (nerdfonts.override { fonts = [ "JetBrainsMono" ]; }) + nerd-fonts.jetbrains-mono + + # Other fonts + inter + roboto + ]; + + # -------------------------------------------------------------------------- + # AUDIO (PipeWire) + # -------------------------------------------------------------------------- + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + }; + + # Disable PulseAudio (conflicts with PipeWire) + hardware.pulseaudio.enable = false; + + # RealtimeKit for PipeWire + security.rtkit.enable = true; + + # -------------------------------------------------------------------------- + # MISC + # -------------------------------------------------------------------------- + # Allow unfree packages (needed for Steam, some drivers) + nixpkgs.config.allowUnfree = true; + + # Enable flakes + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + # Garbage collection + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 14d"; + }; + + # IMPORTANT: Set to the NixOS version of your install media + # Check with: nixos-version + # Do NOT change this after initial install + system.stateVersion = "24.11"; +} diff --git a/modules/dev.nix b/modules/dev.nix new file mode 100644 index 0000000..bcf47d9 --- /dev/null +++ b/modules/dev.nix @@ -0,0 +1,88 @@ +{ pkgs, ... }: + +{ + # Identification tag (shows in boot menu and `nixos-version`) + system.nixos.tags = [ "dev" ]; + + # -------------------------------------------------------------------------- + # KERNEL - Latest stable for RDNA 4 GPU support + # -------------------------------------------------------------------------- + # NOTE: LTS kernels often lag behind new GPU support. + # For RDNA 4 (RX 9060 XT), use linuxPackages_latest instead of linuxPackages. + boot.kernelPackages = pkgs.linuxPackages_latest; + + # -------------------------------------------------------------------------- + # DOCKER + # -------------------------------------------------------------------------- + virtualisation.docker = { + enable = true; + autoPrune = { + enable = true; + dates = "weekly"; + }; + }; + + # IMPORTANT: Replace with actual username + # NOTE: After first enabling/applying this dev profile, you must log out and + # log back in (or reboot) for the docker group membership to take effect. + users.users..extraGroups = [ "docker" ]; + + # -------------------------------------------------------------------------- + # DEVELOPMENT TOOLS + # -------------------------------------------------------------------------- + programs.direnv = { + enable = true; + nix-direnv.enable = true; # Caches nix shells + }; + + # IMPORTANT: Replace with actual username + users.users..packages = with pkgs; [ + # -- Git -- + lazygit + gh # GitHub CLI + + # -- Node.js -- + nodejs_22 + nodePackages.pnpm + nodePackages.yarn + + # -- CLI Tools -- + httpie # HTTP client + jq # JSON processor + yq # YAML processor + fd # Find alternative + ripgrep # Grep alternative + eza # ls alternative + bat # cat alternative + fzf # Fuzzy finder + zoxide # cd alternative + delta # Git diff viewer + + # -- Database Clients -- + postgresql # psql client + # redis # Uncomment if needed + + # -- Misc -- + gnumake + gcc + ]; + + # -------------------------------------------------------------------------- + # SERVICES (Optional - uncomment if needed) + # -------------------------------------------------------------------------- + # Local PostgreSQL + # services.postgresql = { + # enable = true; + # ensureDatabases = [ "devdb" ]; + # ensureUsers = [{ + # name = ""; + # ensureDBOwnership = true; + # }]; + # }; + + # Local Redis + # services.redis.servers."dev" = { + # enable = true; + # port = 6379; + # }; +} diff --git a/modules/gaming.nix b/modules/gaming.nix new file mode 100644 index 0000000..ad40843 --- /dev/null +++ b/modules/gaming.nix @@ -0,0 +1,99 @@ +{ pkgs, ... }: + +{ + # Identification tags (shows in boot menu) + system.nixos.tags = [ "gaming" "zen" ]; + + # -------------------------------------------------------------------------- + # KERNEL - Zen for gaming performance + # -------------------------------------------------------------------------- + boot.kernelPackages = pkgs.linuxPackages_zen; + + # -------------------------------------------------------------------------- + # STEAM + # -------------------------------------------------------------------------- + programs.steam = { + enable = true; + gamescopeSession.enable = true; + remotePlay.openFirewall = true; + dedicatedServer.openFirewall = true; + }; + + # -------------------------------------------------------------------------- + # GAMEMODE - Auto performance optimizations + # -------------------------------------------------------------------------- + programs.gamemode = { + enable = true; + enableRenice = true; + settings = { + general = { + renice = -10; # Negative value = higher priority for games + }; + gpu = { + apply_gpu_optimisations = "accept-responsibility"; + gpu_device = 0; + amd_performance_level = "high"; + }; + }; + }; + + # -------------------------------------------------------------------------- + # CORECTRL - AMD GPU Control + # -------------------------------------------------------------------------- + programs.corectrl = { + enable = true; + gpuOverclock = { + enable = true; + ppfeaturemask = "0xffffffff"; + }; + }; + + # NOTE: Profile-specific group membership + # The user must be in the "corectrl" and "gamemode" groups for these + # programs to function correctly. These groups are only added when using + # the gaming profile. If you need consistent group membership across + # both profiles, add these groups to common.nix instead. + # IMPORTANT: Replace with actual username + users.users..extraGroups = [ "corectrl" "gamemode" ]; + + # -------------------------------------------------------------------------- + # GAMING PACKAGES + # -------------------------------------------------------------------------- + # IMPORTANT: Replace with actual username + users.users..packages = with pkgs; [ + # -- Performance Overlays -- + mangohud # FPS counter, GPU stats + goverlay # MangoHud GUI config + + # -- Game Launchers -- + lutris # Multi-platform launcher + heroic # Epic/GOG launcher + bottles # Wine prefix manager + + # -- Proton/Wine -- + protonup-qt # Proton-GE installer + winetricks + protontricks + + # -- Utilities -- + gamescope # Micro-compositor for gaming + corectrl # AMD GPU control GUI + + # -- Optional Game Clients -- + # prismlauncher # Minecraft + # retroarch # Emulation + ]; + + # -------------------------------------------------------------------------- + # KERNEL PARAMETERS - Gaming optimizations + # -------------------------------------------------------------------------- + boot.kernel.sysctl = { + # Reduce swappiness for gaming + "vm.swappiness" = 10; + # Increase max map count for games requiring many memory mappings. + # This value (2^31 - 6) is the maximum safe value for signed 32-bit integers. + # Games like Star Citizen, Hogwarts Legacy, and some Unity/Unreal titles + # may crash without this setting due to high mmap requirements. + "vm.max_map_count" = 2147483642; + }; +}