As previous dual-boot cachyos user I wanted to switch to fully use linux in my daily life. Someone mentioned he started newly using nixos and well here we are. This rice is now built over a period of 5 months until I said it is good and bug free to use.
In the first few weeks, I managed to like break the system three times a day and I was told nixos is not breakable ... only via live usb the pc was fixable as I edited the hardware-configuration.nix file lol stupid beginner mistake right? And the refind/grub customization caused that too but totally worth it.
Tip
Live Showcase: View the interactive web showcase of this configuration at muddyblack.github.io/NixOS.
Widgets
Nixdatifier
AI API Usage
GitPulse
Tagesschau
Generate GIFs from the MP4s:
for f in assets/plymouth/*/; do name=$(basename $f); ffmpeg -i "$f$name.mp4" -vf "fps=15,scale=400:-1" "$f$name.gif"; done
| OS | NixOS 26.05 |
| Kernel | Linux Zen (nixpkgs) |
| WM | Hyprland · KDE Plasma 6 · COSMIC · GNOME (independently toggleable, any combo) |
| Shell | Zsh · Powerlevel10k |
| Terminal | Ghostty |
| Bar | Caelestia Shell |
| Widgets | Glassy System Monitor · AI Usage · Nixdatifier · GitPulse · Tagesschau · Plasma Audio Visualizer · Advanced Weather · Powerchart |
| Browser | Zen Browser |
| Editor | Neovim (LazyVim) · Antigravity · Zed |
| File Manager | Yazi · Dolphin |
| Theme | Sweet Dark · Kvantum |
| Icons | Papirus-Dark · Slot-Dark · Vivid-Dark |
| Cursor | Sweet Cursors |
| Login | SDDM · Sonomatic |
| Boot | Plymouth · custom MP4 themes |
| Disk | Btrfs · LUKS · Impermanence |
NixOS/
├── flake.nix
├── deploy.sh # Install & rebuild helper
├── docs/ # Showcase site + live USB recovery runbook
├── hosts/
│ ├── common.nix # Shared system config
│ ├── disko-config.nix # Disk layout (LUKS + Btrfs)
│ ├── muddyblack/ # Full desktop
│ └── muddyblack-lite/ # Lightweight (VM / testing)
├── modules/
│ ├── nixos/ # System-level modules & features
│ └── home-manager/ # User environment
├── pkgs/ # Custom packages & overlays
├── assets/ # Wallpapers, sounds, themes, icons
└── dev-shells/ # Language dev environment templates
Locked out of the system? See docs/RECOVERY.md.
No
hardware-configuration.nixin this repo — disks are partitioned at install time via Disko. You can install on a running system or from the NixOS minimal ISO.
Disk layout — the disko config works on any drive. deploy.sh will prompt you for your disk device (e.g. /dev/sda, /dev/nvme0n1) or you can pass --device to skip the prompt. Partition sizes for dual-boot (--win-size, --shared-size) are also configurable — see bash deploy.sh help for all flags.
Try in a VM first (from any machine with Nix)
nix build .#nixosConfigurations.muddyblack-lite.config.system.build.vm
./result/bin/run-muddyblack-lite-vmFresh install from a live ISO
sudo su
git clone https://github.com/Muddyblack/NixOS /mnt/NixOS
cd /mnt/NixOS
bash deploy.sh fresh # prompts for disk device
# or: bash deploy.sh fresh --device /dev/nvme0n1 --no-dual-bootRemote install via nixos-anywhere
git clone https://github.com/Muddyblack/NixOS
cd NixOS
bash deploy.sh fresh --remote root@<ip> --device /dev/sdaDay-to-day rebuild:
upnixPick your sessions: deploy.sh fresh/install asks which desktop sessions to enable
(Hyprland, KDE Plasma 6, COSMIC, GNOME — any combination) as part of the interactive setup, or
skip the prompt with --desktops hyprland,plasma,cosmic (comma-separated, no spaces). The answer
is written to hosts/deploy-config.nix — nothing is hardcoded per-fork, and nobody has to edit
Nix to leave GNOME off or run KDE-only.
bash deploy.sh fresh --desktops hyprland,cosmic # e.g. skip KDE and GNOME entirelyTo change your mind later, edit features.desktops.<name>.enable in hosts/deploy-config.nix
directly and rebuild — no need to re-run the installer. Each flag independently enables/disables
both the system session and its matching home-manager config (shortcuts, wallpaper, theme,
touchpad) — defaults live in modules/nixos/features/desktops.nix
(Hyprland/Plasma/COSMIC on, GNOME off) for anyone who calls nixos-rebuild directly instead of
through deploy.sh.
Pick your keyboard layout: deploy.sh fresh/install asks for it too — a short list
(de, us, gb, fr, es, it, ch) plus an other entry that takes any xkb layout name — or skip the
prompt with --keyboard us. Like the desktop flags it lands in hosts/deploy-config.nix
(keyboardLayout = "…";, default German), and from there one value feeds the console keymap,
xkb/greeter, Hyprland's kb_layout and Plasma's kxkbrc. Change it
later by editing that line and rebuilding — nothing else needs touching.
bash deploy.sh fresh --keyboard us --desktops hyprland,plasmaTwo caveats when you move off German. console.keyMap reuses the same string, so a layout whose
console keymap is spelled differently (xkb gb → console uk) needs console.keyMap set
explicitly in hosts/common.nix — the installer prints a note for that case. And the
Meta+Shift+<digit> window-move shortcuts have to be written as the character the layout
actually produces, so add your row to shiftedNumberRows in
modules/home-manager/plasma-settings.nix; unlisted
layouts fall back to the US row.
Powered by Zsh + Powerlevel10k, with modern CLI replacements throughout:
| Tool | Replaces | Notes |
|---|---|---|
zoxide |
cd |
Frecency-based directory jumping |
eza |
ls |
Icons, git info; auto-runs on cd |
yazi |
file manager | Terminal file browser |
fzf + fzf-tab |
tab completion | Fuzzy completions + history search |
ripgrep |
grep |
Aliased as grep |
fd |
find |
Aliased as find |
btop |
top |
Aliased as top |
gping |
ping |
Graphical, aliased as ping |
xh |
curl |
Aliased as curl |
Reconfigure the prompt:
p10k configureDevelopment environments & offline work:
direnv uses nix-direnv's manual reload mode.
Entering a project reuses its cached environment, even after flake.nix or
flake.lock changes. A warning tells you when the cache is stale. Downloads and
environment rebuilds wait until you explicitly run nix-direnv-reload.
devnew python # optional: initialise a project from a local template
direnv allow # approve an existing project's .envrc
nix-direnv-reload # first setup online, or apply changed shell definitionsWait for direnv to load after allowing the project so nix-direnv-reload becomes
available. Commit the project's flake.lock to pin dependency versions. Reloading
uses those pins; run update --flake "$PWD" from the project root only when you want newer inputs,
then nix-direnv-reload to build the updated environment. direnv reload alone
does not rebuild the Nix cache in manual mode.
After a successful setup, enter the same project normally while offline. Keep
its .direnv/ directory: it holds the cached environment and garbage collection
roots. clean, gcnix, and scheduled cleanup preserve direnv roots. To reclaim
an abandoned project's environment, remove that project's .direnv/ before
running cleanup. Store projects on persistent storage (such as /mnt/projects
or ~/Documents) so their caches survive a reboot.
This caches the Nix environment, not network activity in .envrc, shellHook,
or tools such as npm, pip, and Cargo. Prepare those dependencies online too.
An uncached project or a changed shell needing missing store paths still needs
an online setup; a stale cached shell keeps the previous tools until refreshed.
Generations & rollback:
gen # list all generations
rollback N # switch to generation N
gcnix # garbage collect (keeps last 5 generations)All key aliases
| Command | Does |
|---|---|
upnix |
Rebuild & switch (plays sound on done) |
update |
nix flake update |
gen |
List NixOS generations |
rollback N |
Roll back to generation N |
gcnix |
Garbage collect |
ll |
eza with icons & git info |
vim |
nvim |
top |
btop |
grep |
ripgrep |
find |
fd |
ping |
gping (graphical) |
curl |
xh |
lg |
lazygit |
gs ga gc gp |
git status / add / commit / push |
Keybindings (Hyprland)
| Shortcut | Action |
|---|---|
Super + Return |
Terminal (Ghostty) |
Super + E |
File manager (Dolphin) |
Super + Q |
Close window |
Super + F |
Fullscreen |
Super + Shift + S |
Screenshot (region) |
Super + Shift + R |
Start or stop screen recording |
Super + Shift + T |
Copy text from a screen region |
Super + Shift + Q |
Copy a QR code from a screen region |
Super + Ctrl + C |
Capture menu |
Super + Ctrl + . |
Transcode media |
Super + Shift + V |
Clipboard history |
F9 / Super + Ctrl + X |
Hold to dictate / toggle dictation |
Super + Alt + P |
Pin floating window across workspaces |
Super + H |
Search current shortcuts |
Super + 1-9 |
Switch workspace |
Super + Shift + 1-9 |
Move window to workspace |
Super + − |
Toggle special workspace |
Caelestia's Utilities panel shows the Keep awake card.
Keybindings (KDE Plasma)
Meta=Super(Windows key).
| Shortcut | Action |
|---|---|
Meta (tap) |
KRunner |
Meta + Space |
KRunner |
Meta + 1–5 |
Switch to desktop 1–5 |
Meta + Shift + 1–5 |
Move window to desktop 1–5 and follow |
Meta + Q / Alt + F4 |
Close window |
Meta + Left/Right/Up/Down |
Quick-tile window |
Meta + PgUp / PgDown |
Maximize / minimize window |
Meta + D |
Show desktop |
Meta + W |
Overview |
Meta + B |
Toggle bottom panel (dock) |
Meta + L |
Lock session |
Meta + I |
System Settings |
Meta + P |
Display config |
Meta + Shift + N |
Toggle Night Color |
Meta + Drag |
Move (L) / raise-lower (M) / resize (R) window |
Ctrl + Alt + T |
Terminal (Ghostty) |
Ctrl + Alt + A |
Terminal (Konsole) |
Ctrl + Shift + Esc |
System monitor |
Print / Meta + Shift + S |
Screenshot (full / region) |
Meta + Shift + V |
Clipboard history |
Meta + Ctrl + X |
Toggle dictation |
Meta + Ctrl + C |
Capture menu |
Meta + Shift + R |
Start or stop screen recording |
Meta + Shift + T |
Copy text from a screen region |
Meta + Shift + Q |
Copy a QR code from a screen region |
Meta + Alt + P |
Keep active window on all desktops |
Meta + H |
Open keyboard shortcut settings |
Note: Some shortcuts are powered by KWin scripts (
move-follow,toggle-bottom-panel), and theMeta-tap is a real modifier-only global shortcut — a bareMetakey added to KRunner's launch binding. Plasma 6.1+ handles lone modifiers via kglobalaccel, not the oldkwinrc [ModifierOnlyShortcuts]block (that is silently ignored now). After editing these inplasma-settings.nix, log out and back in for the keyboard bindings to take effect.
The visible battery icon in the system tray has Plasma's Manually block sleep and screen locking switch.
Keybindings (COSMIC)
| Shortcut | Action |
|---|---|
Super + Return / Ctrl + Alt + T |
Terminal (Ghostty) |
Super + E |
File manager (Dolphin) |
Super + Q |
Close window |
Super + F |
Fullscreen |
Super + V |
Toggle window floating |
Super + W |
Workspace overview |
Alt + Tab / Alt + Shift + Tab |
Window switcher (forward / backward) |
Super + Left/Right/Up/Down |
Focus window |
Super + Shift + Left/Right/Up/Down |
Move window |
Super + 1-9/0 |
Switch workspace |
Super + Shift + 1-9/0 |
Send window to workspace |
Super + L |
Lock session |
Ctrl + Alt + Delete |
Log out |
Print / Super + Shift + S |
Screenshot |
Super + Shift + V |
Clipboard history |
Super + Ctrl + X |
Toggle dictation |
Super + Ctrl + C |
Capture menu |
Super + Shift + R |
Start or stop screen recording |
Super + Shift + T |
Copy text from a screen region |
Super + Shift + Q |
Copy a QR code from a screen region |
Super + H |
Open keyboard shortcut settings |
Super + Alt + P |
Pin active window across workspaces |
Configured declaratively via cosmic-manager in modules/home-manager/cosmic.nix.
Keybindings (GNOME)
| Shortcut | Action |
|---|---|
Super + Return / Ctrl + Alt + T |
Terminal (Ghostty) |
Super + E |
File manager (Dolphin) |
Super + Q |
Close window |
Super + F |
Fullscreen |
Super + 1-9/0 |
Switch workspace |
Super + Shift + 1-9/0 |
Move window to workspace |
Super + L |
Lock session |
Print |
Screenshot (native GNOME screenshot UI) |
Super + Shift + S |
Screenshot |
Super + Shift + V |
Clipboard history |
Super + Ctrl + X |
Toggle dictation |
Super + Ctrl + C |
Capture menu |
Super + Shift + R |
Start or stop screen recording |
Super + Shift + T |
Copy text from a screen region |
Super + Shift + Q |
Copy a QR code from a screen region |
Super + H |
Open keyboard shortcut settings |
Super + Alt + P |
Pin active window across workspaces |
Configured via dconf.settings in modules/home-manager/gnome.nix. Workspaces are pinned to a static 10 (dynamic-workspaces = false) to match Hyprland/COSMIC instead of GNOME's default dynamic workspace behavior.
KDE Plasma layout:
Desktop widgets and panel layout are managed by plasma-manager via modules/home-manager/plasma-settings.nix. After editing and running upnix, Plasma needs a layout rebuild to pick up changes:
systemctl --user start plasma-layout-rebuildThis backs up your current layout, wipes Plasma's cache, and re-applies everything from config. Use it whenever widgets drift or don't appear after a rebuild.
Our environment features a suite of highly-polished custom and third-party widgets integrated into the panel and desktop:
- Glassy System Monitor — Real-time CPU, RAM, and network traffic monitor with clean glass visual aesthetics and an interface selector popup.
- AI Usage Widget — Track your Claude Code session and weekly API token usage directly on the panel.
- Nixdatifier — Tray app (also a Plasma widget and Quickshell panel) for NixOS generations, package diffs, flake updates and dev environments.
- GitPulse — GitHub activity, notifications, profile stats & Copilot usage monitoring widget for KDE Plasma.
- Tagesschau — News and finance feeds in a panel widget.
- Plasma Audio Visualizer — Smooth, GPU-friendly visualizer powered by
cavato show audio waveform feedback. - Advanced Weather Widget — Advanced weather forecast widget with radar and detailed popup tracking.
- Powerchart Widget — Real-time power consumption and battery statistics graphing.
- Modern Clock — Desktop clock widget featuring modern typography.
- Overview Widget — Workspace overview utility on the dock launcher.
Local and cloud AI coding assistants are pre-configured and ready after a rebuild.
cc-gemini # Claude Code → Gemini 2.5 Pro (requires GEMINI_API_KEY)
cc-openrouter # Claude Code → OpenRouter (requires OPENROUTER_API_KEY)
oc # OpenCode (auto-configured to local Ollama)Ollama runs as a system service. Models are not downloaded automatically — pull once on first use:
ai-pull # download default model (gemma4:4b, ~3-4 GB)
ai-pull <model> # download any other Ollama model
ai-models # list locally installed modelsThen launch:
cc-ollama # Claude Code → local Gemma 4 4B
cc-ollama qwen2.5-coder:7b # Claude Code → a different local model
oc # OpenCode → same local model
ai-webui # Open WebUI (if enabled: features.ai.openWebui.enable = true)
ai-webui-stop # Stop the WebUIPerformance note: CPU-only (no dedicated GPU) runs at ~4-15 tok/s depending on model size and CPU generation. The 4B model is the sweet spot for usability. Use cloud backends for latency-sensitive work.
| Model | Size | Speed (i5-13420H) | Best for |
|---|---|---|---|
gemma4:e4b |
~9 GB | ~10-15 tok/s | Default, general use (MoE) |
gemma4:e2b |
~5 GB | ~20+ tok/s | Fast replies, weaker reasoning |
qwen2.5-coder:7b |
~5 GB | ~6-10 tok/s | Coding-focused tasks |
gemma4:26b |
~17 GB | ~2-4 tok/s | Higher quality, slow |
Personal secrets (e.g. the :mail espanso snippet) are stored encrypted in secrets/secrets.yaml via sops-nix. SOPS is opt-in — set features.sops.enable = false if you don't need it; forks build fine without it.
First-time setup on a new machine
One command generates your age key, updates .sops.yaml, and opens the editor:
./deploy.sh sops-setupAdd your secrets (see secrets/secrets.yaml.example for the schema), then enable and rebuild:
features.sops.enable = true;upnixDay-to-day secret management
secrets edit # edit encrypted secrets
secrets rotate # re-encrypt after adding a new key to .sops.yamlAdding a new secret:
secrets edit→ add a key- Declare it in
modules/nixos/features/sops.nix:sops.secrets.my-secret = { owner = username; mode = "0400"; };
- Reference as a file path:
/run/secrets/my-secret
| Project | Author |
|---|---|
| Caelestia Shell | caelestia-dots |
| Sweet Theme & Cursors | EliverLara |
| Sonomatic SDDM | phob1an |
| Illusion Plymouth Splash | dgudim |
| Boot Animations (Google Veo) | Google DeepMind |
| Vivid Plasma Themes | L4ki |
| Slot Icon Theme | L4ki |
| Colorful Icon Theme | L4ki |
| Iridescent Plasma Style | ddh4r4m |
| Utterly Round Plasma Style | HimDek |
| Overview Widget | HimDek |
| Modern Clock Widget | prayag2 |
| Glassy System Monitor | muddyblack |
| AI Usage Widget | muddyblack |
| Nixdatifier | muddyblack |
| Advanced Weather Widget | pnedyalkov91 |
| Powerchart Widget | jboero |
| Plasma Audio Visualizer | muddyblack |
| GitPulse | muddyblack |
| Audio Wave Widget | zayronxio (inspiration) |
| Grub2 Themes | vinceliuice |
| rEFInd Theme | evanpurkhiser |
| Sly-Harvey/NixOS | Sly-Harvey |
| home-manager | nix-community |
| disko | nix-community |
| impermanence | nix-community |
| sops-nix | Mic92 |
| plasma-manager | nix-community |












