mirror of
https://github.com/zephrynis/nix-flake.git
synced 2026-08-17 21:45:53 +00:00
Initial NixOS flake: Hyprland (end-4 illogical-impulse), NVIDIA, gaming, dev tools
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5ydBQk68JYw8HXzUDLAyV
This commit is contained in:
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
88
README.md
Normal file
88
README.md
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
# nixos-pc
|
||||||
|
|
||||||
|
NixOS flake for the desktop PC: Hyprland with [end-4's illogical-impulse](https://github.com/end-4/dots-hyprland) via [soymou/illogical-flake](https://github.com/soymou/illogical-flake), NVIDIA RTX 3080, Steam/gaming, dev tools.
|
||||||
|
|
||||||
|
- Host: `nixos-pc` · User: `zephrynis` · Channel: nixos-unstable
|
||||||
|
- Boot: systemd-boot on this install's **own ESP** on the 1TB WD SSD; **rEFInd** (on the 2TB NVMe's ESP) remains the top-level OS picker and auto-detects it.
|
||||||
|
|
||||||
|
```
|
||||||
|
hosts/nixos-pc/ host wiring, bootloader, user, hardware config
|
||||||
|
modules/ core, desktop (hyprland/sddm/fonts), nvidia, gaming
|
||||||
|
home/zephrynis.nix illogical-impulse + git/direnv/vscode/CLI tools
|
||||||
|
```
|
||||||
|
|
||||||
|
Rebuild after changes: `sudo nixos-rebuild switch --flake .#nixos-pc`
|
||||||
|
Update inputs (one at a time is safer): `nix flake update <input>`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Install procedure
|
||||||
|
|
||||||
|
Target: ~250GB shrunk from the work-Windows partition on the **1TB WD SA500 SATA SSD**. The work Windows on that disk and everything on the 2TB NVMe (other Windows, Arch, rEFInd's ESP) must not be touched.
|
||||||
|
|
||||||
|
### 1. Prep (from the work Windows)
|
||||||
|
|
||||||
|
1. Back up anything important. If BitLocker is enabled on C:, **export the recovery key** and suspend BitLocker before repartitioning.
|
||||||
|
2. Disable Fast Startup: `powercfg /h off` (admin) — otherwise NTFS is left dirty.
|
||||||
|
3. Shrink C: by ~256000 MB: Disk Management → right-click C: → Shrink Volume. If it won't shrink enough (unmovable files): temporarily disable pagefile + System Restore on C:, reboot, retry, re-enable after.
|
||||||
|
4. Push this repo somewhere reachable from the ISO (GitHub) or copy to a USB stick. **Flakes only evaluate git-tracked files** — commit everything.
|
||||||
|
5. BIOS: disable Secure Boot (stock NixOS bootloader is unsigned). F11 = one-time boot menu.
|
||||||
|
|
||||||
|
### 2. Partition & install (NixOS ISO, UEFI mode)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ls /sys/firmware/efi # must exist (UEFI mode)
|
||||||
|
lsblk -o NAME,SIZE,FSTYPE,LABEL,MODEL # identify disks
|
||||||
|
```
|
||||||
|
|
||||||
|
The 1TB WD (WDS100T1R0A) is likely `/dev/sda`. **Do not touch any NTFS partition, and nothing on the NVMe.** In the ~250G free space (parted `unit GiB`, `print free` to see exact bounds):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
parted /dev/sda -- mkpart ESP fat32 <freeStart> <freeStart+1GiB>
|
||||||
|
parted /dev/sda -- set <N> esp on
|
||||||
|
parted /dev/sda -- mkpart root ext4 <freeStart+1GiB> 100%
|
||||||
|
|
||||||
|
mkfs.fat -F 32 -n NIXBOOT /dev/sdaX # the new 1GiB partition
|
||||||
|
mkfs.ext4 -L nixos /dev/sdaY # the new large partition
|
||||||
|
|
||||||
|
mount /dev/disk/by-label/nixos /mnt
|
||||||
|
mkdir -p /mnt/boot
|
||||||
|
mount -o umask=0077 /dev/disk/by-label/NIXBOOT /mnt/boot
|
||||||
|
```
|
||||||
|
|
||||||
|
Get the flake and the real hardware config:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone <this-repo-url> /mnt/etc/nixos # or copy from USB
|
||||||
|
nixos-generate-config --root /mnt
|
||||||
|
mv /mnt/etc/nixos/hardware-configuration.nix /mnt/etc/nixos/hosts/nixos-pc/hardware-configuration.nix
|
||||||
|
rm /mnt/etc/nixos/configuration.nix
|
||||||
|
git -C /mnt/etc/nixos add -A
|
||||||
|
```
|
||||||
|
|
||||||
|
Install (needs network — ethernet just works, else `nmtui`):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nixos-install --flake /mnt/etc/nixos#nixos-pc # sets root password at the end
|
||||||
|
nixos-enter --root /mnt -c 'passwd zephrynis'
|
||||||
|
reboot
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. After first boot
|
||||||
|
|
||||||
|
1. rEFInd should show a new NixOS/systemd-boot entry (it scans all ESPs). Windows and Arch entries must still work.
|
||||||
|
2. If the firmware now boots straight into systemd-boot instead of rEFInd, fix the order from NixOS: `efibootmgr` to list, `sudo efibootmgr -o XXXX,YYYY,...` with rEFInd first.
|
||||||
|
3. Optional rEFInd polish (edit `refind.conf` on the NVMe ESP): a `menuentry` stanza for a custom NixOS name/icon, and `dont_scan_files`/`dont_scan_dirs` to hide duplicate auto-detected kernel entries from the NIXBOOT ESP.
|
||||||
|
4. Checks: `nvidia-smi`; `cat /sys/module/nvidia_drm/parameters/modeset` → `Y`; Hyprland session in SDDM; quickshell bar appears (Super for launcher); Steam runs a Proton title.
|
||||||
|
- If the `qs` (quickshell) binary is missing, add `inputs.illogical-flake.inputs.quickshell.packages.x86_64-linux.default` to `home.packages` and rebuild.
|
||||||
|
- Cursor invisible/glitchy: enable Hyprland `cursor:no_hardware_cursors = true`, or the commented `WLR_NO_HARDWARE_CURSORS` fallback in `modules/nvidia.nix`.
|
||||||
|
|
||||||
|
### Follow-up (someday): separate rEFInd entries for the two Windows installs
|
||||||
|
|
||||||
|
Both Windows currently share one Windows Boot Manager/BCD on the NVMe ESP, so rEFInd shows a single Windows entry with a second picker behind it. The new ESP on the 1TB SSD makes splitting easy:
|
||||||
|
|
||||||
|
1. From the **work Windows**, assign the NIXBOOT ESP a letter (e.g. `S:` via `diskpart` → `assign`), then:
|
||||||
|
`bcdboot C:\Windows /s S: /f UEFI`
|
||||||
|
This creates an independent Windows Boot Manager + BCD on the 1TB SSD's ESP that boots only the work OS. 1GiB is plenty for both this and NixOS's kernels.
|
||||||
|
2. rEFInd then shows two distinct Windows Boot Manager entries (one per ESP).
|
||||||
|
3. Remove the work OS's entry from the old shared BCD (`msconfig` → Boot tab, or `bcdedit /delete <id>`) so each menu boots exactly one Windows.
|
||||||
40
flake.nix
Normal file
40
flake.nix
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
description = "nixos-pc — NixOS + Hyprland (end-4 illogical-impulse)";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
|
home-manager = {
|
||||||
|
url = "github:nix-community/home-manager";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
# end-4 dots-hyprland (illogical-impulse) home-manager port
|
||||||
|
illogical-flake = {
|
||||||
|
url = "github:soymou/illogical-flake";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
# To pin or fork the end-4 dotfiles themselves, override the port's
|
||||||
|
# `dotfiles` input (this is the only source-override mechanism):
|
||||||
|
# inputs.dotfiles.url = "git+https://github.com/end-4/dots-hyprland?submodules=1&rev=<sha>";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { nixpkgs, home-manager, ... }@inputs: {
|
||||||
|
nixosConfigurations.nixos-pc = nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
specialArgs = { inherit inputs; };
|
||||||
|
modules = [
|
||||||
|
./hosts/nixos-pc
|
||||||
|
|
||||||
|
home-manager.nixosModules.home-manager
|
||||||
|
{
|
||||||
|
home-manager.useGlobalPkgs = true;
|
||||||
|
home-manager.useUserPackages = true;
|
||||||
|
home-manager.extraSpecialArgs = { inherit inputs; };
|
||||||
|
home-manager.backupFileExtension = "hm-bak";
|
||||||
|
home-manager.users.zephrynis = import ./home/zephrynis.nix;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
47
home/zephrynis.nix
Normal file
47
home/zephrynis.nix
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{ inputs, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [ inputs.illogical-flake.homeManagerModules.default ];
|
||||||
|
|
||||||
|
home.username = "zephrynis";
|
||||||
|
home.homeDirectory = "/home/zephrynis";
|
||||||
|
# Matches the release era of system.stateVersion; never change afterwards.
|
||||||
|
home.stateVersion = "25.11";
|
||||||
|
|
||||||
|
programs.illogical-impulse = {
|
||||||
|
enable = true;
|
||||||
|
# All default to true — listed for discoverability
|
||||||
|
dotfiles = {
|
||||||
|
fish.enable = true;
|
||||||
|
kitty.enable = true;
|
||||||
|
starship.enable = true;
|
||||||
|
};
|
||||||
|
# hyprland.plugins = [ ]; # listOf package, loaded via hyprland's plugin mechanism
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.git = {
|
||||||
|
enable = true;
|
||||||
|
userName = "zephrynis";
|
||||||
|
userEmail = "zephrynis.yt@gmail.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.direnv = {
|
||||||
|
enable = true;
|
||||||
|
nix-direnv.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.vscode.enable = true;
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
ripgrep
|
||||||
|
fd
|
||||||
|
fzf
|
||||||
|
jq
|
||||||
|
btop
|
||||||
|
eza
|
||||||
|
bat
|
||||||
|
tree
|
||||||
|
nixfmt-rfc-style
|
||||||
|
nil # Nix LSP
|
||||||
|
];
|
||||||
|
}
|
||||||
39
hosts/nixos-pc/default.nix
Normal file
39
hosts/nixos-pc/default.nix
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./hardware-configuration.nix
|
||||||
|
../../modules/core.nix
|
||||||
|
../../modules/desktop.nix
|
||||||
|
../../modules/nvidia.nix
|
||||||
|
../../modules/gaming.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.hostName = "nixos-pc";
|
||||||
|
|
||||||
|
# systemd-boot lives on this install's OWN ESP (on the 1TB WD SSD) and only
|
||||||
|
# serves NixOS generations. rEFInd on the NVMe ESP stays the top-level OS
|
||||||
|
# picker and auto-detects this as a new entry — do not add Windows/Arch
|
||||||
|
# entries here.
|
||||||
|
boot.loader = {
|
||||||
|
systemd-boot = {
|
||||||
|
enable = true;
|
||||||
|
configurationLimit = 10;
|
||||||
|
};
|
||||||
|
efi.canTouchEfiVariables = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.zephrynis = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "zephrynis";
|
||||||
|
extraGroups = [ "wheel" "networkmanager" "video" "input" ];
|
||||||
|
shell = pkgs.fish; # end-4 dots are fish-centric
|
||||||
|
};
|
||||||
|
programs.fish.enable = true;
|
||||||
|
|
||||||
|
time.timeZone = "Europe/London";
|
||||||
|
i18n.defaultLocale = "en_GB.UTF-8";
|
||||||
|
|
||||||
|
# Set to the NixOS release of the ISO used at install time; never change afterwards.
|
||||||
|
system.stateVersion = "25.11";
|
||||||
|
}
|
||||||
26
hosts/nixos-pc/hardware-configuration.nix
Normal file
26
hosts/nixos-pc/hardware-configuration.nix
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# PLACEHOLDER — on install day, overwrite this file with the one produced by
|
||||||
|
# nixos-generate-config --root /mnt
|
||||||
|
# (it lands in /mnt/etc/nixos/hardware-configuration.nix), then `git add` it —
|
||||||
|
# flakes only evaluate tracked files. The generated file adds the correct
|
||||||
|
# boot.initrd.availableKernelModules for this machine.
|
||||||
|
#
|
||||||
|
# The labels below match the mkfs commands in README.md (mkfs.ext4 -L nixos,
|
||||||
|
# mkfs.fat -n NIXBOOT), so this stub is bootable even before replacement.
|
||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."/boot" = {
|
||||||
|
device = "/dev/disk/by-label/NIXBOOT";
|
||||||
|
fsType = "vfat";
|
||||||
|
options = [ "fmask=0077" "dmask=0077" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
swapDevices = [ ]; # 128GB RAM — no swap
|
||||||
|
|
||||||
|
hardware.cpu.intel.updateMicrocode = true;
|
||||||
|
}
|
||||||
47
modules/core.nix
Normal file
47
modules/core.nix
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
nix.settings = {
|
||||||
|
experimental-features = [ "nix-command" "flakes" ];
|
||||||
|
auto-optimise-store = true;
|
||||||
|
trusted-users = [ "root" "@wheel" ];
|
||||||
|
};
|
||||||
|
nix.gc = {
|
||||||
|
automatic = true;
|
||||||
|
dates = "weekly";
|
||||||
|
options = "--delete-older-than 14d";
|
||||||
|
};
|
||||||
|
|
||||||
|
nixpkgs.config.allowUnfree = true;
|
||||||
|
|
||||||
|
networking.networkmanager.enable = true; # required by illogical-flake
|
||||||
|
|
||||||
|
hardware.bluetooth = {
|
||||||
|
enable = true;
|
||||||
|
powerOnBoot = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.pipewire = {
|
||||||
|
enable = true;
|
||||||
|
alsa.enable = true;
|
||||||
|
alsa.support32Bit = true;
|
||||||
|
pulse.enable = true;
|
||||||
|
};
|
||||||
|
security.rtkit.enable = true;
|
||||||
|
|
||||||
|
services.fstrim.enable = true;
|
||||||
|
|
||||||
|
# Read the Windows/data partitions when needed
|
||||||
|
boot.supportedFilesystems = [ "ntfs" ];
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
wget
|
||||||
|
curl
|
||||||
|
file
|
||||||
|
unzip
|
||||||
|
p7zip
|
||||||
|
pciutils
|
||||||
|
usbutils
|
||||||
|
efibootmgr # check/fix boot order so rEFInd stays first
|
||||||
|
];
|
||||||
|
}
|
||||||
31
modules/desktop.nix
Normal file
31
modules/desktop.nix
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# System-side requirements of illogical-flake (the HM module does the rest)
|
||||||
|
programs.hyprland.enable = true;
|
||||||
|
services.geoclue2.enable = true; # QtPositioning — weather / night light widgets
|
||||||
|
|
||||||
|
services.displayManager.sddm = {
|
||||||
|
enable = true;
|
||||||
|
wayland.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; # file pickers etc.
|
||||||
|
|
||||||
|
security.polkit.enable = true;
|
||||||
|
programs.dconf.enable = true;
|
||||||
|
services.gvfs.enable = true;
|
||||||
|
services.udisks2.enable = true;
|
||||||
|
services.upower.enable = true;
|
||||||
|
|
||||||
|
fonts.packages = with pkgs; [
|
||||||
|
# named by the illogical-flake README
|
||||||
|
rubik
|
||||||
|
nerd-fonts.ubuntu
|
||||||
|
nerd-fonts.jetbrains-mono
|
||||||
|
material-symbols
|
||||||
|
noto-fonts
|
||||||
|
noto-fonts-cjk-sans
|
||||||
|
noto-fonts-color-emoji
|
||||||
|
];
|
||||||
|
}
|
||||||
19
modules/gaming.nix
Normal file
19
modules/gaming.nix
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
programs.steam = {
|
||||||
|
enable = true;
|
||||||
|
remotePlay.openFirewall = true;
|
||||||
|
gamescopeSession.enable = true; # "Steam (gamescope)" session in SDDM
|
||||||
|
extraCompatPackages = [ pkgs.proton-ge-bin ];
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.gamemode.enable = true;
|
||||||
|
programs.gamescope.enable = true;
|
||||||
|
# programs.gamescope.capSysNice = true; # left off — known to break gamescope under Steam
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
mangohud
|
||||||
|
protonup-qt
|
||||||
|
];
|
||||||
|
}
|
||||||
30
modules/nvidia.nix
Normal file
30
modules/nvidia.nix
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.xserver.videoDrivers = [ "nvidia" ];
|
||||||
|
|
||||||
|
hardware.graphics = {
|
||||||
|
enable = true;
|
||||||
|
enable32Bit = true; # Steam/Proton
|
||||||
|
};
|
||||||
|
|
||||||
|
hardware.nvidia = {
|
||||||
|
modesetting.enable = true; # nvidia-drm.modeset=1 — mandatory for Wayland
|
||||||
|
open = true; # RTX 3080 (Ampere): NVIDIA-recommended on driver >= 560
|
||||||
|
nvidiaSettings = true;
|
||||||
|
powerManagement.enable = true; # preserves VRAM across suspend — avoids Wayland resume corruption
|
||||||
|
powerManagement.finegrained = false; # desktop GPU
|
||||||
|
package = config.boot.kernelPackages.nvidiaPackages.stable;
|
||||||
|
};
|
||||||
|
|
||||||
|
boot.kernelParams = [ "nvidia_drm.fbdev=1" ];
|
||||||
|
|
||||||
|
environment.sessionVariables = {
|
||||||
|
LIBVA_DRIVER_NAME = "nvidia";
|
||||||
|
NVD_BACKEND = "direct";
|
||||||
|
ELECTRON_OZONE_PLATFORM_HINT = "auto";
|
||||||
|
# Fallbacks — only if symptoms appear (should be unnecessary with driver 560+ / explicit sync):
|
||||||
|
# WLR_NO_HARDWARE_CURSORS = "1"; # invisible/glitchy cursor
|
||||||
|
# __GLX_VENDOR_LIBRARY_NAME = "nvidia"; # Xwayland picks wrong GL vendor
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user