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
This commit is contained in:
2026-09-18 23:32:32 -07:00
parent 367e21ef95
commit 598a43eace
30 changed files with 1093 additions and 768 deletions

9
.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# Nix build results
result
result-*
# home-manager backup files (backupFileExtension = "backup")
*.backup
# direnv
.direnv/

View File

@@ -24,10 +24,22 @@ rebuild switch # zsh helper: sudo nixos-rebuild switch --flake ~/NixOS-Configs
## Adding a new host (e.g. a laptop) ## Adding a new host (e.g. a laptop)
1. Create `hosts/<name>/` with `default.nix`, `hardware-configuration.nix`, and 1. Create `hosts/<name>/` with `default.nix`, `hardware-configuration.nix`, and
(optionally) `disko.nix`; import the shared modules (`modules/core`, (optionally) `disko.nix`. Shared modules (`modules/core`, `modules/graphical`,
`modules/graphical`, `modules/apps`). `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`. 2. Register it in `flake.nix` under `nixosConfigurations`.
3. Declare host-specific displays in `hosts/<name>/default.nix`: 3. Turn optional features on per machine via the shared `my.*` options:
```nix
# hosts/<name>/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/<name>/default.nix`:
```nix ```nix
home-manager.users.anish.volt.monitors = [ 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 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 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`).

67
flake.lock generated
View File

@@ -51,7 +51,9 @@
"comfy-ui": { "comfy-ui": {
"inputs": { "inputs": {
"flake-parts": "flake-parts", "flake-parts": "flake-parts",
"nixpkgs": "nixpkgs" "nixpkgs": [
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1787851822, "lastModified": 1787851822,
@@ -186,7 +188,9 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_2" "nixpkgs": [
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1788044418, "lastModified": 1788044418,
@@ -205,16 +209,16 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1766902085, "lastModified": 1787962033,
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=", "narHash": "sha256-u6z9VTZA4Kf3RkHQo9sQI7NI4Ei/uiU9vrMqOiwWP1Y=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4", "rev": "c5c4a43b0e8056328ec4529f735cabdb8f1942bb",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-unstable", "ref": "nixos-26.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@@ -250,56 +254,13 @@
"type": "github" "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": { "pi": {
"inputs": { "inputs": {
"bun2nix": "bun2nix", "bun2nix": "bun2nix",
"jail-nix": "jail-nix", "jail-nix": "jail-nix",
"nixpkgs": "nixpkgs_4", "nixpkgs": [
"nixpkgs"
],
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
@@ -324,7 +285,7 @@
"herdr": "herdr", "herdr": "herdr",
"home-manager": "home-manager", "home-manager": "home-manager",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_3", "nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable", "nixpkgs-unstable": "nixpkgs-unstable",
"pi": "pi" "pi": "pi"
} }

View File

@@ -4,7 +4,10 @@
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; 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 = { home-manager = {
url = "github:nix-community/home-manager/release-26.05"; url = "github:nix-community/home-manager/release-26.05";
@@ -23,9 +26,9 @@
comfy-ui = { comfy-ui = {
url = "github:utensils/comfyui-nix"; url = "github:utensils/comfyui-nix";
inputs.nixpkgs.follows = "nixpkgs";
}; };
herdr = { herdr = {
url = "github:herdrdev/herdr"; url = "github:herdrdev/herdr";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@@ -33,6 +36,7 @@
pi = { pi = {
url = "github:lukasl-dev/pi.nix"; url = "github:lukasl-dev/pi.nix";
inputs.nixpkgs.follows = "nixpkgs";
}; };
}; };
@@ -46,26 +50,18 @@
./modules/graphical ./modules/graphical
./modules/apps ./modules/apps
inputs.home-manager.nixosModules.home-manager inputs.home-manager.nixosModules.home-manager
{ (
nixpkgs.overlays = [ { config, ... }:
(final: prev: { {
unstable = import inputs.nixpkgs-unstable { home-manager = {
inherit (final) system; useGlobalPkgs = true;
config.allowUnfree = true; useUserPackages = true;
}; extraSpecialArgs = { inherit inputs; };
}) backupFileExtension = "backup";
inputs.antigravity.overlays.default users.${config.my.username} = import ./home;
inputs.comfy-ui.overlays.default };
]; }
)
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = { inherit inputs; };
backupFileExtension = "backup";
users.anish = import ./home;
};
}
]; ];
in in
{ {
@@ -80,6 +76,8 @@
}; };
}; };
formatter.${system} = inputs.nixpkgs.legacyPackages.${system}.nixfmt;
devShells.${system}.default = devShells.${system}.default =
let let
pkgs = import inputs.nixpkgs { pkgs = import inputs.nixpkgs {

View File

@@ -29,25 +29,26 @@ let
}; };
in in
{ {
programs.chromium = { programs.chromium = {
enable = true; enable = true;
package = pkgs.brave; package = pkgs.brave;
commandLineArgs = [ commandLineArgs = [
"--enable-features=UseOzonePlatform" "--enable-features=UseOzonePlatform"
"--ozone-platform=wayland" "--ozone-platform=wayland"
"--enable-wayland-ime" "--enable-wayland-ime"
"--ignore-gpu-blocklist" "--ignore-gpu-blocklist"
"--enable-gpu-rasterization" "--enable-gpu-rasterization"
"--enable-zero-copy" "--enable-zero-copy"
]; ];
extensions = [ extensions = [
{ id = "nngceckbapebfimnlniiiahkandclblb"; } # Bitwarden { id = "nngceckbapebfimnlniiiahkandclblb"; } # Bitwarden
{ id = "hfjbmagddngcpeloejdejnfgbamkjaeg"; } # Vimium C { id = "hfjbmagddngcpeloejdejnfgbamkjaeg"; } # Vimium C
]; ];
}; };
xdg.configFile."brave/policies/managed/policies.json".text = builtins.toJSON bravePolicies; 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."BraveSoftware/Brave-Browser/policies/managed/policies.json".text =
xdg.configFile."chromium/policies/managed/policies.json".text = builtins.toJSON bravePolicies; builtins.toJSON bravePolicies;
xdg.configFile."chromium/policies/managed/policies.json".text = builtins.toJSON bravePolicies;
} }

View File

@@ -1,14 +1,22 @@
{ pkgs, inputs, ... }: { pkgs, inputs, ... }:
let let
herdrPkg = if (inputs ? herdr && inputs.herdr ? packages && inputs.herdr.packages ? ${pkgs.stdenv.hostPlatform.system}) herdrPkg =
then inputs.herdr.packages.${pkgs.stdenv.hostPlatform.system}.default if
else (pkgs.herdr or null); (
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); herdrPicker = pkgs.writeShellScriptBin "herdr-picker" (builtins.readFile ./scripts/herdr-picker.sh);
in in
{ {
home.packages = (if herdrPkg != null then [ herdrPkg ] else []) ++ [ home.packages = (if herdrPkg != null then [ herdrPkg ] else [ ]) ++ [
herdrPicker herdrPicker
]; ];
@@ -51,24 +59,24 @@ in
# Cursor text and cursor (background) colors # Cursor text and cursor (background) colors
cursor = "0e0e0e cffc00"; cursor = "0e0e0e cffc00";
regular0 = "0e0e0e"; # bgSecondary regular0 = "0e0e0e"; # bgSecondary
regular1 = "ff7a59"; # accentCoral regular1 = "ff7a59"; # accentCoral
regular2 = "cffc00"; # accentVolt (green) regular2 = "cffc00"; # accentVolt (green)
regular3 = "e3ff66"; # accentVoltLight (yellow) regular3 = "e3ff66"; # accentVoltLight (yellow)
regular4 = "00bfff"; # accentBlue regular4 = "00bfff"; # accentBlue
regular5 = "c6c6c7"; # Neutral Gray (magenta) regular5 = "c6c6c7"; # Neutral Gray (magenta)
regular6 = "66d9ff"; # Light Cyan regular6 = "66d9ff"; # Light Cyan
regular7 = "e5e2e1"; # textSecondary regular7 = "e5e2e1"; # textSecondary
# Bright Colors # Bright Colors
bright0 = "2a2929"; # surfaceVariant bright0 = "2a2929"; # surfaceVariant
bright1 = "ff9a82"; # Bright Coral bright1 = "ff9a82"; # Bright Coral
bright2 = "dfff66"; # Bright Lime bright2 = "dfff66"; # Bright Lime
bright3 = "f0ff8c"; # Bright Volt bright3 = "f0ff8c"; # Bright Volt
bright4 = "66d9ff"; # Bright Blue bright4 = "66d9ff"; # Bright Blue
bright5 = "e0e0e1"; # Bright Gray bright5 = "e0e0e1"; # Bright Gray
bright6 = "99e6ff"; # Bright Cyan bright6 = "99e6ff"; # Bright Cyan
bright7 = "ffffff"; # textPrimary bright7 = "ffffff"; # textPrimary
# Selection & URLs - volt lime selection like the site # Selection & URLs - volt lime selection like the site
selection-foreground = "0e0e0e"; selection-foreground = "0e0e0e";

View File

@@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
let let
# Deterministic Silicon Volt wallpaper: rendered from SVG at build time, # Deterministic Silicon Volt wallpaper: rendered from SVG at build time,
@@ -8,65 +13,65 @@ let
''; '';
in in
{ {
imports = [ imports = [
./hyprland.nix ./hyprland.nix
./hyprlock.nix ./hyprlock.nix
./hypridle.nix ./hypridle.nix
./quickshell.nix ./quickshell.nix
]; ];
home.packages = with pkgs; [ home.packages = with pkgs; [
# Utilities & Tools # Utilities & Tools
grim grim
slurp slurp
wl-clipboard wl-clipboard
cliphist cliphist
brightnessctl brightnessctl
jq jq
# Desktop Environment / Hyprland ecosystem # Desktop Environment / Hyprland ecosystem
hyprpaper hyprpaper
hyprpolkitagent hyprpolkitagent
]; ];
# Build-time rendered wallpaper # Build-time rendered wallpaper
xdg.dataFile."backgrounds/silicon-volt.png".source = wallpaper; xdg.dataFile."backgrounds/silicon-volt.png".source = wallpaper;
# hyprpaper: load the Silicon Volt wallpaper on every output # hyprpaper: load the Silicon Volt wallpaper on every output
xdg.configFile."hypr/hyprpaper.conf".text = '' xdg.configFile."hypr/hyprpaper.conf".text = ''
preload = ${config.home.homeDirectory}/.local/share/backgrounds/silicon-volt.png preload = ${config.home.homeDirectory}/.local/share/backgrounds/silicon-volt.png
wallpaper = ,${config.home.homeDirectory}/.local/share/backgrounds/silicon-volt.png wallpaper = ,${config.home.homeDirectory}/.local/share/backgrounds/silicon-volt.png
splash = false splash = false
''; '';
# Notifications: flat brutalist-glass cards with volt accents # Notifications: flat brutalist-glass cards with volt accents
services.mako = { services.mako = {
enable = true; enable = true;
settings = { settings = {
background-color = "#1c1b1bee"; background-color = "#1c1b1bee";
text-color = "#e5e2e1"; text-color = "#e5e2e1";
border-color = "#cffc00"; border-color = "#cffc00";
border-size = 1; border-size = 1;
border-radius = 0; border-radius = 0;
width = 420; width = 420;
margin = "12"; margin = "12";
padding = "14"; padding = "14";
default-timeout = 6000; default-timeout = 6000;
font = "JetBrainsMono Nerd Font 11"; font = "JetBrainsMono Nerd Font 11";
format = "<b>%s</b>\\n%b"; format = "<b>%s</b>\\n%b";
"icon-location" = "left"; "icon-location" = "left";
max-icon-size = 48; max-icon-size = 48;
"urgency=critical" = { "urgency=critical" = {
border-color = "#ff7a59"; border-color = "#ff7a59";
text-color = "#ffffff"; text-color = "#ffffff";
default-timeout = 0; default-timeout = 0;
}; };
"urgency=low" = { "urgency=low" = {
border-color = "#2a2929"; border-color = "#2a2929";
text-color = "#adaaaa"; text-color = "#adaaaa";
}; };
};
}; };
};
} }

View File

@@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }: {
pkgs,
lib,
config,
...
}:
let let
mkLua = lib.generators.mkLuaInline; mkLua = lib.generators.mkLuaInline;
@@ -8,395 +13,621 @@ in
# Per-host monitor configuration. # Per-host monitor configuration.
# #
# Hosts declare their displays once, in hosts/<host>/default.nix, via: # Hosts declare their displays once, in hosts/<host>/default.nix, via:
# home-manager.users.anish.volt.monitors = [ { ... } ]; # home-manager.users.<my.username>.volt.monitors = [ { ... } ];
# and the setting flows into Hyprland here. The default (empty output + # and the setting flows into Hyprland here. The default (empty output +
# preferred mode) works on any machine with any display. # preferred mode) works on any machine with any display.
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
options.volt.monitors = lib.mkOption { options.volt.monitors = lib.mkOption {
description = "Hyprland monitor rules for this host"; description = "Hyprland monitor rules for this host";
type = lib.types.listOf (lib.types.submodule { type = lib.types.listOf (
options = { lib.types.submodule {
output = lib.mkOption { options = {
type = lib.types.str; output = lib.mkOption {
default = ""; type = lib.types.str;
description = "Output name or desc: match. Empty string matches every output."; 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 = [ default = [
{ output = ""; mode = "preferred"; position = "auto"; scale = "auto"; } {
output = "";
mode = "preferred";
position = "auto";
scale = "auto";
}
]; ];
}; };
config = { config = {
wayland.windowManager.hyprland.settings.monitor = map (m: wayland.windowManager.hyprland.settings.monitor = map (
{ inherit (m) output mode position scale; } m:
{
inherit (m)
output
mode
position
scale
;
}
// (lib.optionalAttrs (m.vrr != null) { inherit (m) vrr; }) // (lib.optionalAttrs (m.vrr != null) { inherit (m) vrr; })
) config.volt.monitors; ) config.volt.monitors;
wayland.windowManager.hyprland = { wayland.windowManager.hyprland = {
enable = true; enable = true;
configType = "lua"; configType = "lua";
package = null; # Hyprland package is managed system-wide via NixOS programs.hyprland package = null; # Hyprland package is managed system-wide via NixOS programs.hyprland
settings = { settings = {
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# 1. Variables & Modifiers (Rendered as Lua local variables) # 1. Variables & Modifiers (Rendered as Lua local variables)
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
mainMod = { _var = "SUPER"; }; mainMod = {
terminal = { _var = "foot"; }; _var = "SUPER";
browser = { _var = "brave"; }; };
terminal = {
# ----------------------------------------------------------------------- _var = "foot";
# 2. Monitors (hl.monitor) - declared per-host via volt.monitors };
# (see hosts/<host>/default.nix); defaults to any display @ preferred. browser = {
# ----------------------------------------------------------------------- _var = "brave";
# -----------------------------------------------------------------------
# 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;
};
}; };
cursor = { # -----------------------------------------------------------------------
inactive_timeout = 3; # 2. Monitors (hl.monitor) - declared per-host via volt.monitors
# Hardware cursors ON (explicit). Note: this replaces the old # (see hosts/<host>/default.nix); defaults to any display @ preferred.
# WLR_NO_HARDWARE_CURSORS=1, which forced software rendering. # -----------------------------------------------------------------------
no_hardware_cursors = false;
};
general = { # -----------------------------------------------------------------------
gaps_in = 5; # 3. Environment Variables (hl.env)
gaps_out = 10; # -----------------------------------------------------------------------
border_size = 2; env = [
col = { {
# Silicon Volt: electric lime gradient on focus, glass gray at rest _args = [
active_border = { "XCURSOR_SIZE"
colors = [ "rgba(cffc00ee)" "rgba(e3ff66ee)" ]; "24"
angle = 45; ];
}
{
_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 = { cursor = {
groupbar = { inactive_timeout = 3;
font_size = 14; # Hardware cursors ON (explicit). Note: this replaces the old
font_family = "JetBrainsMono Nerd Font"; # WLR_NO_HARDWARE_CURSORS=1, which forced software rendering.
no_hardware_cursors = false;
};
general = {
gaps_in = 5;
gaps_out = 10;
border_size = 2;
col = { col = {
active = "rgba(cffc0022)"; # Silicon Volt: electric lime gradient on focus, glass gray at rest
inactive = "rgba(ffffff08)"; 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 = { misc = {
border_active = { disable_hyprland_logo = true;
colors = [ "rgba(cffc00ee)" "rgba(e3ff66ee)" ]; disable_splash_rendering = true;
angle = 45; };
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 = { animations = {
disable_hyprland_logo = true;
disable_splash_rendering = true;
};
decoration = {
rounding = 4;
# Subtle glass blur to match the brutalist-glass aesthetic
blur = {
enabled = true; 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; enabled = true;
range = 12; speed = 7;
render_power = 3; bezier = "myBezier";
color = "rgba(00000066)"; }
}; {
}; 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 = { # Move focus with mainMod + vim
new_status = "master"; {
}; _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;
}
];
};
}; };
}; };
} }

View File

@@ -1,9 +1,17 @@
{ pkgs, inputs, ... }: { pkgs, inputs, ... }:
let let
quickshellPkg = if (inputs ? quickshell && inputs.quickshell ? packages && inputs.quickshell.packages ? ${pkgs.stdenv.hostPlatform.system}) quickshellPkg =
then inputs.quickshell.packages.${pkgs.stdenv.hostPlatform.system}.default if
else (pkgs.quickshell or pkgs.qt6.qtbase); (
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 in
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [

View File

@@ -1,76 +1,83 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
let let
treesitterParsers = pkgs.symlinkJoin { treesitterParsers = pkgs.symlinkJoin {
name = "treesitter-parsers"; name = "treesitter-parsers";
paths = builtins.attrValues pkgs.vimPlugins.nvim-treesitter.passthru.grammarPlugins; paths = builtins.attrValues pkgs.vimPlugins.nvim-treesitter.passthru.grammarPlugins;
}; };
in in
{ {
programs.neovim = { programs.neovim = {
enable = true; enable = true;
defaultEditor = true; defaultEditor = true;
viAlias = true; viAlias = true;
vimAlias = true; vimAlias = true;
withNodeJs = true; withNodeJs = true;
withPython3 = true; withPython3 = true;
extraPackages = with pkgs; [ extraPackages = with pkgs; [
# Native compilation tools & Treesitter CLI # Native compilation tools & Treesitter CLI
gcc gcc
clang clang
gnumake gnumake
cmake cmake
tree-sitter tree-sitter
# Search & Fuzzy Finding # Search & Fuzzy Finding
ripgrep ripgrep
fd fd
fzf fzf
# Archive and Network Utilities # Archive and Network Utilities
git git
curl curl
unzip unzip
gnutar gnutar
gzip gzip
# Language Servers, Linters & Formatters (Declarative, no Mason needed) # Language Servers, Linters & Formatters (Declarative, no Mason needed)
# Nix # Nix
nil nil
nixfmt nixfmt
statix statix
# Lua # Lua
lua-language-server lua-language-server
stylua stylua
# C / C++ # C / C++
llvmPackages_latest.clang-tools llvmPackages_latest.clang-tools
llvmPackages_latest.lldb llvmPackages_latest.lldb
# Rust # Rust
rust-analyzer rust-analyzer
# Python # Python
pyright pyright
ruff ruff
# Web / TypeScript / JavaScript / HTML / CSS / JSON # Web / TypeScript / JavaScript / HTML / CSS / JSON
vtsls vtsls
vscode-langservers-extracted vscode-langservers-extracted
prettier prettier
# Shell # Shell
shfmt shfmt
shellcheck shellcheck
]; ];
extraWrapperArgs = [ extraWrapperArgs = [
"--set" "NVIM_TREESITTER_PARSERS" "${treesitterParsers}" "--set"
]; "NVIM_TREESITTER_PARSERS"
}; "${treesitterParsers}"
];
};
# Symlink LazyVim configuration to ~/.config/nvim recursively # Symlink LazyVim configuration to ~/.config/nvim recursively
xdg.configFile."nvim" = { xdg.configFile."nvim" = {
source = ./config; source = ./config;
recursive = true; recursive = true;
}; };
# Symlink precompiled Treesitter parsers directly into ~/.config/nvim/parser # Symlink precompiled Treesitter parsers directly into ~/.config/nvim/parser
xdg.configFile."nvim/parser".source = "${treesitterParsers}/parser"; xdg.configFile."nvim/parser".source = "${treesitterParsers}/parser";
} }

View File

@@ -3,8 +3,7 @@
let let
# Rofi script-mode indexer: exposes every executable user script # Rofi script-mode indexer: exposes every executable user script
# (shell, python, whatever) so the launcher finds "everything". # (shell, python, whatever) so the launcher finds "everything".
rofiScripts = pkgs.writeShellScriptBin "rofi-scripts" rofiScripts = pkgs.writeShellScriptBin "rofi-scripts" (builtins.readFile ./rofi/rofi-scripts.sh);
(builtins.readFile ./rofi/rofi-scripts.sh);
in in
{ {
programs.rofi = { programs.rofi = {

View File

@@ -47,7 +47,7 @@ rebuild () {
shift 2>/dev/null || true shift 2>/dev/null || true
local config_dir="${FLAKE_CONFIG:-$HOME/NixOS-Configs}" local config_dir="${FLAKE_CONFIG:-$HOME/NixOS-Configs}"
local host="hades" local host="${REBUILD_HOST:-$(hostname)}"
local target="$config_dir#$host" local target="$config_dir#$host"
case "$action" in case "$action" in

View File

@@ -11,18 +11,21 @@
inputs.disko.nixosModules.disko inputs.disko.nixosModules.disko
./disko.nix ./disko.nix
./hardware-configuration.nix ./hardware-configuration.nix
./display-configuration.nix
../../modules/hardware/nvidia.nix ../../modules/hardware/nvidia.nix
../../modules/apps/gaming.nix
../../modules/apps/local_ai.nix
]; ];
networking.hostName = "hades"; 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) # 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 # Samsung Odyssey Ark - matched by description so it survives port changes
output = "desc:Samsung Electric Company Odyssey Ark H1AK500000"; output = "desc:Samsung Electric Company Odyssey Ark H1AK500000";
@@ -44,7 +47,7 @@
# Ensure /games directory is accessible by default user # Ensure /games directory is accessible by default user
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d /games 0755 anish users -" "d /games 0755 ${config.my.username} users -"
]; ];
powerManagement.cpuFreqGovernor = "performance"; powerManagement.cpuFreqGovernor = "performance";
@@ -58,7 +61,6 @@
}; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
mangohud
nvtopPackages.nvidia nvtopPackages.nvidia
]; ];
} }

View File

@@ -14,7 +14,10 @@
type = "filesystem"; type = "filesystem";
format = "vfat"; format = "vfat";
mountpoint = "/boot"; mountpoint = "/boot";
mountOptions = [ "fmask=0077" "dmask=0077" ]; mountOptions = [
"fmask=0077"
"dmask=0077"
];
}; };
}; };
root = { root = {

View File

@@ -1,5 +0,0 @@
{ ... }:
{
# Host-specific display configurations can be placed here if needed.
}

View File

@@ -1,14 +1,27 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’ # Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = [ 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.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ]; boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];

View File

@@ -1,5 +0,0 @@
{ ... }:
{
# Browser is configured and managed via Home Manager (home/brave.nix)
}

View File

@@ -1,8 +1,8 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
vesktop vesktop
signal-desktop signal-desktop
]; ];
} }

View File

@@ -3,9 +3,10 @@
{ {
imports = [ imports = [
./terminal.nix ./terminal.nix
./browser.nix
./communication.nix ./communication.nix
./dev.nix ./dev.nix
./virt.nix ./virt.nix
./gaming.nix
./local-ai.nix
]; ];
} }

View File

@@ -1,15 +1,22 @@
{ pkgs, ... }: {
config,
lib,
pkgs,
...
}:
{ {
config = lib.mkIf config.my.gaming.enable {
programs.steam = { programs.steam = {
enable = true; enable = true;
remotePlay.openFirewall = false; remotePlay.openFirewall = false;
dedicatedServer.openFirewall = false; dedicatedServer.openFirewall = false;
gamescopeSession.enable = false; gamescopeSession.enable = false;
}; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
mangohud mangohud
gamemode gamemode
]; ];
};
} }

45
modules/apps/local-ai.nix Normal file
View File

@@ -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
];
};
}

View File

@@ -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
];
}

View File

@@ -1,9 +1,9 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
# Terminal is managed elsewhere; system-level CLI helpers live here. # Terminal is managed elsewhere; system-level CLI helpers live here.
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
zoxide zoxide
fzf fzf
]; ];
} }

View File

@@ -1,4 +1,4 @@
{ pkgs, ... }: { config, pkgs, ... }:
{ {
virtualisation = { virtualisation = {
@@ -27,7 +27,7 @@
programs.virt-manager.enable = true; programs.virt-manager.enable = true;
users.users.anish.extraGroups = [ users.users.${config.my.username}.extraGroups = [
"libvirtd" "libvirtd"
"kvm" "kvm"
"incus-admin" "incus-admin"

View File

@@ -1,9 +1,10 @@
{ ... }: { ... }:
{ {
imports = [ imports = [
./system.nix ../options.nix
./users.nix ./system.nix
./nix.nix ./users.nix
]; ./nix.nix
];
} }

View File

@@ -36,12 +36,16 @@
nixpkgs.config.allowUnfree = true; 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 = [ nixpkgs.overlays = [
(final: prev: { (final: prev: {
unstable = import inputs.nixpkgs-unstable { unstable = import inputs.nixpkgs-unstable {
inherit (prev) system; system = final.stdenv.hostPlatform.system;
inherit (prev) config; config = final.config;
}; };
}) })
inputs.antigravity.overlays.default
inputs.comfy-ui.overlays.default
]; ];
} }

View File

@@ -1,30 +1,30 @@
{ pkgs, ... }: { config, pkgs, ... }:
{ {
users.defaultUserShell = pkgs.zsh; users.defaultUserShell = pkgs.zsh;
programs.zsh = { programs.zsh.enable = true;
enable = true;
loginShellInit = ''
if [ -z "$DISPLAY" ] && [ "$TTY" = "/dev/tty1" ]; then
exec start-hyprland
fi
'';
};
users.users.anish = { users.users.${config.my.username} = {
isNormalUser = true; isNormalUser = true;
description = "Main Account"; description = "Main Account";
extraGroups = [ "wheel" "networkmanager" "video" "audio" "gaming" "llm" ]; extraGroups = [
openssh.authorizedKeys.keys = [ "wheel"
# ssh-ed25519 AAAAA.... add my key here to enable ssh from another computer "networkmanager"
]; "video"
}; "audio"
"gaming"
"llm"
];
openssh.authorizedKeys.keys = [
# ssh-ed25519 AAAAA.... add my key here to enable ssh from another computer
];
};
services.openssh = { services.openssh = {
enable = true; enable = true;
settings = { settings = {
PasswordAuthentication = false; PasswordAuthentication = false;
PermitRootLogin = "no"; PermitRootLogin = "no";
};
}; };
};
} }

View File

@@ -1,41 +1,58 @@
{ pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
{ {
programs.hyprland = { programs.hyprland = {
enable = true; enable = true;
xwayland.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. # Boot straight into Hyprland from the first virtual console on any machine.
# No display manager required; tty2-6 remain available as plain shells. # No display manager required; tty2-6 remain available as plain shells.
environment.loginShellInit = '' # The start-hyprland wrapper ships with programs.hyprland and sets up the
if [ "$(tty)" = "/dev/tty1" ]; then # session environment correctly.
exec ${pkgs.hyprland}/bin/Hyprland environment.loginShellInit = ''
fi if [ "$(tty)" = "/dev/tty1" ]; then
''; exec start-hyprland
fi
'';
# Machine-agnostic Wayland session variables. # Vendor-neutral graphics stack. Vendor modules (e.g. modules/hardware/nvidia.nix)
# GPU/vendor specific variables live with their hardware module (e.g. modules/hardware/nvidia.nix). # only add drivers and vendor-specific environment variables.
environment.sessionVariables = { hardware.graphics = {
NIXOS_OZONE_WL = "1"; enable = true;
HYPRCURSOR_ENABLED = "1"; enable32Bit = true;
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): # Machine-agnostic Wayland session variables.
# JetBrains Mono for terminal/UI mono, IBM Plex Sans for UI sans, # GPU/vendor specific variables live with their hardware module (e.g. modules/hardware/nvidia.nix).
# Instrument Serif for display italics, Nanum Gothic Coding as mono fallback. environment.sessionVariables = {
fonts.packages = with pkgs; [ NIXOS_OZONE_WL = "1";
nerd-fonts.jetbrains-mono HYPRCURSOR_ENABLED = "1";
nerd-fonts.fira-code MOZ_ENABLE_WAYLAND = "1";
font-awesome QT_QPA_PLATFORM = "wayland;xcb";
ibm-plex QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
nanum-gothic-coding CLUTTER_BACKEND = "wayland";
] ++ lib.optional (lib.hasAttr "instrument-serif" pkgs) pkgs.instrument-serif; 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;
} }

View File

@@ -1,34 +1,39 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
{ {
hardware.graphics = { services.xserver.videoDrivers = [ "nvidia" ];
enable = true;
enable32Bit = true;
};
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" ]; hardware.nvidia = {
boot.kernelParams = [ modesetting.enable = true;
"nvidia-drm.modeset=1" powerManagement.enable = true;
"nvidia-drm.fbdev=1" powerManagement.finegrained = lib.mkDefault false;
]; open = lib.mkDefault true;
nvidiaSettings = true;
package = config.boot.kernelPackages.nvidiaPackages.stable;
};
hardware.nvidia = { # NVIDIA-specific session variables live here so machines without
modesetting.enable = true; # NVIDIA GPUs (which do not import this module) stay vendor-clean.
powerManagement.enable = true; environment.sessionVariables = {
powerManagement.finegrained = lib.mkDefault false; LIBVA_DRIVER_NAME = "nvidia";
open = lib.mkDefault true; GBM_BACKEND = "nvidia-drm";
nvidiaSettings = true; __GLX_VENDOR_LIBRARY_NAME = "nvidia";
package = config.boot.kernelPackages.nvidiaPackages.stable; 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";
};
} }

20
modules/options.nix Normal file
View File

@@ -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)";
};
}