A modern, declarative NixOS configuration featuring Hyprland, comprehensive home-manager integration, and per-machine customization.
Main desktop environment with Hyprland and Waybar
- Overview
- Features
- Screenshots
- System Components
- Home Manager Applications
- Installation
- Configuration
- Customization
- Managing Secrets
- Tips & Tricks
NullOS is a fully declarative NixOS configuration that provides a polished Wayland desktop experience using Hyprland. It leverages Nix flakes for reproducibility and home-manager for user-level configuration management.
Key Philosophy:
- Declarative Everything - System and user configurations defined in Nix
- Per-Machine Flexibility - Easy multi-host management with shared components
- Modern Desktop - Wayland-first with Hyprland compositor
- Developer-Friendly - Includes dev tools, containers, and virtualization support
✨ Desktop Environment
- Hyprland compositor with custom animations
- Waybar status bar with system monitoring
- Rofi application launcher
- SwayNC notification daemon
- SwayOSD for volume/brightness feedback
- Pyprland scratchpads for quick terminal access
- Hyprlock and Hypridle for screen locking
🎨 Theming
- Stylix-based system-wide theming
- GTK and Qt theme coordination
- Automatic wallpaper-based color schemes
🔧 System Services
- NVIDIA PRIME support with power-efficient specialisation
- Docker and virtualization ready
- VPN support (Tailscale, Mullvad, Cloudflare WARP, Riseup)
- Sunshine game streaming server
- Ollama AI inference server
- Automated backups with Restic
🛠️ Development Tools
- Neovim with Nixvim configuration (also NVF available)
- VSCode with Nix integration
- Android Studio and ADB
- Git with GitHub CLI
- Direnv for project environments
🎮 Gaming
- Steam with gamemode
- Lutris game launcher
- Moonlight streaming client
- GameMode performance optimizations
- Fusion 360 (via Wine)
These applications are installed system-wide via NixOS configuration:
- Window Manager: Hyprland
- Display Manager: SDDM
- Shell: Zsh with Powerlevel10k
- Editor: Neovim (default editor)
- File Manager: Dolphin
- Terminal: Ghostty
- Browser: Configurable (Brave by default)
- Audio: PipeWire + Pavucontrol
- Brightness Control: brightnessctl
- Screenshot: Custom screenshotin script + Swappy
- Notifications: SwayNC
- OSD: SwayOSD
- Display Configuration: nwg-displays
- Video Player: MPV
- Music Player: Rhythmbox
- Image Viewer: Eye of GNOME (eog)
- Screen Streaming: Gnome Network Displays
- Game Streaming: Moonlight, Sunshine
- Game Launcher: Lutris
- CAD/Design: Fusion 360 (via Wine)
- Notes: Obsidian
- Office Suite: LibreOffice (Configured via office.nix)
- Database Client: DbGate
- HTTP Client: HTTPie Desktop
- Torrent Client: qBittorrent
- Communication: Teams for Linux
- Containerization: Docker, Docker Compose
- Virtualization: KVM, libvirt
- Android: Android Studio, ADB
- Version Control: Git, GitHub CLI (gh)
- AI/ML: Ollama
- Process Monitor: btop, bottom
- Disk Usage: gdu, dysk, ncdu
- System Info: inxi, lshw, lm_sensors
- Hardware Utils: pciutils, usbutils, alsa-utils
- VPN: Tailscale, Mullvad, Cloudflare WARP, OpenFortiVPN, Riseup
- Secrets: GnuPG, libsecret, Seahorse
- Firewall: Managed by NixOS
- Archive Support: p7zip, unrar, unzip
- Binary Analysis: binwalk, hexdump
- File Search: ripgrep, eza
- Navigation: zoxide, yazi
- Video/Audio: ffmpeg, sox
- Wallpapers: hyprpaper
User-level applications managed via home-manager:
- Shell: Zsh with custom configuration
- Prompt: Starship
- File Explorer: Yazi
- Directory Jump: Zoxide
- Cat Replacement: Bat
- Ls Replacement: Eza
- Process Monitor: Bottom
- Quick Help: Tealdeer (tldr)
- Fetch: Fastfetch
- Editor: VSCode, Neovim (Nixvim/NVF)
- File Manager: Dolphin (system integration)
- HTTP Client: HTTPie Desktop
- Office Suite: LibreOffice (via office.nix)
- Display Config: nwg-displays
- Gaming: Lutris game launcher
- CAD: Fusion 360 (via Wine)
- Screenshot: Custom screenshotin script, Swappy
- Notifications: SwayNC
- OSD: SwayOSD
- Wallpaper: Custom wallsetter script
- Logout Menu: wlogout
- Git: Configured with credentials
- GitHub CLI: gh
- Direnv: Automatic environment loading
Located in home/scripts/:
- screenshotin - Screenshot utility with area selection
- keybinds - List all Hyprland keybindings
- rofi-launcher - Custom Rofi launcher wrapper
- wallsetter - Wallpaper management and setting
- A working NixOS installation with flakes enabled
- Git installed
- Your system hostname and desired username
If you haven't enabled flakes, add to /etc/nixos/configuration.nix:
nix.settings.experimental-features = [ "nix-command" "flakes" ];Then rebuild: sudo nixos-rebuild switch
git clone https://github.com/nullstring1/NullOS.git ~/NullOS
cd ~/NullOSNullOS includes pre-configured machines in machines/:
- nslapt - Laptop (NVIDIA Prime, passwordless sudo, Restic backup, iOS support)
- nspc - Desktop (full NVIDIA, Steam enabled)
- nsminipc - Headless server (minimal, no desktop environment)
To use an existing config:
# For nslapt (laptop)
sudo nixos-rebuild switch --flake .#nslapt
# For nspc (desktop)
sudo nixos-rebuild switch --flake .#nspcFor a new machine, create machines/yourhostname/default.nix:
{
# User settings
username = "youruser";
gitUsername = "Your Name";
gitEmail = "your@email.com";
# System settings
timeZone = "Europe/London";
locale = "en_GB.UTF-8";
keyboardLayout = "gb";
# Optional: Desktop environment (default: "hyprland")
# desktopEnvironment = "hyprland"; # or "kde" or null for headless
# Optional: NVIDIA (if applicable)
# useNvidiaPrime = true;
# intelBusId = "PCI:0:2:0";
# nvidiaBusId = "PCI:2:0:0";
# Optional: Customizations
# stylixImage = ./wallpapers/screen.jpg;
# resticRepository = "sftp:user@host:/backup/path";
}Create hardware config:
# Generate your hardware configuration
sudo nixos-generate-config --show-hardware-config > /tmp/hardware.nix
# Copy template and edit
cp modules/system/hardware_nslapt.nix modules/system/hardware_yourhostname.nix
# Edit the file and paste your hardware config from /tmp/hardware.nixUpdate flake.nix to include your machine. Refer to the existing nslapt and nspc configurations as templates.
# For custom hostname
sudo nixos-rebuild switch --flake .#yourhostname
# Or use the convenient alias (requires nix develop)
nix develop
fr # rebuilds current machine (via nh)- Log out and log back in to apply user environment
- Set your user password:
passwd - Configure SDDM autologin if desired (see customization)
- Apply your wallpaper: Run
wallsetteror place images inwallpapers/
NullOS uses a three-stage configuration system:
- Base defaults (
machines/profiles/base.nix) - Common settings, most features disabled - Profile config (
machines/profiles/pc.nixorserver.nix) - Sets 20+ features based on machine class - Machine overrides (
machines/{hostname}/default.nix) - Per-machine customization
This design allows sharing common configs while easily overriding for individual machines.
Each machine config lives in machines/{hostname}/default.nix. This is where you customize:
- User settings:
username,gitUsername,gitEmail - System settings:
timeZone,locale,keyboardLayout - Desktop environment:
desktopEnvironment("hyprland", "kde", or null for headless) - Hardware: GPU configuration, monitor settings
- Features: Enable/disable Docker, VSCode, Android Studio, Steam, etc.
- Secrets: Reference to
machines/{hostname}/secrets.yaml
Example structure:
{
# Identifiers
username = "nullstring1";
gitUsername = "Null String";
gitEmail = "null@example.com";
# Locale
timeZone = "Europe/London";
locale = "en_GB.UTF-8";
keyboardLayout = "gb";
# Desktop (optional, defaults to "hyprland")
desktopEnvironment = "hyprland";
# GPU (optional, for NVIDIA laptops)
useNvidiaPrime = true;
intelBusId = "PCI:0:2:0";
nvidiaBusId = "PCI:2:0:0";
# Optional customizations
stylixImage = ./wallpapers/mywall.jpg;
resticRepository = "sftp:user@host:/backup";
}nslapt (Laptop)
- NVIDIA PRIME (Intel iGPU + NVIDIA dGPU)
- Passwordless sudo
- Restic backups enabled
- iOS device support
- Power-efficient specialisation
nspc (Desktop)
- Full NVIDIA GPU support
- Steam with gamemode
- High-performance settings
- Distributed build machine setup
nsminipc (Headless Server)
- No desktop environment
- Minimal services
- Docker support
- Tailscale VPN
NullOS supports both Hyprland (primary) and KDE (secondary). Set in machine config:
# Hyprland (default)
desktopEnvironment = "hyprland";
# KDE
desktopEnvironment = "kde";
# Headless (no DE)
desktopEnvironment = null;Real secrets (API keys, tokens, backup credentials) use sops-nix with age encryption:
- Create
machines/{hostname}/secrets.yamlwith encrypted secrets - NixOS decrypts at system activation using age key at
~/.config/sops/age/keys.txt - Access in configs via
config.sops.secrets.secretname.path
Example secrets:
githubToken- For GitHub CLI accessnextdnsServerName,nextdnsStamp- If NextDNS enabledresticRepository- Backup target credentials
See .sops.yaml for encryption rules matching machines/.*/secrets.yaml.
Convenient shell aliases (defined in home/zsh/default.nix):
fr # nh os switch --hostname {hostname}
# Fast rebuild current machine
fu # nh os switch --hostname {hostname} --update
# Rebuild with flake input updates
ncg # Garbage collection + bootloader cleanup + home-manager generationsTo use these, enter the dev shell first:
nix develop
fr # Now you can use the aliasNullOS uses Stylix for automatic theming based on wallpapers.
- Add your wallpaper to
wallpapers/ - Update your machine config (
machines/{hostname}/default.nix):
stylixImage = ./wallpapers/yourwallpaper.jpg;- Rebuild:
frorsudo nixos-rebuild switch --flake .#yourhostname
Edit modules/software/packages.nix:
environment.systemPackages = with pkgs; [
# Add your package here
newpackage
];Create a new file in home/ or add to existing configuration:
# home/myapp.nix
{ pkgs, ... }:
{
home.packages = [ pkgs.myapp ];
}Then import in home/default.nix:
imports = [
# ... existing imports
./myapp.nix
];Edit home/hyprland/binds.nix:
bind = [
"SUPER,X,exec,yourcommand" # Add your keybind
];View current keybinds: Press SUPER+K or run keybinds
Change animation style by updating your machine config:
# In machines/{hostname}/default.nix (optional, defaults to animations-end4)
# animationSet = ./home/hyprland/animations-yourname.nix;Edit home/hyprland/windowrules.nix:
windowrule = [
"match:class (myapp), float on" # Add custom window rules
];Monitor config can be handled at runtime with nwg-displays (F8 key), or declaratively:
Edit your machine config:
# In machines/{hostname}/default.nix
extraMonitorSettings = ''
monitor = DP-1, 2560x1440@144, 0x0, 1
monitor = HDMI-A-1, 1920x1080@60, 2560x0, 1
'';Edit home/waybar/default.nix to modify the status bar layout, modules, and appearance.
Edit home/hyprland/pyprland.nix:
[scratchpads.myapp]
animation = "fromTop"
command = "myapplication"
size = "70% 70%"
max_size = "1920px 100%"Bind in home/hyprland/binds.nix:
"SUPER,A,exec,pypr toggle myapp"Edit home/zsh/zshrc-personal.nix for custom shell aliases and functions.
Customize prompt: home/zsh/p10k-config/p10k.zsh
Or run the configuration wizard:
p10k configureNullOS uses Nixvim as the primary Neovim configuration. Edit home/nixvim.nix to customize your editor. An alternative NVF configuration is also available in home/nvf.nix.
Set your git identity in your machine config:
# In machines/{hostname}/default.nix
gitUsername = "Your Name";
gitEmail = "your@email.com";Additional git config can be added in home/git.nix.
Real secrets (API keys, backup credentials, etc.) are encrypted using sops-nix with age encryption.
Setup (first time):
- Generate age keys:
mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt- Create
machines/{hostname}/secrets.yamlwith your secrets:
githubToken: your-secret-token
resticPassword: your-backup-password
nextdnsServerName: your.server.name- Encrypt with sops (automatic via
.sops.yamlrules):
sops machines/yourhostname/secrets.yaml- Reference in your machine config or modules using
config.sops.secrets.secretname.path
Secrets are automatically:
- Encrypted at rest (age encryption)
- Stored in git safely
- Decrypted during system activation
- Made available to services
Some configurations may require --impure flag during development:
sudo nixos-rebuild switch --flake .#yourhostname --impureHowever, with the sops-nix secrets system, you typically don't need this flag.
# Enter dev shell (provides aliases and build tools)
nix develop
direnv allow # Auto-activate on cd (if using direnv)
# Rebuild system (flake reload)
fr # = nh os switch --hostname {hostname}
# Update flake inputs and rebuild
fu # = nh os switch --hostname {hostname} --update
# Garbage collection
ncg # = nix-collect-garbage --delete-old && sudo nix-collect-garbage -d && bootloader cleanup
# Validate flake
nix flake check
# List generations
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
# Rollback to previous generation
sudo nh os rollback
# Home manager switch (standalone)
home-manager switch --flake .Press SUPER+K to view all keybindings, or check home/hyprland/binds.nix.
Essential bindings:
SUPER+Return- TerminalSUPER+SHIFT+Return- App launcherSUPER+W- BrowserSUPER+E- File managerSUPER+S- ScreenshotSUPER+C- VSCodeSUPER+T- Scratchpad terminalSUPER+Q- Close windowSUPER+SHIFT+C- Exit Hyprland
For laptops with NVIDIA GPUs:
Boot into power-efficient mode: Select "power-efficient" from GRUB menu, or:
sudo nixos-rebuild boot --flake .#nslapt --specialisation power-efficient
sudo rebootCheck current GPU:
glxinfo | grep "OpenGL renderer"The system includes Restic backup configuration. Configure in your machine config:
# In machines/{hostname}/default.nix
resticRepository = "sftp:user@host:/backup/path";Service is defined in modules/services/backup.nix.
# Remove old generations
ncg
nh clean all
# Remove old home-manager generations
home-manager expire-generations "-7 days"# Update all flake inputs
fu
# or
nix flake update
# Update specific input
nix flake lock --update-input nixpkgs
# Rebuild with updates
sudo nixos-rebuild switch --flake .#yourhostname
# or
fr
# or
nh os switch --flake .#yourhostnameSystem won't boot:
- Select previous generation from GRUB menu
- Or boot from NixOS installer and rollback
Home manager conflicts:
- Check
~/.config/for files that need manual removal - Home manager backup files have
.backupextension
Build errors:
- Check syntax with
nix flake check - Review error messages for missing imports or syntax errors
- Ensure all required files are staged in git (or use
--impure)
NVIDIA issues:
- Check
nvidia-smioutput - Review NVIDIA module in
modules/system/nvidia.nix - Try power-efficient specialisation
Feel free to fork this configuration and make it your own! If you find bugs or have improvements, pull requests are welcome.
This configuration is provided as-is for personal use and modification.
Built with:
Original inspiration:
Enjoy your NullOS experience! 🚀




