Add NixOS dual-configuration setup with isolated dev and gaming profiles #1

Merged
Copilot merged 5 commits from copilot/create-nixos-dual-configs into main 2026-02-01 19:51:45 +00:00
6 changed files with 699 additions and 1 deletions

229
README.md
View File

@@ -1 +1,228 @@
# nixos
# NixOS Dual-Configuration Setup
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:09 +00:00 (Migrated from github.com)
Review

The README states that files must be staged in git before building (line 69: "git add .") and mentions this again in troubleshooting (line 182), but the initial setup instructions in step 4 "Build and Switch" don't explicitly remind users to do this before running nixos-rebuild. Users might miss step 3 and try to build without staging files, leading to confusing errors. Consider adding a reminder or verification step in the build instructions.

The README states that files must be staged in git before building (line 69: "git add .") and mentions this again in troubleshooting (line 182), but the initial setup instructions in step 4 "Build and Switch" don't explicitly remind users to do this before running nixos-rebuild. Users might miss step 3 and try to build without staging files, leading to confusing errors. Consider adding a reminder or verification step in the build instructions.
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:10 +00:00 (Migrated from github.com)
Review

The README instructs users to "rename hosts/hostname/ to match your actual hostname" (line 63), but the actual flake.nix expects the path to be "./hosts/<hostname>/hardware-configuration.nix" where <hostname> is a placeholder that needs to be replaced in the flake.nix itself (line 31). This creates ambiguity: should users rename the directory AND update flake.nix, or just update flake.nix? The instructions should be clearer that both the directory name and the reference in flake.nix need to match the actual hostname.

Also rename the `hosts/<hostname>/` directory to match your actual hostname, and ensure the same hostname is used for all `<hostname>` placeholders (including in `flake.nix`).
The README instructs users to "rename hosts/hostname/ to match your actual hostname" (line 63), but the actual flake.nix expects the path to be "./hosts/&lt;hostname&gt;/hardware-configuration.nix" where &lt;hostname&gt; is a placeholder that needs to be replaced in the flake.nix itself (line 31). This creates ambiguity: should users rename the directory AND update flake.nix, or just update flake.nix? The instructions should be clearer that both the directory name and the reference in flake.nix need to match the actual hostname. ```suggestion Also rename the `hosts/<hostname>/` directory to match your actual hostname, and ensure the same hostname is used for all `<hostname>` placeholders (including in `flake.nix`). ```
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:10 +00:00 (Migrated from github.com)
Review

The README instructs users to run "sudo nixos-rebuild boot --profile-name gaming" (line 86) but this will only build the gaming profile without making it immediately available. The user won't be able to boot into the gaming profile until after a reboot. Consider clarifying in the README that the gaming profile will only be available after the next reboot, or consider using "sudo nixos-rebuild test --flake .#gaming" first to verify the gaming config works before committing to it as a boot option.

# (Optional but recommended) Test gaming config without committing it as a boot option
sudo nixos-rebuild test --flake .#gaming

# Build gaming config as a separate boot profile (will be available after the next reboot)
The README instructs users to run "sudo nixos-rebuild boot --profile-name gaming" (line 86) but this will only build the gaming profile without making it immediately available. The user won't be able to boot into the gaming profile until after a reboot. Consider clarifying in the README that the gaming profile will only be available after the next reboot, or consider using "sudo nixos-rebuild test --flake .#gaming" first to verify the gaming config works before committing to it as a boot option. ```suggestion # (Optional but recommended) Test gaming config without committing it as a boot option sudo nixos-rebuild test --flake .#gaming # Build gaming config as a separate boot profile (will be available after the next reboot) ```
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:12 +00:00 (Migrated from github.com)
Review

The autostart script created in lines 138-142 uses "qs -c noctalia-shell" but this requires the quickshell binary to be in PATH. While quickshell is installed as a user package (common.nix line 83), the full command might need to be more specific or use the full path. Additionally, there's no error handling if noctalia-shell fails to start. Consider adding error handling or verification steps to the README.

The autostart script created in lines 138-142 uses "qs -c noctalia-shell" but this requires the quickshell binary to be in PATH. While quickshell is installed as a user package (common.nix line 83), the full command might need to be more specific or use the full path. Additionally, there's no error handling if noctalia-shell fails to start. Consider adding error handling or verification steps to the README.
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/
│ └── <hostname>/
│ └── 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 <this-repo> ~/nixos-config
cd ~/nixos-config
# Create the host directory (replace <hostname> with your actual hostname)
mkdir -p hosts/<hostname>
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:11 +00:00 (Migrated from github.com)
Review

The README instructs users to "cp /etc/nixos/hardware-configuration.nix hosts/<hostname>/" (line 49), but this assumes the hosts/<hostname>/ directory already exists. If users haven't renamed the directory yet (as per line 63), this command will fail. The setup instructions should specify creating or renaming the directory first, then copying the hardware configuration.


# Create the host directory (replace <hostname> with your actual hostname)
mkdir -p hosts/<hostname>
The README instructs users to "cp /etc/nixos/hardware-configuration.nix hosts/&lt;hostname&gt;/" (line 49), but this assumes the hosts/&lt;hostname&gt;/ directory already exists. If users haven't renamed the directory yet (as per line 63), this command will fail. The setup instructions should specify creating or renaming the directory first, then copying the hardware configuration. ```suggestion # Create the host directory (replace <hostname> with your actual hostname) mkdir -p hosts/<hostname> ```
# Replace the placeholder hardware-configuration.nix with your actual one
cp /etc/nixos/hardware-configuration.nix hosts/<hostname>/
```
### 2. Replace Placeholders
Edit the following files and replace these placeholders:
| Placeholder | Example Value | Files |
|-------------|---------------|-------|
| `<hostname>` | `desktop` | `flake.nix`, `modules/common.nix` |
| `<username>` | `john` | `modules/common.nix`, `modules/dev.nix`, `modules/gaming.nix` |
| `<timezone>` | `America/New_York` | `modules/common.nix` |
| `<locale>` | `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 `<hostname>` 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
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:12 +00:00 (Migrated from github.com)
Review

The update instructions start with "git add ." (line 101) which suggests staging all changes, but this is only appropriate if the user has made configuration changes. If they're just updating flake inputs (as shown in lines 108-112), they only need to stage flake.lock. The "git add ." command could accidentally stage unwanted changes. Consider clarifying when to use "git add ." versus just "git add flake.lock".

The update instructions start with "git add ." (line 101) which suggests staging all changes, but this is only appropriate if the user has made configuration changes. If they're just updating flake inputs (as shown in lines 108-112), they only need to stage flake.lock. The "git add ." command could accidentally stage unwanted changes. Consider clarifying when to use "git add ." versus just "git add flake.lock".
```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 <replace-with-password-hash> 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

58
flake.nix Normal file
View File

@@ -0,0 +1,58 @@
{
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:11 +00:00 (Migrated from github.com)
Review

The flake.nix uses "mango.nixosModules.mango" (line 33) but there's no verification that this module exists or is exported by the mango flake. If the mango repository doesn't export a nixosModules.mango output, this will cause a build failure. Consider adding a note in the README about verifying the flake inputs or handling potential issues if the upstream flakes change their output schema.

    mangoModule =
      let
        lib = nixpkgs.lib;
      in
      assert lib.hasAttrByPath [ "nixosModules" "mango" ] mango;
      mango.nixosModules.mango;

    # IMPORTANT: Replace <hostname> with actual hostname
    commonModules = [
      ./hosts/<hostname>/hardware-configuration.nix
      ./modules/common.nix
      mangoModule
The flake.nix uses "mango.nixosModules.mango" (line 33) but there's no verification that this module exists or is exported by the mango flake. If the mango repository doesn't export a nixosModules.mango output, this will cause a build failure. Consider adding a note in the README about verifying the flake inputs or handling potential issues if the upstream flakes change their output schema. ```suggestion mangoModule = let lib = nixpkgs.lib; in assert lib.hasAttrByPath [ "nixosModules" "mango" ] mango; mango.nixosModules.mango; # IMPORTANT: Replace <hostname> with actual hostname commonModules = [ ./hosts/<hostname>/hardware-configuration.nix ./modules/common.nix mangoModule ```
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";
};
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:13 +00:00 (Migrated from github.com)
Review

The flake inputs declare third-party NixOS modules (mango, quickshell, noctalia) via mutable GitHub references without a committed flake.lock, so new clones or rebuilds will automatically track whatever commit is at the head of those repositories. Because these modules are integrated into the system as NixOS modules (running code as root at build and runtime), a compromise of any upstream repo or a malicious update could silently introduce arbitrary code into your system. Commit a flake.lock to pin these inputs to specific immutable commits (and update them only via nix flake update) or otherwise explicitly pin them to trusted revisions to reduce this supply-chain risk.

The flake `inputs` declare third-party NixOS modules (`mango`, `quickshell`, `noctalia`) via mutable GitHub references without a committed `flake.lock`, so new clones or rebuilds will automatically track whatever commit is at the head of those repositories. Because these modules are integrated into the system as NixOS modules (running code as root at build and runtime), a compromise of any upstream repo or a malicious update could silently introduce arbitrary code into your system. Commit a `flake.lock` to pin these inputs to specific immutable commits (and update them only via `nix flake update`) or otherwise explicitly pin them to trusted revisions to reduce this supply-chain risk.
};
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 <hostname> with actual hostname
commonModules = [
./hosts/<hostname>/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 ];
};
};
};
}

View File

@@ -0,0 +1,44 @@
# This is a placeholder hardware-configuration.nix file.
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:11 +00:00 (Migrated from github.com)
Review

The filesystem mount configuration is commented out, which means the system won't have any filesystems defined. This will prevent the system from booting. While this is a placeholder file, the commented-out nature makes it more dangerous because it might not fail fast during build time. Consider uncommenting the example filesystem configurations with clear placeholder UUIDs like "REPLACE-WITH-YOUR-ROOT-UUID" to make it more obvious that this needs to be configured.

  fileSystems."/" = {
    # Replace this UUID with the actual root filesystem UUID for your system.
    device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-ROOT-UUID";
    fsType = "ext4";
  };

  fileSystems."/boot" = {
    # Replace this UUID with the actual /boot filesystem UUID for your system.
    device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-BOOT-UUID";
    fsType = "vfat";
  };

  swapDevices = [
    # Replace this UUID with the actual swap partition UUID for your system.
    { device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-SWAP-UUID"; }
  ];
The filesystem mount configuration is commented out, which means the system won't have any filesystems defined. This will prevent the system from booting. While this is a placeholder file, the commented-out nature makes it more dangerous because it might not fail fast during build time. Consider uncommenting the example filesystem configurations with clear placeholder UUIDs like "REPLACE-WITH-YOUR-ROOT-UUID" to make it more obvious that this needs to be configured. ```suggestion fileSystems."/" = { # Replace this UUID with the actual root filesystem UUID for your system. device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-ROOT-UUID"; fsType = "ext4"; }; fileSystems."/boot" = { # Replace this UUID with the actual /boot filesystem UUID for your system. device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-BOOT-UUID"; fsType = "vfat"; }; swapDevices = [ # Replace this UUID with the actual swap partition UUID for your system. { device = "/dev/disk/by-uuid/REPLACE-WITH-YOUR-SWAP-UUID"; } ]; ```
#
# 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;
}

182
modules/common.nix Normal file
View File

@@ -0,0 +1,182 @@
{ config, pkgs, inputs, system, ... }:
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:09 +00:00 (Migrated from github.com)
Review

Setting initialPassword to a plaintext "changeme" is a security concern. While this is mentioned in the comment as temporary, it means the system will boot with a known weak password. Consider using hashedPassword instead, or at a minimum, add a prominent warning in the README that users must change this password immediately after first boot. The current README does mention changing the password in the Post-Installation section, but it should be more prominent.

    # IMPORTANT: Set a secure password hash (e.g. via `mkpasswd -m sha-512`) before using this config
    hashedPassword = "<replace-with-password-hash>";
Setting initialPassword to a plaintext "changeme" is a security concern. While this is mentioned in the comment as temporary, it means the system will boot with a known weak password. Consider using hashedPassword instead, or at a minimum, add a prominent warning in the README that users must change this password immediately after first boot. The current README does mention changing the password in the Post-Installation section, but it should be more prominent. ```suggestion # IMPORTANT: Set a secure password hash (e.g. via `mkpasswd -m sha-512`) before using this config hashedPassword = "<replace-with-password-hash>"; ```
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:10 +00:00 (Migrated from github.com)
Review

The PR description mentions that RDNA 4 requires "navi44_*.bin" firmware blobs and uses "hardware.enableAllFirmware = true" to enable them. However, this setting enables ALL firmware including potentially problematic non-free firmware. A more targeted approach would be to use "hardware.enableRedistributableFirmware = true" which enables AMD GPU firmware but excludes some problematic firmware. If specific navi44 firmware is needed that's not in redistributable, users can be directed to add specific firmware packages.

  hardware.enableRedistributableFirmware = true;
The PR description mentions that RDNA 4 requires "navi44_*.bin" firmware blobs and uses "hardware.enableAllFirmware = true" to enable them. However, this setting enables ALL firmware including potentially problematic non-free firmware. A more targeted approach would be to use "hardware.enableRedistributableFirmware = true" which enables AMD GPU firmware but excludes some problematic firmware. If specific navi44 firmware is needed that's not in redistributable, users can be directed to add specific firmware packages. ```suggestion hardware.enableRedistributableFirmware = true; ```
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:10 +00:00 (Migrated from github.com)
Review

The comment states "Nerd fonts - syntax changed in nixpkgs after 24.05" and shows the new individual package syntax being used. However, this configuration is explicitly targeting nixos-unstable which should use this syntax. The comment could be misleading for users on unstable who won't encounter the old syntax. Consider updating the comment to clarify this is the current syntax for nixos-unstable (and nixos versions after 24.05).

    # Nerd fonts: current syntax for nixos-unstable and NixOS ≥ 24.05
    # For older nixpkgs (before this change), use:
    #   (nerdfonts.override { fonts = [ "JetBrainsMono" ]; })
The comment states "Nerd fonts - syntax changed in nixpkgs after 24.05" and shows the new individual package syntax being used. However, this configuration is explicitly targeting nixos-unstable which should use this syntax. The comment could be misleading for users on unstable who won't encounter the old syntax. Consider updating the comment to clarify this is the current syntax for nixos-unstable (and nixos versions after 24.05). ```suggestion # Nerd fonts: current syntax for nixos-unstable and NixOS ≥ 24.05 # For older nixpkgs (before this change), use: # (nerdfonts.override { fonts = [ "JetBrainsMono" ]; }) ```
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:11 +00:00 (Migrated from github.com)
Review

The system.stateVersion is set to "25.05" which does not follow the NixOS versioning convention. NixOS versions follow the pattern YY.MM (e.g., "24.05", "24.11"), and "25.05" would be released in May 2025. Given the PR description mentions requiring kernel 6.14+ and Mesa 25.0+ from nixos-unstable, and the current date is February 2026, this should likely be "24.11" or "25.05" if that release exists. Verify the correct NixOS release version.

  system.stateVersion = "24.11";
The system.stateVersion is set to "25.05" which does not follow the NixOS versioning convention. NixOS versions follow the pattern YY.MM (e.g., "24.05", "24.11"), and "25.05" would be released in May 2025. Given the PR description mentions requiring kernel 6.14+ and Mesa 25.0+ from nixos-unstable, and the current date is February 2026, this should likely be "24.11" or "25.05" if that release exists. Verify the correct NixOS release version. ```suggestion system.stateVersion = "24.11"; ```
{
# --------------------------------------------------------------------------
# BOOT
# --------------------------------------------------------------------------
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# --------------------------------------------------------------------------
# SYSTEM
# --------------------------------------------------------------------------
# IMPORTANT: Replace with actual values
networking.hostName = "<hostname>";
time.timeZone = "<timezone>";
i18n.defaultLocale = "<locale>";
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;
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:12 +00:00 (Migrated from github.com)
Review

The configuration enables seatd (line 70) which is necessary for MangoWC to function, but there's no configuration for starting MangoWC automatically on boot or login. Users have to manually start it or configure it themselves (as shown in the README post-installation section). For a complete setup, consider mentioning in the README that MangoWC needs to be started manually after the first boot, or provide a display manager option.


  # Use greetd to automatically start a MangoWC session on login
  services.greetd = {
    enable = true;
    settings.default_session = {
      # MangoWC compositor command; ensure this matches the MangoWC binary name
      command = "mango";
      # IMPORTANT: Replace <username> with the same username defined below
      user = "<username>";
    };
  };
The configuration enables seatd (line 70) which is necessary for MangoWC to function, but there's no configuration for starting MangoWC automatically on boot or login. Users have to manually start it or configure it themselves (as shown in the README post-installation section). For a complete setup, consider mentioning in the README that MangoWC needs to be started manually after the first boot, or provide a display manager option. ```suggestion # Use greetd to automatically start a MangoWC session on login services.greetd = { enable = true; settings.default_session = { # MangoWC compositor command; ensure this matches the MangoWC binary name command = "mango"; # IMPORTANT: Replace <username> with the same username defined below user = "<username>"; }; }; ```
# 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 <username> with actual username
user = "<username>";
};
};
# --------------------------------------------------------------------------
# USER ACCOUNT
# --------------------------------------------------------------------------
# IMPORTANT: Replace <username> with actual username
users.users.<username> = {
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 = "<replace-with-password-hash>";
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";
}

88
modules/dev.nix Normal file
View File

@@ -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 <username> with actual username
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:12 +00:00 (Migrated from github.com)
Review

Docker requires the user to log out and log back in after being added to the docker group for the group membership to take effect. Since this configuration adds the user to the docker group, users won't be able to use Docker immediately after the first build without logging out and back in. Consider adding this information to the README in a "Post-Installation" or "First Steps" section for the dev profile.

  # IMPORTANT: Replace <username> with actual username
  # NOTE: This adds the user to the "docker" group so Docker can be used without sudo.
  #       After first enabling/applying this dev profile, you must log out and log
  #       back in (or reboot) for the new group membership to take effect.
  #       Consider documenting this in the README under a "Post-Installation" or
  #       "First Steps" section for the dev profile.
Docker requires the user to log out and log back in after being added to the docker group for the group membership to take effect. Since this configuration adds the user to the docker group, users won't be able to use Docker immediately after the first build without logging out and back in. Consider adding this information to the README in a "Post-Installation" or "First Steps" section for the dev profile. ```suggestion # IMPORTANT: Replace <username> with actual username # NOTE: This adds the user to the "docker" group so Docker can be used without sudo. # After first enabling/applying this dev profile, you must log out and log # back in (or reboot) for the new group membership to take effect. # Consider documenting this in the README under a "Post-Installation" or # "First Steps" section for the dev profile. ```
# 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.<username>.extraGroups = [ "docker" ];
# --------------------------------------------------------------------------
# DEVELOPMENT TOOLS
# --------------------------------------------------------------------------
programs.direnv = {
enable = true;
nix-direnv.enable = true; # Caches nix shells
};
# IMPORTANT: Replace <username> with actual username
users.users.<username>.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 = "<username>";
# ensureDBOwnership = true;
# }];
# };
# Local Redis
# services.redis.servers."dev" = {
# enable = true;
# port = 6379;
# };
}

99
modules/gaming.nix Normal file
View File

@@ -0,0 +1,99 @@
{ pkgs, ... }:
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:10 +00:00 (Migrated from github.com)
Review

The renice value of 10 will make games run with LOWER priority (higher niceness = lower priority). For gaming performance optimization, this should be a negative value like -10 to give games HIGHER priority. The current setting will degrade gaming performance rather than improve it.

        renice = -10;
The renice value of 10 will make games run with LOWER priority (higher niceness = lower priority). For gaming performance optimization, this should be a negative value like -10 to give games HIGHER priority. The current setting will degrade gaming performance rather than improve it. ```suggestion renice = -10; ```
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:11 +00:00 (Migrated from github.com)
Review

The amd_pstate=active kernel parameter is already set in common.nix (line 49), making this redundant. While the comment mentions it's "for clarity," having duplicate kernel parameters can lead to confusion and maintenance issues. Consider removing this duplicate entry.


The amd_pstate=active kernel parameter is already set in common.nix (line 49), making this redundant. While the comment mentions it's "for clarity," having duplicate kernel parameters can lead to confusion and maintenance issues. Consider removing this duplicate entry. ```suggestion ```
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:12 +00:00 (Migrated from github.com)
Review

The gaming profile sets boot.kernelParams to include "mitigations=off", which disables CPU security mitigations for speculative execution and related vulnerabilities. This exposes the system to a broad class of local-attack and potential VM escape primitives, especially in multi-user or virtualization scenarios, purely for a small performance gain. Remove "mitigations=off" (or use more targeted mitigation flags) so the kernel retains its default hardening against these attacks.


The gaming profile sets `boot.kernelParams` to include `"mitigations=off"`, which disables CPU security mitigations for speculative execution and related vulnerabilities. This exposes the system to a broad class of local-attack and potential VM escape primitives, especially in multi-user or virtualization scenarios, purely for a small performance gain. Remove `"mitigations=off"` (or use more targeted mitigation flags) so the kernel retains its default hardening against these attacks. ```suggestion ```
{
# 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 <username> with actual username
users.users.<username>.extraGroups = [ "corectrl" "gamemode" ];
copilot-pull-request-reviewer[bot] commented 2026-02-01 19:45:09 +00:00 (Migrated from github.com)
Review

Both gaming.nix (line 52) and dev.nix (line 26) attempt to add extraGroups to the same user that is already configured in common.nix (line 76-80). In NixOS, when multiple modules configure the same user attribute (extraGroups in this case), the lists are concatenated. However, the common.nix already defines extraGroups = [ "wheel" "networkmanager" "video" "seat" ], and both profiles add their own groups. This works correctly, but it means switching between profiles will have different group memberships for the same user, which could lead to permission issues if files/processes from one profile expect certain groups. Consider documenting this behavior or ensuring both profiles include all necessary groups.

  # NOTE:
  # The user must be in the "corectrl" and "gamemode" groups for these
  # programs to function correctly. To avoid profile-specific differences
  # in group membership, add these groups to `users.users.<username>.extraGroups`
  # in your common user configuration (e.g. common.nix), rather than here.
Both gaming.nix (line 52) and dev.nix (line 26) attempt to add extraGroups to the same user that is already configured in common.nix (line 76-80). In NixOS, when multiple modules configure the same user attribute (extraGroups in this case), the lists are concatenated. However, the common.nix already defines extraGroups = [ "wheel" "networkmanager" "video" "seat" ], and both profiles add their own groups. This works correctly, but it means switching between profiles will have different group memberships for the same user, which could lead to permission issues if files/processes from one profile expect certain groups. Consider documenting this behavior or ensuring both profiles include all necessary groups. ```suggestion # NOTE: # The user must be in the "corectrl" and "gamemode" groups for these # programs to function correctly. To avoid profile-specific differences # in group membership, add these groups to `users.users.<username>.extraGroups` # in your common user configuration (e.g. common.nix), rather than here. ```
# --------------------------------------------------------------------------
# GAMING PACKAGES
# --------------------------------------------------------------------------
# IMPORTANT: Replace <username> with actual username
users.users.<username>.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;
};
}