From 598a43eace618175b1866d094436d5ad9d7b503e Mon Sep 17 00:00:00 2001 From: Anish Govind Date: Fri, 18 Sep 2026 23:32:32 -0700 Subject: [PATCH] refactor: make hosts declarative and consolidate shared config - add my.username / my.gaming.enable / my.ai.local.enable options and gate optional app modules on them instead of per-host import lists - move vendor-neutral hardware.graphics into modules/graphical, leaving only NVIDIA-specific drivers and env vars in modules/hardware/nvidia - derive the primary user everywhere from my.username (users, getty, home-manager, tmpfiles) - de-duplicate Hyprland autostart down to a single system loginShellInit using the start-hyprland wrapper - consolidate all nixpkgs overlays into modules/core/nix.nix and use final.stdenv.hostPlatform.system - make the zsh rebuild helper target $(hostname) instead of hardcoded hades - add nixpkgs follows for nixos-hardware, pi and comfy-ui (single nixpkgs) - add .gitignore and a nixfmt flake formatter; format all nix files - remove empty browser.nix/display-configuration.nix and rename local_ai.nix -> local-ai.nix - document the my.* toggles in the README --- .gitignore | 9 + README.md | 35 +- flake.lock | 67 +- flake.nix | 42 +- home/brave.nix | 43 +- home/foot.nix | 48 +- home/hypr/default.nix | 113 +-- home/hypr/hyprland.nix | 937 +++++++++++++++---------- home/hypr/quickshell.nix | 14 +- home/nvim/default.nix | 135 ++-- home/rofi.nix | 3 +- home/zsh/init.zsh | 2 +- hosts/hades/default.nix | 14 +- hosts/hades/disko.nix | 5 +- hosts/hades/display-configuration.nix | 5 - hosts/hades/hardware-configuration.nix | 21 +- modules/apps/browser.nix | 5 - modules/apps/communication.nix | 8 +- modules/apps/default.nix | 3 +- modules/apps/gaming.nix | 21 +- modules/apps/local-ai.nix | 45 ++ modules/apps/local_ai.nix | 37 - modules/apps/terminal.nix | 10 +- modules/apps/virt.nix | 4 +- modules/core/default.nix | 11 +- modules/core/nix.nix | 8 +- modules/core/users.nix | 50 +- modules/graphical/default.nix | 85 ++- modules/hardware/nvidia.nix | 61 +- modules/options.nix | 20 + 30 files changed, 1093 insertions(+), 768 deletions(-) create mode 100644 .gitignore delete mode 100644 hosts/hades/display-configuration.nix delete mode 100644 modules/apps/browser.nix create mode 100644 modules/apps/local-ai.nix delete mode 100644 modules/apps/local_ai.nix create mode 100644 modules/options.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ba6402 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Nix build results +result +result-* + +# home-manager backup files (backupFileExtension = "backup") +*.backup + +# direnv +.direnv/ \ No newline at end of file diff --git a/README.md b/README.md index 3b9b706..1281b80 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,22 @@ rebuild switch # zsh helper: sudo nixos-rebuild switch --flake ~/NixOS-Configs ## Adding a new host (e.g. a laptop) 1. Create `hosts//` with `default.nix`, `hardware-configuration.nix`, and - (optionally) `disko.nix`; import the shared modules (`modules/core`, - `modules/graphical`, `modules/apps`). + (optionally) `disko.nix`. Shared modules (`modules/core`, `modules/graphical`, + `modules/apps`) are already pulled in by `commonModules` in `flake.nix` — the + host only adds its own hardware/disko config. 2. Register it in `flake.nix` under `nixosConfigurations`. -3. Declare host-specific displays in `hosts//default.nix`: +3. Turn optional features on per machine via the shared `my.*` options: + +```nix +# hosts//default.nix +my = { + username = "anish"; # default; change for a different primary user + gaming.enable = false; # Steam, Gamemode, MangoHud + ai.local.enable = false; # Ollama, ComfyUI, Open WebUI +}; +``` + +4. Declare host-specific displays in `hosts//default.nix`: ```nix home-manager.users.anish.volt.monitors = [ @@ -44,4 +56,19 @@ home-manager.users.anish.volt.monitors = [ The `volt.monitors` default (any output @ preferred) keeps every machine working out of the box; hosts override only what they need. Hosts without an NVIDIA GPU -simply don't import `modules/hardware/nvidia.nix` — all vendor env vars live there. +simply don't import `modules/hardware/nvidia.nix` — all vendor env vars live there, +while the vendor-neutral `hardware.graphics` stack lives in `modules/graphical`. + +## Feature toggles (`my.*`) + +Optional app modules are always imported (via `modules/apps/default.nix`) but only +activate when a host sets the corresponding flag, so hosts never need to edit +import lists: + +| Option | Enables | +| --- | --- | +| `my.username` | Primary user (users, home-manager, getty autologin) | +| `my.gaming.enable` | Steam, Gamemode, MangoHud | +| `my.ai.local.enable` | Ollama (CUDA), ComfyUI, Open WebUI | + +Hardware modules remain explicit imports per host (e.g. `modules/hardware/nvidia.nix`). diff --git a/flake.lock b/flake.lock index e33f184..bc5ec97 100644 --- a/flake.lock +++ b/flake.lock @@ -51,7 +51,9 @@ "comfy-ui": { "inputs": { "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { "lastModified": 1787851822, @@ -186,7 +188,9 @@ }, "nixos-hardware": { "inputs": { - "nixpkgs": "nixpkgs_2" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { "lastModified": 1788044418, @@ -205,16 +209,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1766902085, - "narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=", + "lastModified": 1787962033, + "narHash": "sha256-u6z9VTZA4Kf3RkHQo9sQI7NI4Ei/uiU9vrMqOiwWP1Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4", + "rev": "c5c4a43b0e8056328ec4529f735cabdb8f1942bb", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-unstable", + "ref": "nixos-26.05", "repo": "nixpkgs", "type": "github" } @@ -250,56 +254,13 @@ "type": "github" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 1767892417, - "narHash": "sha256-8bW3q88CEg2u4hSP66Vf4lpbLonHz7hqDNBMcCY7E9U=", - "rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba", - "type": "tarball", - "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre924538.3497aa5c9457/nixexprs.tar.xz" - }, - "original": { - "type": "tarball", - "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz" - } - }, - "nixpkgs_3": { - "locked": { - "lastModified": 1787962033, - "narHash": "sha256-u6z9VTZA4Kf3RkHQo9sQI7NI4Ei/uiU9vrMqOiwWP1Y=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c5c4a43b0e8056328ec4529f735cabdb8f1942bb", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-26.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_4": { - "locked": { - "lastModified": 1773646010, - "narHash": "sha256-iYrs97hS7p5u4lQzuNWzuALGIOdkPXvjz7bviiBjUu8=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "5b2c2d84341b2afb5647081c1386a80d7a8d8605", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "pi": { "inputs": { "bun2nix": "bun2nix", "jail-nix": "jail-nix", - "nixpkgs": "nixpkgs_4", + "nixpkgs": [ + "nixpkgs" + ], "systems": "systems" }, "locked": { @@ -324,7 +285,7 @@ "herdr": "herdr", "home-manager": "home-manager", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs", "nixpkgs-unstable": "nixpkgs-unstable", "pi": "pi" } diff --git a/flake.nix b/flake.nix index 7a70c74..a6d1992 100644 --- a/flake.nix +++ b/flake.nix @@ -4,7 +4,10 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; - nixos-hardware.url = "github:NixOS/nixos-hardware/master"; + nixos-hardware = { + url = "github:NixOS/nixos-hardware/master"; + inputs.nixpkgs.follows = "nixpkgs"; + }; home-manager = { url = "github:nix-community/home-manager/release-26.05"; @@ -23,9 +26,9 @@ comfy-ui = { url = "github:utensils/comfyui-nix"; + inputs.nixpkgs.follows = "nixpkgs"; }; - herdr = { url = "github:herdrdev/herdr"; inputs.nixpkgs.follows = "nixpkgs"; @@ -33,6 +36,7 @@ pi = { url = "github:lukasl-dev/pi.nix"; + inputs.nixpkgs.follows = "nixpkgs"; }; }; @@ -46,26 +50,18 @@ ./modules/graphical ./modules/apps inputs.home-manager.nixosModules.home-manager - { - nixpkgs.overlays = [ - (final: prev: { - unstable = import inputs.nixpkgs-unstable { - inherit (final) system; - config.allowUnfree = true; - }; - }) - inputs.antigravity.overlays.default - inputs.comfy-ui.overlays.default - ]; - - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - extraSpecialArgs = { inherit inputs; }; - backupFileExtension = "backup"; - users.anish = import ./home; - }; - } + ( + { config, ... }: + { + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + extraSpecialArgs = { inherit inputs; }; + backupFileExtension = "backup"; + users.${config.my.username} = import ./home; + }; + } + ) ]; in { @@ -80,6 +76,8 @@ }; }; + formatter.${system} = inputs.nixpkgs.legacyPackages.${system}.nixfmt; + devShells.${system}.default = let pkgs = import inputs.nixpkgs { diff --git a/home/brave.nix b/home/brave.nix index a03698f..4a8b770 100644 --- a/home/brave.nix +++ b/home/brave.nix @@ -29,25 +29,26 @@ let }; in { - programs.chromium = { - enable = true; - package = pkgs.brave; - - commandLineArgs = [ - "--enable-features=UseOzonePlatform" - "--ozone-platform=wayland" - "--enable-wayland-ime" - "--ignore-gpu-blocklist" - "--enable-gpu-rasterization" - "--enable-zero-copy" - ]; - - extensions = [ - { id = "nngceckbapebfimnlniiiahkandclblb"; } # Bitwarden - { id = "hfjbmagddngcpeloejdejnfgbamkjaeg"; } # Vimium C - ]; - }; - xdg.configFile."brave/policies/managed/policies.json".text = builtins.toJSON bravePolicies; - xdg.configFile."BraveSoftware/Brave-Browser/policies/managed/policies.json".text = builtins.toJSON bravePolicies; - xdg.configFile."chromium/policies/managed/policies.json".text = builtins.toJSON bravePolicies; + programs.chromium = { + enable = true; + package = pkgs.brave; + + commandLineArgs = [ + "--enable-features=UseOzonePlatform" + "--ozone-platform=wayland" + "--enable-wayland-ime" + "--ignore-gpu-blocklist" + "--enable-gpu-rasterization" + "--enable-zero-copy" + ]; + + extensions = [ + { id = "nngceckbapebfimnlniiiahkandclblb"; } # Bitwarden + { id = "hfjbmagddngcpeloejdejnfgbamkjaeg"; } # Vimium C + ]; + }; + xdg.configFile."brave/policies/managed/policies.json".text = builtins.toJSON bravePolicies; + xdg.configFile."BraveSoftware/Brave-Browser/policies/managed/policies.json".text = + builtins.toJSON bravePolicies; + xdg.configFile."chromium/policies/managed/policies.json".text = builtins.toJSON bravePolicies; } diff --git a/home/foot.nix b/home/foot.nix index acbc63b..cf6bf8d 100644 --- a/home/foot.nix +++ b/home/foot.nix @@ -1,14 +1,22 @@ { pkgs, inputs, ... }: let - herdrPkg = if (inputs ? herdr && inputs.herdr ? packages && inputs.herdr.packages ? ${pkgs.stdenv.hostPlatform.system}) - then inputs.herdr.packages.${pkgs.stdenv.hostPlatform.system}.default - else (pkgs.herdr or null); + herdrPkg = + if + ( + inputs ? herdr + && inputs.herdr ? packages + && inputs.herdr.packages ? ${pkgs.stdenv.hostPlatform.system} + ) + then + inputs.herdr.packages.${pkgs.stdenv.hostPlatform.system}.default + else + (pkgs.herdr or null); herdrPicker = pkgs.writeShellScriptBin "herdr-picker" (builtins.readFile ./scripts/herdr-picker.sh); in { - home.packages = (if herdrPkg != null then [ herdrPkg ] else []) ++ [ + home.packages = (if herdrPkg != null then [ herdrPkg ] else [ ]) ++ [ herdrPicker ]; @@ -51,24 +59,24 @@ in # Cursor text and cursor (background) colors cursor = "0e0e0e cffc00"; - regular0 = "0e0e0e"; # bgSecondary - regular1 = "ff7a59"; # accentCoral - regular2 = "cffc00"; # accentVolt (green) - regular3 = "e3ff66"; # accentVoltLight (yellow) - regular4 = "00bfff"; # accentBlue - regular5 = "c6c6c7"; # Neutral Gray (magenta) - regular6 = "66d9ff"; # Light Cyan - regular7 = "e5e2e1"; # textSecondary + regular0 = "0e0e0e"; # bgSecondary + regular1 = "ff7a59"; # accentCoral + regular2 = "cffc00"; # accentVolt (green) + regular3 = "e3ff66"; # accentVoltLight (yellow) + regular4 = "00bfff"; # accentBlue + regular5 = "c6c6c7"; # Neutral Gray (magenta) + regular6 = "66d9ff"; # Light Cyan + regular7 = "e5e2e1"; # textSecondary # Bright Colors - bright0 = "2a2929"; # surfaceVariant - bright1 = "ff9a82"; # Bright Coral - bright2 = "dfff66"; # Bright Lime - bright3 = "f0ff8c"; # Bright Volt - bright4 = "66d9ff"; # Bright Blue - bright5 = "e0e0e1"; # Bright Gray - bright6 = "99e6ff"; # Bright Cyan - bright7 = "ffffff"; # textPrimary + bright0 = "2a2929"; # surfaceVariant + bright1 = "ff9a82"; # Bright Coral + bright2 = "dfff66"; # Bright Lime + bright3 = "f0ff8c"; # Bright Volt + bright4 = "66d9ff"; # Bright Blue + bright5 = "e0e0e1"; # Bright Gray + bright6 = "99e6ff"; # Bright Cyan + bright7 = "ffffff"; # textPrimary # Selection & URLs - volt lime selection like the site selection-foreground = "0e0e0e"; diff --git a/home/hypr/default.nix b/home/hypr/default.nix index ea4ecbd..d27259c 100644 --- a/home/hypr/default.nix +++ b/home/hypr/default.nix @@ -1,4 +1,9 @@ -{ pkgs, lib, config, ... }: +{ + pkgs, + lib, + config, + ... +}: let # Deterministic Silicon Volt wallpaper: rendered from SVG at build time, @@ -8,65 +13,65 @@ let ''; in { - imports = [ - ./hyprland.nix - ./hyprlock.nix - ./hypridle.nix - ./quickshell.nix - ]; + imports = [ + ./hyprland.nix + ./hyprlock.nix + ./hypridle.nix + ./quickshell.nix + ]; - home.packages = with pkgs; [ - # Utilities & Tools - grim - slurp - wl-clipboard - cliphist - brightnessctl - jq + home.packages = with pkgs; [ + # Utilities & Tools + grim + slurp + wl-clipboard + cliphist + brightnessctl + jq - # Desktop Environment / Hyprland ecosystem - hyprpaper - hyprpolkitagent - ]; + # Desktop Environment / Hyprland ecosystem + hyprpaper + hyprpolkitagent + ]; - # Build-time rendered wallpaper - xdg.dataFile."backgrounds/silicon-volt.png".source = wallpaper; + # Build-time rendered wallpaper + xdg.dataFile."backgrounds/silicon-volt.png".source = wallpaper; - # hyprpaper: load the Silicon Volt wallpaper on every output - xdg.configFile."hypr/hyprpaper.conf".text = '' - preload = ${config.home.homeDirectory}/.local/share/backgrounds/silicon-volt.png - wallpaper = ,${config.home.homeDirectory}/.local/share/backgrounds/silicon-volt.png - splash = false - ''; + # hyprpaper: load the Silicon Volt wallpaper on every output + xdg.configFile."hypr/hyprpaper.conf".text = '' + preload = ${config.home.homeDirectory}/.local/share/backgrounds/silicon-volt.png + wallpaper = ,${config.home.homeDirectory}/.local/share/backgrounds/silicon-volt.png + splash = false + ''; - # Notifications: flat brutalist-glass cards with volt accents - services.mako = { - enable = true; + # Notifications: flat brutalist-glass cards with volt accents + services.mako = { + enable = true; - settings = { - background-color = "#1c1b1bee"; - text-color = "#e5e2e1"; - border-color = "#cffc00"; - border-size = 1; - border-radius = 0; - width = 420; - margin = "12"; - padding = "14"; - default-timeout = 6000; - font = "JetBrainsMono Nerd Font 11"; - format = "%s\\n%b"; - "icon-location" = "left"; - max-icon-size = 48; + settings = { + background-color = "#1c1b1bee"; + text-color = "#e5e2e1"; + border-color = "#cffc00"; + border-size = 1; + border-radius = 0; + width = 420; + margin = "12"; + padding = "14"; + default-timeout = 6000; + font = "JetBrainsMono Nerd Font 11"; + format = "%s\\n%b"; + "icon-location" = "left"; + max-icon-size = 48; - "urgency=critical" = { - border-color = "#ff7a59"; - text-color = "#ffffff"; - default-timeout = 0; - }; - "urgency=low" = { - border-color = "#2a2929"; - text-color = "#adaaaa"; - }; - }; + "urgency=critical" = { + border-color = "#ff7a59"; + text-color = "#ffffff"; + default-timeout = 0; + }; + "urgency=low" = { + border-color = "#2a2929"; + text-color = "#adaaaa"; + }; }; + }; } diff --git a/home/hypr/hyprland.nix b/home/hypr/hyprland.nix index 9f68dec..c6ba5dd 100644 --- a/home/hypr/hyprland.nix +++ b/home/hypr/hyprland.nix @@ -1,4 +1,9 @@ -{ pkgs, lib, config, ... }: +{ + pkgs, + lib, + config, + ... +}: let mkLua = lib.generators.mkLuaInline; @@ -8,395 +13,621 @@ in # Per-host monitor configuration. # # Hosts declare their displays once, in hosts//default.nix, via: - # home-manager.users.anish.volt.monitors = [ { ... } ]; + # home-manager.users..volt.monitors = [ { ... } ]; # and the setting flows into Hyprland here. The default (empty output + # preferred mode) works on any machine with any display. # ------------------------------------------------------------------------- options.volt.monitors = lib.mkOption { description = "Hyprland monitor rules for this host"; - type = lib.types.listOf (lib.types.submodule { - options = { - output = lib.mkOption { - type = lib.types.str; - default = ""; - description = "Output name or desc: match. Empty string matches every output."; + type = lib.types.listOf ( + lib.types.submodule { + options = { + output = lib.mkOption { + type = lib.types.str; + default = ""; + description = "Output name or desc: match. Empty string matches every output."; + }; + mode = lib.mkOption { + type = lib.types.str; + default = "preferred"; + description = "Resolution@refresh, e.g. \"3840x2160@164.99Hz\" or \"preferred\"."; + }; + position = lib.mkOption { + type = lib.types.str; + default = "auto"; + }; + scale = lib.mkOption { + type = lib.types.either lib.types.number lib.types.str; + default = "auto"; + }; + vrr = lib.mkOption { + type = lib.types.nullOr (lib.types.either lib.types.number lib.types.str); + default = null; + description = "Optional per-monitor VRR setting (0/1/on-demand)."; + }; }; - mode = lib.mkOption { - type = lib.types.str; - default = "preferred"; - description = "Resolution@refresh, e.g. \"3840x2160@164.99Hz\" or \"preferred\"."; - }; - position = lib.mkOption { - type = lib.types.str; - default = "auto"; - }; - scale = lib.mkOption { - type = lib.types.either lib.types.number lib.types.str; - default = "auto"; - }; - vrr = lib.mkOption { - type = lib.types.nullOr (lib.types.either lib.types.number lib.types.str); - default = null; - description = "Optional per-monitor VRR setting (0/1/on-demand)."; - }; - }; - }); + } + ); default = [ - { output = ""; mode = "preferred"; position = "auto"; scale = "auto"; } + { + output = ""; + mode = "preferred"; + position = "auto"; + scale = "auto"; + } ]; }; config = { - wayland.windowManager.hyprland.settings.monitor = map (m: - { inherit (m) output mode position scale; } + wayland.windowManager.hyprland.settings.monitor = map ( + m: + { + inherit (m) + output + mode + position + scale + ; + } // (lib.optionalAttrs (m.vrr != null) { inherit (m) vrr; }) ) config.volt.monitors; wayland.windowManager.hyprland = { - enable = true; - configType = "lua"; - package = null; # Hyprland package is managed system-wide via NixOS programs.hyprland + enable = true; + configType = "lua"; + package = null; # Hyprland package is managed system-wide via NixOS programs.hyprland - settings = { - # ----------------------------------------------------------------------- - # 1. Variables & Modifiers (Rendered as Lua local variables) - # ----------------------------------------------------------------------- - mainMod = { _var = "SUPER"; }; - terminal = { _var = "foot"; }; - browser = { _var = "brave"; }; - - # ----------------------------------------------------------------------- - # 2. Monitors (hl.monitor) - declared per-host via volt.monitors - # (see hosts//default.nix); defaults to any display @ preferred. - # ----------------------------------------------------------------------- - - # ----------------------------------------------------------------------- - # 3. Environment Variables (hl.env) - # ----------------------------------------------------------------------- - env = [ - { _args = [ "XCURSOR_SIZE" "24" ]; } - { _args = [ "XDG_SESSION_TYPE" "wayland" ]; } - ]; - - # ----------------------------------------------------------------------- - # 4. Main Configuration (hl.config) - Strictly validates against Hyprland 0.55+ schema - # ----------------------------------------------------------------------- - config = { - input = { - kb_layout = "us"; - repeat_delay = 300; - repeat_rate = 50; - follow_mouse = 1; - sensitivity = 0; - touchpad = { - natural_scroll = false; - }; + settings = { + # ----------------------------------------------------------------------- + # 1. Variables & Modifiers (Rendered as Lua local variables) + # ----------------------------------------------------------------------- + mainMod = { + _var = "SUPER"; + }; + terminal = { + _var = "foot"; + }; + browser = { + _var = "brave"; }; - cursor = { - inactive_timeout = 3; - # Hardware cursors ON (explicit). Note: this replaces the old - # WLR_NO_HARDWARE_CURSORS=1, which forced software rendering. - no_hardware_cursors = false; - }; + # ----------------------------------------------------------------------- + # 2. Monitors (hl.monitor) - declared per-host via volt.monitors + # (see hosts//default.nix); defaults to any display @ preferred. + # ----------------------------------------------------------------------- - general = { - gaps_in = 5; - gaps_out = 10; - border_size = 2; - col = { - # Silicon Volt: electric lime gradient on focus, glass gray at rest - active_border = { - colors = [ "rgba(cffc00ee)" "rgba(e3ff66ee)" ]; - angle = 45; + # ----------------------------------------------------------------------- + # 3. Environment Variables (hl.env) + # ----------------------------------------------------------------------- + env = [ + { + _args = [ + "XCURSOR_SIZE" + "24" + ]; + } + { + _args = [ + "XDG_SESSION_TYPE" + "wayland" + ]; + } + ]; + + # ----------------------------------------------------------------------- + # 4. Main Configuration (hl.config) - Strictly validates against Hyprland 0.55+ schema + # ----------------------------------------------------------------------- + config = { + input = { + kb_layout = "us"; + repeat_delay = 300; + repeat_rate = 50; + follow_mouse = 1; + sensitivity = 0; + touchpad = { + natural_scroll = false; }; - inactive_border = "rgba(ffffff14)"; }; - layout = "dwindle"; - }; - group = { - groupbar = { - font_size = 14; - font_family = "JetBrainsMono Nerd Font"; + cursor = { + inactive_timeout = 3; + # Hardware cursors ON (explicit). Note: this replaces the old + # WLR_NO_HARDWARE_CURSORS=1, which forced software rendering. + no_hardware_cursors = false; + }; + + general = { + gaps_in = 5; + gaps_out = 10; + border_size = 2; col = { - active = "rgba(cffc0022)"; - inactive = "rgba(ffffff08)"; + # Silicon Volt: electric lime gradient on focus, glass gray at rest + active_border = { + colors = [ + "rgba(cffc00ee)" + "rgba(e3ff66ee)" + ]; + angle = 45; + }; + inactive_border = "rgba(ffffff14)"; + }; + layout = "dwindle"; + }; + + group = { + groupbar = { + font_size = 14; + font_family = "JetBrainsMono Nerd Font"; + col = { + active = "rgba(cffc0022)"; + inactive = "rgba(ffffff08)"; + }; + }; + + col = { + border_active = { + colors = [ + "rgba(cffc00ee)" + "rgba(e3ff66ee)" + ]; + angle = 45; + }; + border_inactive = "rgba(ffffff14)"; }; }; - col = { - border_active = { - colors = [ "rgba(cffc00ee)" "rgba(e3ff66ee)" ]; - angle = 45; + misc = { + disable_hyprland_logo = true; + disable_splash_rendering = true; + }; + + decoration = { + rounding = 4; + + # Subtle glass blur to match the brutalist-glass aesthetic + blur = { + enabled = true; + size = 4; + passes = 2; + new_optimizations = true; + ignore_opacity = true; + contrast = 1.1; + brightness = 0.9; + vibrancy = 0.1; + }; + + shadow = { + enabled = true; + range = 12; + render_power = 3; + color = "rgba(00000066)"; }; - border_inactive = "rgba(ffffff14)"; }; - }; - misc = { - disable_hyprland_logo = true; - disable_splash_rendering = true; - }; - - decoration = { - rounding = 4; - - # Subtle glass blur to match the brutalist-glass aesthetic - blur = { + animations = { enabled = true; - size = 4; - passes = 2; - new_optimizations = true; - ignore_opacity = true; - contrast = 1.1; - brightness = 0.9; - vibrancy = 0.1; }; - shadow = { + dwindle = { + preserve_split = true; + }; + + master = { + new_status = "master"; + }; + }; + + # ----------------------------------------------------------------------- + # 5. Curves & Animations (hl.curve & hl.animation) + # ----------------------------------------------------------------------- + curve = [ + { + _args = [ + "myBezier" + { + type = "bezier"; + points = [ + [ + 0.05 + 0.9 + ] + [ + 0.1 + 1.05 + ] + ]; + } + ]; + } + ]; + + animation = [ + { + leaf = "windows"; enabled = true; - range = 12; - render_power = 3; - color = "rgba(00000066)"; - }; - }; + speed = 7; + bezier = "myBezier"; + } + { + leaf = "windowsOut"; + enabled = true; + speed = 7; + bezier = "default"; + style = "popin 80%"; + } + { + leaf = "border"; + enabled = true; + speed = 10; + bezier = "default"; + } + { + leaf = "borderangle"; + enabled = true; + speed = 8; + bezier = "default"; + } + { + leaf = "fade"; + enabled = true; + speed = 7; + bezier = "default"; + } + { + leaf = "workspaces"; + enabled = true; + speed = 6; + bezier = "default"; + } + ]; - animations = { - enabled = true; - }; + # ----------------------------------------------------------------------- + # 6. Autostart Daemons & Apps (hl.on) + # ----------------------------------------------------------------------- + on = [ + { + _args = [ + "hyprland.start" + (mkLua '' + function() + hl.exec_cmd("qs") + hl.exec_cmd("hyprpaper") + hl.exec_cmd("mako") + hl.exec_cmd("wl-paste --type text --watch cliphist store") + hl.exec_cmd("wl-paste --type image --watch cliphist store") + hl.exec_cmd("${pkgs.hyprpolkitagent}/libexec/hyprpolkitagent") + end'') + ]; + } + ]; - dwindle = { - preserve_split = true; - }; + # ----------------------------------------------------------------------- + # 7. Keybindings (hl.bind) + # ----------------------------------------------------------------------- + bind = [ + # Launchers & Window Controls + { + _args = [ + (mkLua "mainMod .. \" + Q\"") + (mkLua "hl.dsp.exec_cmd(terminal)") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + C\"") + (mkLua "hl.dsp.window.close()") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + SPACE\"") + (mkLua "hl.dsp.exec_cmd(\"rofi -show combi -show-icons\")") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + N\"") + (mkLua "hl.dsp.exec_cmd(\"swaync-client -t -sw\")") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + TAB\"") + (mkLua "hl.dsp.exec_cmd(\"qs ipc call overview toggle\")") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + V\"") + (mkLua "hl.dsp.window.float({ action = \"toggle\" })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + R\"") + (mkLua "hl.dsp.exec_cmd(\"rofi -show combi\")") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + G\"") + (mkLua "hl.dsp.group.toggle()") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + F\"") + (mkLua "hl.dsp.window.fullscreen({ fullscreen = 0 })") + ]; + } - master = { - new_status = "master"; - }; + # Move focus with mainMod + vim + { + _args = [ + (mkLua "mainMod .. \" + h\"") + (mkLua "hl.dsp.focus({ direction = \"left\" })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + l\"") + (mkLua "hl.dsp.focus({ direction = \"right\" })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + k\"") + (mkLua "hl.dsp.focus({ direction = \"up\" })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + j\"") + (mkLua "hl.dsp.focus({ direction = \"down\" })") + ]; + } + + # Move focus within a grouped page + { + _args = [ + (mkLua "mainMod .. \" + e\"") + (mkLua "hl.dsp.group.next()") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + d\"") + (mkLua "hl.dsp.group.prev()") + ]; + } + + # Move window or group with vim keys + { + _args = [ + (mkLua "mainMod .. \" + SHIFT + h\"") + (mkLua "hl.dsp.window.move({ direction = \"left\" })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + SHIFT + l\"") + (mkLua "hl.dsp.window.move({ direction = \"right\" })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + SHIFT + k\"") + (mkLua "hl.dsp.window.move({ direction = \"up\" })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + SHIFT + j\"") + (mkLua "hl.dsp.window.move({ direction = \"down\" })") + ]; + } + + # Scroll through existing workspaces with mainMod + scroll + { + _args = [ + (mkLua "mainMod .. \" + mouse_down\"") + (mkLua "hl.dsp.focus({ workspace = \"e+1\" })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + mouse_up\"") + (mkLua "hl.dsp.focus({ workspace = \"e-1\" })") + ]; + } + + # Lock shortcut + { + _args = [ + (mkLua "mainMod .. \" + S\"") + (mkLua "hl.dsp.exec_cmd(\"hyprlock\")") + ]; + } + + # Quick access applications + { + _args = [ + (mkLua "mainMod .. \" + b\"") + (mkLua "hl.dsp.exec_cmd(browser)") + ]; + } + + # Scratch workspace + { + _args = [ + (mkLua "mainMod .. \" + RETURN\"") + (mkLua "hl.dsp.workspace.toggle_special(\"scratch\")") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + SHIFT + RETURN\"") + (mkLua "hl.dsp.window.move({ workspace = \"special:scratch\" })") + ]; + } + + # Messaging workspace + { + _args = [ + (mkLua "mainMod .. \" + M\"") + (mkLua "hl.dsp.workspace.toggle_special(\"messaging\")") + ]; + } + + # Move/resize windows with mouse and dragging + { + _args = [ + (mkLua "mainMod .. \" + mouse:272\"") + (mkLua "hl.dsp.window.drag()") + { mouse = true; } + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + mouse:273\"") + (mkLua "hl.dsp.window.resize()") + { mouse = true; } + ]; + } + + # Function Row Keys + { + _args = [ + "XF86AudioRaiseVolume" + (mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-volume @DEFAULT_SINK@ +5%\")") + { repeating = true; } + ]; + } + { + _args = [ + "XF86AudioLowerVolume" + (mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-volume @DEFAULT_SINK@ -5%\")") + { + repeating = true; + locked = true; + } + ]; + } + { + _args = [ + "XF86AudioMute" + (mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-mute @DEFAULT_SINK@ toggle\")") + { + repeating = true; + locked = true; + } + ]; + } + { + _args = [ + "XF86MonBrightnessUp" + (mkLua "hl.dsp.exec_cmd(\"brightnessctl set 5%+\")") + { + repeating = true; + locked = true; + } + ]; + } + { + _args = [ + "XF86MonBrightnessDown" + (mkLua "hl.dsp.exec_cmd(\"brightnessctl set 5%-\")") + { + repeating = true; + locked = true; + } + ]; + } + + # Lid switch - generically detects the embedded (eDP*) panel on any laptop + { + _args = [ + "switch:off:Lid Switch" + (mkLua "hl.dsp.exec_cmd(\"m=$(hyprctl monitors | awk '$1==\\\"Monitor\\\"{print $2; exit}'); [ -n \\\"$m\\\" ] && hyprctl keyword monitor \\\"$m, preferred, auto, auto\\\"\")") + { locked = true; } + ]; + } + { + _args = [ + "switch:on:Lid Switch" + (mkLua "hl.dsp.exec_cmd(\"m=$(hyprctl monitors | awk '$1==\\\"Monitor\\\"{print $2; exit}'); [ -n \\\"$m\\\" ] && hyprctl keyword monitor \\\"$m, disable\\\"\")") + { locked = true; } + ]; + } + ] + # Workspace 1-9 switching and moving + ++ (lib.concatMap (i: [ + { + _args = [ + (mkLua "mainMod .. \" + ${toString i}\"") + (mkLua "hl.dsp.focus({ workspace = ${toString i} })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + SHIFT + ${toString i}\"") + (mkLua "hl.dsp.window.move({ workspace = ${toString i} })") + ]; + } + ]) (lib.range 1 9)) + # Workspace 10 switching and moving (mapped to key 0) + ++ [ + { + _args = [ + (mkLua "mainMod .. \" + 0\"") + (mkLua "hl.dsp.focus({ workspace = 10 })") + ]; + } + { + _args = [ + (mkLua "mainMod .. \" + SHIFT + 0\"") + (mkLua "hl.dsp.window.move({ workspace = 10 })") + ]; + } + ]; + + # ----------------------------------------------------------------------- + # 8. Workspace Rules (hl.workspace_rule) + # ----------------------------------------------------------------------- + workspace_rule = [ + { + workspace = "name:messaging"; + on_created_empty = "[] togglegroup"; + } + ]; + + # ----------------------------------------------------------------------- + # 9. Window Rules (hl.window_rule) + # ----------------------------------------------------------------------- + window_rule = [ + { + name = "signal-messaging"; + match = { + class = "Signal"; + }; + workspace = "special:messaging"; + } + { + name = "vesktop-messaging"; + match = { + class = "vesktop"; + }; + workspace = "special:messaging"; + } + { + name = "ghidra-tile"; + match = { + class = "ghidra-Ghidra"; + }; + float = false; + } + ]; }; - - # ----------------------------------------------------------------------- - # 5. Curves & Animations (hl.curve & hl.animation) - # ----------------------------------------------------------------------- - curve = [ - { - _args = [ - "myBezier" - { - type = "bezier"; - points = [ [ 0.05 0.9 ] [ 0.1 1.05 ] ]; - } - ]; - } - ]; - - animation = [ - { leaf = "windows"; enabled = true; speed = 7; bezier = "myBezier"; } - { leaf = "windowsOut"; enabled = true; speed = 7; bezier = "default"; style = "popin 80%"; } - { leaf = "border"; enabled = true; speed = 10; bezier = "default"; } - { leaf = "borderangle"; enabled = true; speed = 8; bezier = "default"; } - { leaf = "fade"; enabled = true; speed = 7; bezier = "default"; } - { leaf = "workspaces"; enabled = true; speed = 6; bezier = "default"; } - ]; - - # ----------------------------------------------------------------------- - # 6. Autostart Daemons & Apps (hl.on) - # ----------------------------------------------------------------------- - on = [ - { - _args = [ - "hyprland.start" - (mkLua ''function() - hl.exec_cmd("qs") - hl.exec_cmd("hyprpaper") - hl.exec_cmd("mako") - hl.exec_cmd("wl-paste --type text --watch cliphist store") - hl.exec_cmd("wl-paste --type image --watch cliphist store") - hl.exec_cmd("${pkgs.hyprpolkitagent}/libexec/hyprpolkitagent") - end'') - ]; - } - ]; - - # ----------------------------------------------------------------------- - # 7. Keybindings (hl.bind) - # ----------------------------------------------------------------------- - bind = [ - # Launchers & Window Controls - { _args = [ (mkLua "mainMod .. \" + Q\"") (mkLua "hl.dsp.exec_cmd(terminal)") ]; } - { _args = [ (mkLua "mainMod .. \" + C\"") (mkLua "hl.dsp.window.close()") ]; } - { _args = [ (mkLua "mainMod .. \" + SPACE\"") (mkLua "hl.dsp.exec_cmd(\"rofi -show combi -show-icons\")") ]; } - { _args = [ (mkLua "mainMod .. \" + N\"") (mkLua "hl.dsp.exec_cmd(\"swaync-client -t -sw\")") ]; } - { _args = [ (mkLua "mainMod .. \" + TAB\"") (mkLua "hl.dsp.exec_cmd(\"qs ipc call overview toggle\")") ]; } - { _args = [ (mkLua "mainMod .. \" + V\"") (mkLua "hl.dsp.window.float({ action = \"toggle\" })") ]; } - { _args = [ (mkLua "mainMod .. \" + R\"") (mkLua "hl.dsp.exec_cmd(\"rofi -show combi\")") ]; } - { _args = [ (mkLua "mainMod .. \" + G\"") (mkLua "hl.dsp.group.toggle()") ]; } - { _args = [ (mkLua "mainMod .. \" + F\"") (mkLua "hl.dsp.window.fullscreen({ fullscreen = 0 })") ]; } - - # Move focus with mainMod + vim - { _args = [ (mkLua "mainMod .. \" + h\"") (mkLua "hl.dsp.focus({ direction = \"left\" })") ]; } - { _args = [ (mkLua "mainMod .. \" + l\"") (mkLua "hl.dsp.focus({ direction = \"right\" })") ]; } - { _args = [ (mkLua "mainMod .. \" + k\"") (mkLua "hl.dsp.focus({ direction = \"up\" })") ]; } - { _args = [ (mkLua "mainMod .. \" + j\"") (mkLua "hl.dsp.focus({ direction = \"down\" })") ]; } - - # Move focus within a grouped page - { _args = [ (mkLua "mainMod .. \" + e\"") (mkLua "hl.dsp.group.next()") ]; } - { _args = [ (mkLua "mainMod .. \" + d\"") (mkLua "hl.dsp.group.prev()") ]; } - - # Move window or group with vim keys - { _args = [ (mkLua "mainMod .. \" + SHIFT + h\"") (mkLua "hl.dsp.window.move({ direction = \"left\" })") ]; } - { _args = [ (mkLua "mainMod .. \" + SHIFT + l\"") (mkLua "hl.dsp.window.move({ direction = \"right\" })") ]; } - { _args = [ (mkLua "mainMod .. \" + SHIFT + k\"") (mkLua "hl.dsp.window.move({ direction = \"up\" })") ]; } - { _args = [ (mkLua "mainMod .. \" + SHIFT + j\"") (mkLua "hl.dsp.window.move({ direction = \"down\" })") ]; } - - # Scroll through existing workspaces with mainMod + scroll - { _args = [ (mkLua "mainMod .. \" + mouse_down\"") (mkLua "hl.dsp.focus({ workspace = \"e+1\" })") ]; } - { _args = [ (mkLua "mainMod .. \" + mouse_up\"") (mkLua "hl.dsp.focus({ workspace = \"e-1\" })") ]; } - - # Lock shortcut - { _args = [ (mkLua "mainMod .. \" + S\"") (mkLua "hl.dsp.exec_cmd(\"hyprlock\")") ]; } - - # Quick access applications - { _args = [ (mkLua "mainMod .. \" + b\"") (mkLua "hl.dsp.exec_cmd(browser)") ]; } - - # Scratch workspace - { _args = [ (mkLua "mainMod .. \" + RETURN\"") (mkLua "hl.dsp.workspace.toggle_special(\"scratch\")") ]; } - { _args = [ (mkLua "mainMod .. \" + SHIFT + RETURN\"") (mkLua "hl.dsp.window.move({ workspace = \"special:scratch\" })") ]; } - - # Messaging workspace - { _args = [ (mkLua "mainMod .. \" + M\"") (mkLua "hl.dsp.workspace.toggle_special(\"messaging\")") ]; } - - # Move/resize windows with mouse and dragging - { - _args = [ - (mkLua "mainMod .. \" + mouse:272\"") - (mkLua "hl.dsp.window.drag()") - { mouse = true; } - ]; - } - { - _args = [ - (mkLua "mainMod .. \" + mouse:273\"") - (mkLua "hl.dsp.window.resize()") - { mouse = true; } - ]; - } - - # Function Row Keys - { - _args = [ - "XF86AudioRaiseVolume" - (mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-volume @DEFAULT_SINK@ +5%\")") - { repeating = true; } - ]; - } - { - _args = [ - "XF86AudioLowerVolume" - (mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-volume @DEFAULT_SINK@ -5%\")") - { repeating = true; locked = true; } - ]; - } - { - _args = [ - "XF86AudioMute" - (mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-mute @DEFAULT_SINK@ toggle\")") - { repeating = true; locked = true; } - ]; - } - { - _args = [ - "XF86MonBrightnessUp" - (mkLua "hl.dsp.exec_cmd(\"brightnessctl set 5%+\")") - { repeating = true; locked = true; } - ]; - } - { - _args = [ - "XF86MonBrightnessDown" - (mkLua "hl.dsp.exec_cmd(\"brightnessctl set 5%-\")") - { repeating = true; locked = true; } - ]; - } - - # Lid switch - generically detects the embedded (eDP*) panel on any laptop - { - _args = [ - "switch:off:Lid Switch" - (mkLua "hl.dsp.exec_cmd(\"m=$(hyprctl monitors | awk '$1==\\\"Monitor\\\"{print $2; exit}'); [ -n \\\"$m\\\" ] && hyprctl keyword monitor \\\"$m, preferred, auto, auto\\\"\")") - { locked = true; } - ]; - } - { - _args = [ - "switch:on:Lid Switch" - (mkLua "hl.dsp.exec_cmd(\"m=$(hyprctl monitors | awk '$1==\\\"Monitor\\\"{print $2; exit}'); [ -n \\\"$m\\\" ] && hyprctl keyword monitor \\\"$m, disable\\\"\")") - { locked = true; } - ]; - } - ] - # Workspace 1-9 switching and moving - ++ (lib.concatMap (i: [ - { - _args = [ - (mkLua "mainMod .. \" + ${toString i}\"") - (mkLua "hl.dsp.focus({ workspace = ${toString i} })") - ]; - } - { - _args = [ - (mkLua "mainMod .. \" + SHIFT + ${toString i}\"") - (mkLua "hl.dsp.window.move({ workspace = ${toString i} })") - ]; - } - ]) (lib.range 1 9)) - # Workspace 10 switching and moving (mapped to key 0) - ++ [ - { - _args = [ - (mkLua "mainMod .. \" + 0\"") - (mkLua "hl.dsp.focus({ workspace = 10 })") - ]; - } - { - _args = [ - (mkLua "mainMod .. \" + SHIFT + 0\"") - (mkLua "hl.dsp.window.move({ workspace = 10 })") - ]; - } - ]; - - # ----------------------------------------------------------------------- - # 8. Workspace Rules (hl.workspace_rule) - # ----------------------------------------------------------------------- - workspace_rule = [ - { - workspace = "name:messaging"; - on_created_empty = "[] togglegroup"; - } - ]; - - # ----------------------------------------------------------------------- - # 9. Window Rules (hl.window_rule) - # ----------------------------------------------------------------------- - window_rule = [ - { - name = "signal-messaging"; - match = { class = "Signal"; }; - workspace = "special:messaging"; - } - { - name = "vesktop-messaging"; - match = { class = "vesktop"; }; - workspace = "special:messaging"; - } - { - name = "ghidra-tile"; - match = { class = "ghidra-Ghidra"; }; - float = false; - } - ]; - }; }; }; } diff --git a/home/hypr/quickshell.nix b/home/hypr/quickshell.nix index bb2e7bf..1cdd430 100644 --- a/home/hypr/quickshell.nix +++ b/home/hypr/quickshell.nix @@ -1,9 +1,17 @@ { pkgs, inputs, ... }: let - quickshellPkg = if (inputs ? quickshell && inputs.quickshell ? packages && inputs.quickshell.packages ? ${pkgs.stdenv.hostPlatform.system}) - then inputs.quickshell.packages.${pkgs.stdenv.hostPlatform.system}.default - else (pkgs.quickshell or pkgs.qt6.qtbase); + quickshellPkg = + if + ( + inputs ? quickshell + && inputs.quickshell ? packages + && inputs.quickshell.packages ? ${pkgs.stdenv.hostPlatform.system} + ) + then + inputs.quickshell.packages.${pkgs.stdenv.hostPlatform.system}.default + else + (pkgs.quickshell or pkgs.qt6.qtbase); in { home.packages = with pkgs; [ diff --git a/home/nvim/default.nix b/home/nvim/default.nix index dd91429..595a0f9 100644 --- a/home/nvim/default.nix +++ b/home/nvim/default.nix @@ -1,76 +1,83 @@ -{ config, pkgs, lib, ... }: +{ + config, + pkgs, + lib, + ... +}: let - treesitterParsers = pkgs.symlinkJoin { - name = "treesitter-parsers"; - paths = builtins.attrValues pkgs.vimPlugins.nvim-treesitter.passthru.grammarPlugins; - }; + treesitterParsers = pkgs.symlinkJoin { + name = "treesitter-parsers"; + paths = builtins.attrValues pkgs.vimPlugins.nvim-treesitter.passthru.grammarPlugins; + }; in { - programs.neovim = { - enable = true; - defaultEditor = true; - viAlias = true; - vimAlias = true; - withNodeJs = true; - withPython3 = true; + programs.neovim = { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + withNodeJs = true; + withPython3 = true; - extraPackages = with pkgs; [ - # Native compilation tools & Treesitter CLI - gcc - clang - gnumake - cmake - tree-sitter + extraPackages = with pkgs; [ + # Native compilation tools & Treesitter CLI + gcc + clang + gnumake + cmake + tree-sitter - # Search & Fuzzy Finding - ripgrep - fd - fzf + # Search & Fuzzy Finding + ripgrep + fd + fzf - # Archive and Network Utilities - git - curl - unzip - gnutar - gzip + # Archive and Network Utilities + git + curl + unzip + gnutar + gzip - # Language Servers, Linters & Formatters (Declarative, no Mason needed) - # Nix - nil - nixfmt - statix - # Lua - lua-language-server - stylua - # C / C++ - llvmPackages_latest.clang-tools - llvmPackages_latest.lldb - # Rust - rust-analyzer - # Python - pyright - ruff - # Web / TypeScript / JavaScript / HTML / CSS / JSON - vtsls - vscode-langservers-extracted - prettier - # Shell - shfmt - shellcheck - ]; + # Language Servers, Linters & Formatters (Declarative, no Mason needed) + # Nix + nil + nixfmt + statix + # Lua + lua-language-server + stylua + # C / C++ + llvmPackages_latest.clang-tools + llvmPackages_latest.lldb + # Rust + rust-analyzer + # Python + pyright + ruff + # Web / TypeScript / JavaScript / HTML / CSS / JSON + vtsls + vscode-langservers-extracted + prettier + # Shell + shfmt + shellcheck + ]; - extraWrapperArgs = [ - "--set" "NVIM_TREESITTER_PARSERS" "${treesitterParsers}" - ]; - }; + extraWrapperArgs = [ + "--set" + "NVIM_TREESITTER_PARSERS" + "${treesitterParsers}" + ]; + }; - # Symlink LazyVim configuration to ~/.config/nvim recursively - xdg.configFile."nvim" = { - source = ./config; - recursive = true; - }; + # Symlink LazyVim configuration to ~/.config/nvim recursively + xdg.configFile."nvim" = { + source = ./config; + recursive = true; + }; - # Symlink precompiled Treesitter parsers directly into ~/.config/nvim/parser - xdg.configFile."nvim/parser".source = "${treesitterParsers}/parser"; + # Symlink precompiled Treesitter parsers directly into ~/.config/nvim/parser + xdg.configFile."nvim/parser".source = "${treesitterParsers}/parser"; } diff --git a/home/rofi.nix b/home/rofi.nix index c12cf9e..3cf5fc3 100644 --- a/home/rofi.nix +++ b/home/rofi.nix @@ -3,8 +3,7 @@ let # Rofi script-mode indexer: exposes every executable user script # (shell, python, whatever) so the launcher finds "everything". - rofiScripts = pkgs.writeShellScriptBin "rofi-scripts" - (builtins.readFile ./rofi/rofi-scripts.sh); + rofiScripts = pkgs.writeShellScriptBin "rofi-scripts" (builtins.readFile ./rofi/rofi-scripts.sh); in { programs.rofi = { diff --git a/home/zsh/init.zsh b/home/zsh/init.zsh index 810c312..42270b4 100644 --- a/home/zsh/init.zsh +++ b/home/zsh/init.zsh @@ -47,7 +47,7 @@ rebuild () { shift 2>/dev/null || true local config_dir="${FLAKE_CONFIG:-$HOME/NixOS-Configs}" - local host="hades" + local host="${REBUILD_HOST:-$(hostname)}" local target="$config_dir#$host" case "$action" in diff --git a/hosts/hades/default.nix b/hosts/hades/default.nix index 5207bd4..92266f9 100644 --- a/hosts/hades/default.nix +++ b/hosts/hades/default.nix @@ -11,18 +11,21 @@ inputs.disko.nixosModules.disko ./disko.nix ./hardware-configuration.nix - ./display-configuration.nix ../../modules/hardware/nvidia.nix - ../../modules/apps/gaming.nix - ../../modules/apps/local_ai.nix ]; networking.hostName = "hades"; + # Opt this machine into the shared optional feature modules. + my = { + gaming.enable = true; + ai.local.enable = true; + }; + # --------------------------------------------------------------------------- # Host display configuration (absorbed by home/hypr/hyprland.nix) # --------------------------------------------------------------------------- - home-manager.users.anish.volt.monitors = [ + home-manager.users.${config.my.username}.volt.monitors = [ { # Samsung Odyssey Ark - matched by description so it survives port changes output = "desc:Samsung Electric Company Odyssey Ark H1AK500000"; @@ -44,7 +47,7 @@ # Ensure /games directory is accessible by default user systemd.tmpfiles.rules = [ - "d /games 0755 anish users -" + "d /games 0755 ${config.my.username} users -" ]; powerManagement.cpuFreqGovernor = "performance"; @@ -58,7 +61,6 @@ }; environment.systemPackages = with pkgs; [ - mangohud nvtopPackages.nvidia ]; } diff --git a/hosts/hades/disko.nix b/hosts/hades/disko.nix index ae09d88..4c57071 100644 --- a/hosts/hades/disko.nix +++ b/hosts/hades/disko.nix @@ -14,7 +14,10 @@ type = "filesystem"; format = "vfat"; mountpoint = "/boot"; - mountOptions = [ "fmask=0077" "dmask=0077" ]; + mountOptions = [ + "fmask=0077" + "dmask=0077" + ]; }; }; root = { diff --git a/hosts/hades/display-configuration.nix b/hosts/hades/display-configuration.nix deleted file mode 100644 index f2237fd..0000000 --- a/hosts/hades/display-configuration.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ ... }: - -{ - # Host-specific display configurations can be placed here if needed. -} diff --git a/hosts/hades/hardware-configuration.nix b/hosts/hades/hardware-configuration.nix index 8d526f1..22d9d4e 100644 --- a/hosts/hades/hardware-configuration.nix +++ b/hosts/hades/hardware-configuration.nix @@ -1,14 +1,27 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: +{ + config, + lib, + pkgs, + modulesPath, + ... +}: { imports = [ - (modulesPath + "/installer/scan/not-detected.nix") - ]; + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "thunderbolt" "usbhid" "sd_mod" ]; + boot.initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "ahci" + "thunderbolt" + "usbhid" + "sd_mod" + ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-amd" ]; boot.extraModulePackages = [ ]; diff --git a/modules/apps/browser.nix b/modules/apps/browser.nix deleted file mode 100644 index 876d644..0000000 --- a/modules/apps/browser.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ ... }: - -{ - # Browser is configured and managed via Home Manager (home/brave.nix) -} diff --git a/modules/apps/communication.nix b/modules/apps/communication.nix index 2e1a5a0..321856a 100644 --- a/modules/apps/communication.nix +++ b/modules/apps/communication.nix @@ -1,8 +1,8 @@ { pkgs, ... }: { - environment.systemPackages = with pkgs; [ - vesktop - signal-desktop - ]; + environment.systemPackages = with pkgs; [ + vesktop + signal-desktop + ]; } diff --git a/modules/apps/default.nix b/modules/apps/default.nix index e51edc3..e72395a 100644 --- a/modules/apps/default.nix +++ b/modules/apps/default.nix @@ -3,9 +3,10 @@ { imports = [ ./terminal.nix - ./browser.nix ./communication.nix ./dev.nix ./virt.nix + ./gaming.nix + ./local-ai.nix ]; } diff --git a/modules/apps/gaming.nix b/modules/apps/gaming.nix index 8415512..0ea6f76 100644 --- a/modules/apps/gaming.nix +++ b/modules/apps/gaming.nix @@ -1,15 +1,22 @@ -{ pkgs, ... }: +{ + config, + lib, + pkgs, + ... +}: { + config = lib.mkIf config.my.gaming.enable { programs.steam = { - enable = true; - remotePlay.openFirewall = false; - dedicatedServer.openFirewall = false; - gamescopeSession.enable = false; + enable = true; + remotePlay.openFirewall = false; + dedicatedServer.openFirewall = false; + gamescopeSession.enable = false; }; environment.systemPackages = with pkgs; [ - mangohud - gamemode + mangohud + gamemode ]; + }; } diff --git a/modules/apps/local-ai.nix b/modules/apps/local-ai.nix new file mode 100644 index 0000000..8c20cca --- /dev/null +++ b/modules/apps/local-ai.nix @@ -0,0 +1,45 @@ +{ + config, + lib, + pkgs, + inputs, + ... +}: + +{ + imports = [ + inputs.comfy-ui.nixosModules.default + ]; + + config = lib.mkIf config.my.ai.local.enable { + services = { + comfyui = { + enable = true; + gpuSupport = "cuda"; + enableManager = true; + port = 8188; + listenAddress = "0.0.0.0"; + dataDir = "/var/lib/comfyui"; + user = "comfyui"; + group = "comfyui"; + createUser = true; + }; + + ollama = { + enable = true; + package = pkgs.unstable.ollama-cuda; + host = "0.0.0.0"; + port = 11434; + user = "ollama"; + group = "ollama"; + home = "/var/lib/ollama"; + }; + + open-webui.enable = true; + }; + + environment.systemPackages = with pkgs; [ + unstable.ollama-cuda + ]; + }; +} diff --git a/modules/apps/local_ai.nix b/modules/apps/local_ai.nix deleted file mode 100644 index fe1710a..0000000 --- a/modules/apps/local_ai.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ pkgs, inputs, ... }: - -{ - imports = [ - inputs.comfy-ui.nixosModules.default - ]; - - services = { - comfyui = { - enable = true; - gpuSupport = "cuda"; - enableManager = true; - port = 8188; - listenAddress = "0.0.0.0"; - dataDir = "/var/lib/comfyui"; - user = "comfyui"; - group = "comfyui"; - createUser = true; - }; - - ollama = { - enable = true; - package = pkgs.unstable.ollama-cuda; - host = "0.0.0.0"; - port = 11434; - user = "ollama"; - group = "ollama"; - home = "/var/lib/ollama"; - }; - - open-webui.enable = true; - }; - - environment.systemPackages = with pkgs; [ - unstable.ollama-cuda - ]; -} diff --git a/modules/apps/terminal.nix b/modules/apps/terminal.nix index 253f24c..afd2aac 100644 --- a/modules/apps/terminal.nix +++ b/modules/apps/terminal.nix @@ -1,9 +1,9 @@ { pkgs, ... }: { - # Terminal is managed elsewhere; system-level CLI helpers live here. - environment.systemPackages = with pkgs; [ - zoxide - fzf - ]; + # Terminal is managed elsewhere; system-level CLI helpers live here. + environment.systemPackages = with pkgs; [ + zoxide + fzf + ]; } diff --git a/modules/apps/virt.nix b/modules/apps/virt.nix index 377d79a..fcad3bd 100644 --- a/modules/apps/virt.nix +++ b/modules/apps/virt.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ config, pkgs, ... }: { virtualisation = { @@ -27,7 +27,7 @@ programs.virt-manager.enable = true; - users.users.anish.extraGroups = [ + users.users.${config.my.username}.extraGroups = [ "libvirtd" "kvm" "incus-admin" diff --git a/modules/core/default.nix b/modules/core/default.nix index 7116be0..89f6fb2 100644 --- a/modules/core/default.nix +++ b/modules/core/default.nix @@ -1,9 +1,10 @@ { ... }: { - imports = [ - ./system.nix - ./users.nix - ./nix.nix - ]; + imports = [ + ../options.nix + ./system.nix + ./users.nix + ./nix.nix + ]; } diff --git a/modules/core/nix.nix b/modules/core/nix.nix index 7beb8f8..b5f9163 100644 --- a/modules/core/nix.nix +++ b/modules/core/nix.nix @@ -36,12 +36,16 @@ nixpkgs.config.allowUnfree = true; + # Single source of truth for overlays; the flake module imports only the + # modules and does not declare overlays itself. nixpkgs.overlays = [ (final: prev: { unstable = import inputs.nixpkgs-unstable { - inherit (prev) system; - inherit (prev) config; + system = final.stdenv.hostPlatform.system; + config = final.config; }; }) + inputs.antigravity.overlays.default + inputs.comfy-ui.overlays.default ]; } diff --git a/modules/core/users.nix b/modules/core/users.nix index fa23e7e..d466a13 100644 --- a/modules/core/users.nix +++ b/modules/core/users.nix @@ -1,30 +1,30 @@ -{ pkgs, ... }: +{ config, pkgs, ... }: { - users.defaultUserShell = pkgs.zsh; - programs.zsh = { - enable = true; - loginShellInit = '' - if [ -z "$DISPLAY" ] && [ "$TTY" = "/dev/tty1" ]; then - exec start-hyprland - fi - ''; - }; + users.defaultUserShell = pkgs.zsh; + programs.zsh.enable = true; - users.users.anish = { - isNormalUser = true; - description = "Main Account"; - extraGroups = [ "wheel" "networkmanager" "video" "audio" "gaming" "llm" ]; - openssh.authorizedKeys.keys = [ - # ssh-ed25519 AAAAA.... add my key here to enable ssh from another computer - ]; - }; - - services.openssh = { - enable = true; - settings = { - PasswordAuthentication = false; - PermitRootLogin = "no"; - }; + users.users.${config.my.username} = { + isNormalUser = true; + description = "Main Account"; + extraGroups = [ + "wheel" + "networkmanager" + "video" + "audio" + "gaming" + "llm" + ]; + openssh.authorizedKeys.keys = [ + # ssh-ed25519 AAAAA.... add my key here to enable ssh from another computer + ]; + }; + + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "no"; }; + }; } diff --git a/modules/graphical/default.nix b/modules/graphical/default.nix index 2b398e6..3fa1daf 100644 --- a/modules/graphical/default.nix +++ b/modules/graphical/default.nix @@ -1,41 +1,58 @@ -{ pkgs, lib, ... }: +{ + config, + pkgs, + lib, + ... +}: { - programs.hyprland = { - enable = true; - xwayland.enable = true; - }; + programs.hyprland = { + enable = true; + xwayland.enable = true; + }; - services.getty.autologinUser = "anish"; + services.getty.autologinUser = config.my.username; - # Boot straight into Hyprland from the first virtual console on any machine. - # No display manager required; tty2-6 remain available as plain shells. - environment.loginShellInit = '' - if [ "$(tty)" = "/dev/tty1" ]; then - exec ${pkgs.hyprland}/bin/Hyprland - fi - ''; + # Boot straight into Hyprland from the first virtual console on any machine. + # No display manager required; tty2-6 remain available as plain shells. + # The start-hyprland wrapper ships with programs.hyprland and sets up the + # session environment correctly. + environment.loginShellInit = '' + if [ "$(tty)" = "/dev/tty1" ]; then + exec start-hyprland + fi + ''; - # Machine-agnostic Wayland session variables. - # GPU/vendor specific variables live with their hardware module (e.g. modules/hardware/nvidia.nix). - environment.sessionVariables = { - NIXOS_OZONE_WL = "1"; - HYPRCURSOR_ENABLED = "1"; - MOZ_ENABLE_WAYLAND = "1"; - QT_QPA_PLATFORM = "wayland;xcb"; - QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; - CLUTTER_BACKEND = "wayland"; - GDK_BACKEND = "wayland,x11,*"; - }; + # Vendor-neutral graphics stack. Vendor modules (e.g. modules/hardware/nvidia.nix) + # only add drivers and vendor-specific environment variables. + hardware.graphics = { + enable = true; + enable32Bit = true; + }; - # Fonts used across the desktop shell (Silicon Volt theme): - # JetBrains Mono for terminal/UI mono, IBM Plex Sans for UI sans, - # Instrument Serif for display italics, Nanum Gothic Coding as mono fallback. - fonts.packages = with pkgs; [ - nerd-fonts.jetbrains-mono - nerd-fonts.fira-code - font-awesome - ibm-plex - nanum-gothic-coding - ] ++ lib.optional (lib.hasAttr "instrument-serif" pkgs) pkgs.instrument-serif; + # Machine-agnostic Wayland session variables. + # GPU/vendor specific variables live with their hardware module (e.g. modules/hardware/nvidia.nix). + environment.sessionVariables = { + NIXOS_OZONE_WL = "1"; + HYPRCURSOR_ENABLED = "1"; + MOZ_ENABLE_WAYLAND = "1"; + QT_QPA_PLATFORM = "wayland;xcb"; + QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; + CLUTTER_BACKEND = "wayland"; + GDK_BACKEND = "wayland,x11,*"; + }; + + # Fonts used across the desktop shell (Silicon Volt theme): + # JetBrains Mono for terminal/UI mono, IBM Plex Sans for UI sans, + # Instrument Serif for display italics, Nanum Gothic Coding as mono fallback. + fonts.packages = + with pkgs; + [ + nerd-fonts.jetbrains-mono + nerd-fonts.fira-code + font-awesome + ibm-plex + nanum-gothic-coding + ] + ++ lib.optional (lib.hasAttr "instrument-serif" pkgs) pkgs.instrument-serif; } diff --git a/modules/hardware/nvidia.nix b/modules/hardware/nvidia.nix index b5cd275..ddcc4ec 100644 --- a/modules/hardware/nvidia.nix +++ b/modules/hardware/nvidia.nix @@ -1,34 +1,39 @@ -{ config, pkgs, lib, ... }: +{ + config, + pkgs, + lib, + ... +}: { - hardware.graphics = { - enable = true; - enable32Bit = true; - }; + services.xserver.videoDrivers = [ "nvidia" ]; - services.xserver.videoDrivers = [ "nvidia" ]; + boot.initrd.kernelModules = [ + "nvidia" + "nvidia_modeset" + "nvidia_uvm" + "nvidia_drm" + ]; + boot.kernelParams = [ + "nvidia-drm.modeset=1" + "nvidia-drm.fbdev=1" + ]; - boot.initrd.kernelModules = [ "nvidia" "nvidia_modeset" "nvidia_uvm" "nvidia_drm" ]; - boot.kernelParams = [ - "nvidia-drm.modeset=1" - "nvidia-drm.fbdev=1" - ]; - - hardware.nvidia = { - modesetting.enable = true; - powerManagement.enable = true; - powerManagement.finegrained = lib.mkDefault false; - open = lib.mkDefault true; - nvidiaSettings = true; - package = config.boot.kernelPackages.nvidiaPackages.stable; - }; + hardware.nvidia = { + modesetting.enable = true; + powerManagement.enable = true; + powerManagement.finegrained = lib.mkDefault false; + open = lib.mkDefault true; + nvidiaSettings = true; + package = config.boot.kernelPackages.nvidiaPackages.stable; + }; - # NVIDIA-specific session variables live here so machines without - # NVIDIA GPUs (which do not import this module) stay vendor-clean. - environment.sessionVariables = { - LIBVA_DRIVER_NAME = "nvidia"; - GBM_BACKEND = "nvidia-drm"; - __GLX_VENDOR_LIBRARY_NAME = "nvidia"; - NVD_BACKEND = "direct"; - }; + # NVIDIA-specific session variables live here so machines without + # NVIDIA GPUs (which do not import this module) stay vendor-clean. + environment.sessionVariables = { + LIBVA_DRIVER_NAME = "nvidia"; + GBM_BACKEND = "nvidia-drm"; + __GLX_VENDOR_LIBRARY_NAME = "nvidia"; + NVD_BACKEND = "direct"; + }; } diff --git a/modules/options.nix b/modules/options.nix new file mode 100644 index 0000000..1a1e6c9 --- /dev/null +++ b/modules/options.nix @@ -0,0 +1,20 @@ +{ + lib, + ... +}: + +{ + # Shared, machine-agnostic configuration surface. Hosts enable optional + # feature modules by setting these booleans instead of editing import lists. + options.my = { + username = lib.mkOption { + type = lib.types.str; + default = "anish"; + description = "Primary interactive user account."; + }; + + gaming.enable = lib.mkEnableOption "Steam, Gamemode and gaming tooling"; + + ai.local.enable = lib.mkEnableOption "local AI services (Ollama, ComfyUI, Open WebUI)"; + }; +}