A standalone NixOS flake for configuring Hyprland desktop environment with Kartoza theming and customizations.
This flake provides a complete Hyprland desktop environment configuration that can be imported into any NixOS flake. It includes:
- Hyprland compositor with window animations and effects
- Waybar status bar with modular configuration and working taskbar
- Workspace Management: Named workspaces with fuzzel-based switcher
- Nwggrid and nwgpanel application launcher
- Mako notification daemon with Kartoza theming and custom sound
- Fuzzel and other utilities
- Complete theming and styling
- GNOME Keyring integration with SSH and GPG support
- Floating windows by default with optional tiling mode
- Secure clipboard management with clipse encryption and fuzzel interface
- Desktop zoom functionality for accessibility and presentations
- Screen recording with multi-monitor support and audio
- Emoji picker with fuzzel search interface
- On-screen key display for tutorials and presentations
Add this flake as an input to your NixOS configuration:
{
inputs = {
hyprland-desktop.url = "github:kartoza/nix-hyprland-desktop";
# ... other inputs
};
}Import the module and enable it in your NixOS configuration:
{
imports = [
hyprland-desktop.nixosModules.default
# ... other modules
];
# Enable Kartoza Hyprland Desktop with one line!
kartoza.hyprland-desktop.enable = true;
}IMPORTANT: You must configure your display manager to start Hyprland with the correct configuration file. The module configures greetd as the display manager, but you need to set the initial session command in your user configuration:
{
# Configure greetd to auto-login with Hyprland
services.greetd = {
enable = true;
settings = {
default_session = {
command = "${pkgs.greetd.tuigreet}/bin/tuigreet --time --cmd 'Hyprland --config /etc/xdg/hypr/hyprland.conf'";
user = "greeter";
};
# Optional: Auto-login for a specific user
initial_session = {
command = "Hyprland --config /etc/xdg/hypr/hyprland.conf";
user = "your-username"; # Replace with your actual username
};
};
};
}Critical Parameter:
--config /etc/xdg/hypr/hyprland.conf- Ensures Hyprland uses the module's configuration
Without this parameter, Hyprland will use default configs and the desktop environment may not work correctly.
After configuration, rebuild your system:
sudo nixos-rebuild switch --flake .#your-hostname{
kartoza.hyprland-desktop = {
enable = true;
iconTheme = "Papirus"; # Icon theme (default: "Papirus")
gtkTheme = "Adwaita"; # GTK theme (default: "Adwaita")
darkTheme = true; # Use dark theme (default: true)
fractionalScaling = 1.25; # Default scaling factor (default: 1.0)
qtTheme = "gnome"; # Qt platform theme (default: "gnome")
cursorTheme = "Vanilla-DMZ"; # Cursor theme (default: "Vanilla-DMZ")
cursorSize = 24; # Cursor size in pixels (default: 24)
# Per-display scaling overrides
displayScaling = {
"eDP-1" = 1.5; # Laptop screen at 150%
"DP-9" = 1.0; # External monitor at 100%
};
# Keyboard layout configuration
keyboardLayouts = [ "us" "pt" ]; # Default: US English, Portuguese
# keyboardLayouts = [ "us" "de" "fr" ]; # Example: US, German, French
# keyboardLayouts = [ "us" "es" ]; # Example: US, Spanish
# Wallpaper configuration
wallpaper = "/etc/kartoza-wallpaper.png"; # Default: Kartoza wallpaper
# wallpaper = "/home/user/Pictures/my-wallpaper.jpg"; # Example: Custom wallpaper
};
}The module provides intelligent keyboard layout management with configurable options:
- Multiple Layout Support: Configure any number of keyboard layouts
- Smart Toggle: Alt+Shift switches between layouts automatically
- Waybar Integration: Shows current layout with proper display names
- Auto-Detection: Waybar script reads layouts from Hyprland configuration
- Display Name Mapping: Converts layout codes to readable names (us→EN, de→DE, fr→FR, pt→PT, etc.)
# Default configuration (US English + Portuguese)
kartoza.hyprland-desktop = {
enable = true;
keyboardLayouts = [ "us" "pt" ];
};
# European configuration (US English + German + French)
kartoza.hyprland-desktop = {
enable = true;
keyboardLayouts = [ "us" "de" "fr" ];
};
# Spanish configuration
kartoza.hyprland-desktop = {
enable = true;
keyboardLayouts = [ "us" "es" ];
};
# Multi-language setup
kartoza.hyprland-desktop = {
enable = true;
keyboardLayouts = [ "us" "de" "fr" "it" "pt" ];
};- Module Configuration: The
keyboardLayoutsoption generates the Hyprland configuration - Hyprland Setup: Layouts are configured in
kb_layoutwith Alt+Shift toggle (grp:alt_shift_toggle) - Waybar Display: The keyboard layout script reads the Hyprland config and shows the current layout
- Toggle Methods:
- Hardware: Press Alt+Shift to cycle through layouts
- GUI: Click the keyboard layout widget in Waybar
The module supports standard XKB layout codes:
| Code | Language | Display Name |
|---|---|---|
us |
US English | EN |
pt |
Portuguese | PT |
de |
German | DE |
fr |
French | FR |
es |
Spanish | ES |
it |
Italian | IT |
ru |
Russian | RU |
pl |
Polish | PL |
nl |
Dutch | NL |
se |
Swedish | SE |
no |
Norwegian | NO |
dk |
Danish | DK |
fi |
Finnish | FI |
For other layouts, the script will display the uppercase layout code (e.g., cz → CZ).
The test VM is configured with US, German, and French layouts to demonstrate the feature:
./run-vm.sh
# In the VM: Press Alt+Shift to cycle between US, German, French layouts
# Check the Waybar keyboard layout widget for current layout displayThe module provides unified wallpaper management for both desktop background and lock screen:
- Unified Wallpaper: Same image used for desktop background and swaylock
- Configurable Path: Override with any image file path
- Lock Screen Styling: Swaylock displays wallpaper with beautiful Kartoza-themed overlay
- Effects: Lock screen includes blur, vignette, clock, and caps lock indicator
- Smart Scaling: Automatically scales wallpaper to fit screen resolution
# Default configuration (uses Kartoza wallpaper)
kartoza.hyprland-desktop = {
enable = true;
wallpaper = "/etc/kartoza-wallpaper.png"; # Default
};
# Custom wallpaper configuration
kartoza.hyprland-desktop = {
enable = true;
wallpaper = "/home/user/Pictures/my-wallpaper.jpg";
};
# Network wallpaper (downloaded separately)
kartoza.hyprland-desktop = {
enable = true;
wallpaper = "/usr/share/backgrounds/nature.jpg";
};Swaylock and swww support common image formats:
- PNG (.png)
- JPEG (.jpg, .jpeg)
- BMP (.bmp)
- WEBP (.webp)
The swaylock configuration includes:
- Clock Display: Shows current time and date
- Keyboard Layout: Shows current layout indicator
- Kartoza Theme: Blue and orange color scheme matching desktop
- Visual Effects: Blur effect on wallpaper, vignette overlay
- Security Features: Caps lock indicator, wrong password feedback
- Accessibility: Large, readable fonts and clear visual indicators
To test the wallpaper configuration:
# Test desktop wallpaper change
swww img /path/to/your/wallpaper.jpg
# Test lock screen wallpaper (Ctrl+Alt+L to lock)
swaylock -c /etc/xdg/swaylock/configThe module uses Mako as the notification daemon, providing lightweight desktop notifications with Kartoza theming.
- Lightweight and minimal resource usage
- Simple popup notifications with action button support
- Custom Kartoza branding and color scheme
- Custom notification sound
- Configuration via XDG config directories
Mako configuration can be customized by copying the system config to your home directory:
# Override Mako configuration
cp /etc/xdg/mako/kartoza ~/.config/mako/config
# Edit ~/.config/mako/config
# Override notification sound
mkdir -p ~/.config/mako/sounds
cp your-custom-sound.wav ~/.config/mako/sounds/notification.wavThe module provides a comprehensive workspace management system with named workspaces and fuzzel-based switching.
- Named Workspaces: Each workspace has a meaningful name (Browser, Chat, Terminal, etc.)
- Fuzzel Integration: Beautiful graphical workspace selector with fuzzel
- Waybar Widget: Clickable workspace indicator in status bar with working taskbar
- Window Management: Click taskbar icons to focus windows, middle-click to close
- Keyboard Shortcuts: Multiple ways to switch workspaces
- Change Tracking: Automatic logging when switching workspaces using
hyprctl - User Customizable: Override workspace names easily
- Floating Mode: Windows spawn in floating mode by default (Super+F to toggle tiling)
The system provides a 3×3 workspace grid with meaningful default names:
┌─────────────┬─────────────┬─────────────┐
│ 1: Browser │ 2: Chat │ 3: Terminal │
├─────────────┼─────────────┼─────────────┤
│ 4: Project1 │ 5: Project2 │ 6: Media │
├─────────────┼─────────────┼─────────────┤
│ 7: Documents│ 8: Games │ 9: System │
└─────────────┴─────────────┴─────────────┘
Super + S- Open fuzzel workspace switcher (primary method)Super + 1-9- Switch directly to workspace 1-9Super + Shift + 1-9- Move current window to workspace 1-9Ctrl + Super + Arrow Keys- Navigate workspace gridSuper + Shift + Ctrl + Arrows- Move window in workspace grid
The waybar displays a workspace widget showing:
- Current workspace number and name (e.g., "2: Chat")
- Click to open fuzzel workspace switcher
- Auto-updates when workspace changes
- Styled with Kartoza theme colors
# Show current workspace
workspace-names.sh current
# List all workspace names
workspace-names.sh list
# Rename a workspace
workspace-names.sh set 1 "Web Browser"
workspace-names.sh set 4 "Development"
# Get specific workspace name
workspace-names.sh get 2Override the default workspace names by copying and editing the configuration:
# Copy system config to user directory
mkdir -p ~/.config/hypr
cp /etc/xdg/hypr/workspace-names.conf ~/.config/hypr/
# Edit workspace names (format: workspace_number=workspace_name)
cat >> ~/.config/hypr/workspace-names.conf << EOF
0=My Browser
1=Slack & Teams
2=Terminal Work
3=Main Project
4=Side Project
5=Entertainment
6=File Management
7=Gaming
8=System Admin
EOFThe system calls workspace-changed.sh whenever workspace changes. You can override this script to add custom actions:
# Copy and customize the workspace change hook
cp /etc/xdg/hypr/scripts/workspace-changed.sh ~/.config/hypr/scripts/
# Edit to add your custom logic:
# - Change wallpaper per workspace
# - Start/stop applications
# - Adjust system settings
# - etc.The workspace management system consists of:
workspace-switcher.sh- Fuzzel-based workspace selectorworkspace-names.sh- Name management utilityworkspace-changed.sh- Change trigger hookworkspace-display.sh- Waybar widget scriptworkspace-names.conf- Name mappings configuration
All scripts support XDG user overrides and follow the same override patterns as other configuration files.
The module includes several integrated tools for productivity and accessibility, all using fuzzel interfaces with consistent Kartoza theming:
- Keybinding:
Super + ,(comma) - Technology: clipse + fuzzel integration
- Features:
- Encrypted clipboard history storage
- Beautiful fuzzel interface with numbered entries
- Preview of clipboard content with newline indicators
- Secure storage protects sensitive data
- Keybinding:
Super + .(period) - Technology: fuzzel + comprehensive emoji database
- Features:
- Searchable emoji database with descriptions
- Types emoji at cursor and copies to clipboard
- Fuzzel interface with consistent theming
- Supports all Unicode emoji categories
- Keybinding:
Ctrl + 6 - Technology: wf-recorder with Hyprland integration
- Features:
- Toggle recording on/off with single keybind
- Multi-monitor support (records focused monitor)
- Audio recording included
- High-quality H.264 encoding
- Saves to
~/Videos/Screencasts/with timestamped names - Visual notifications for recording status
- Keybindings:
Super + Shift + Scroll Up- Zoom inSuper + Shift + Scroll Down- Zoom outSuper + Shift + Z- Reset zoom to 1x
- Technology: Hyprland cursor zoom feature
- Features:
- Real-time desktop magnification like Wayfire
- Perfect for accessibility needs
- Great for screencasts and presentations
- Smooth zoom transitions
- No performance impact when not zooming
- Keybinding:
Ctrl + Super + K - Technology: wshowkeys with Kartoza theming
- Features:
- Shows pressed keys on screen
- Perfect for tutorials and presentations
- Kartoza color scheme integration
- Toggle on/off functionality
- Customizable position and appearance
# Show clipboard history
Super + ,
# Insert emoji at cursor
Super + .
# Start/stop screen recording
Ctrl + 6
# Zoom in for accessibility/presentations
Super + Shift + Scroll Up
# Show keys for tutorial recording
Ctrl + Super + KAll tools respect XDG configuration overrides. You can customize:
# Customize clipboard settings
cp /etc/xdg/hypr/scripts/clipboard.sh ~/.config/hypr/scripts/
# Edit ~/.config/hypr/scripts/clipboard.sh
# Customize emoji picker
cp /etc/xdg/fuzzel/fuzzel-emoji ~/.config/fuzzel/
# Edit ~/.config/fuzzel/fuzzel-emoji
# Customize wshowkeys appearance
cp /etc/xdg/hypr/scripts/wshowkeys-toggle.sh ~/.config/hypr/scripts/
# Edit font, colors, position in ~/.config/hypr/scripts/wshowkeys-toggle.shThis module deploys configuration files to /etc/xdg/ for system-wide availability. Users can override these configurations by creating local dotfiles in their home directories.
Configuration files are loaded in this order (highest to lowest priority):
- User home directory:
~/.config/hypr/,~/.config/waybar/, etc. - System XDG config:
/etc/xdg/hypr/,/etc/xdg/waybar/, etc. (this module) - Application defaults: Built-in application defaults
Copy the system configurations to your home directory and modify them:
# Copy hyprland config for customization
mkdir -p ~/.config/hypr
cp /etc/xdg/hypr/hyprland.conf ~/.config/hypr/
# Edit ~/.config/hypr/hyprland.conf as needed
# Copy waybar config for customization
mkdir -p ~/.config/waybar
cp /etc/xdg/waybar/config ~/.config/waybar/
cp /etc/xdg/waybar/style.css ~/.config/waybar/
# Edit ~/.config/waybar/ files as needed
# Copy mako config for customization
mkdir -p ~/.config/mako
cp /etc/xdg/mako/kartoza ~/.config/mako/config
# Edit ~/.config/mako/config as neededYou can override specific applications without copying entire configurations:
Hyprland: Create ~/.config/hypr/hyprland.conf with your custom configuration. You can include the system config and add overrides, or replace it entirely.
Waybar: Create ~/.config/waybar/ with your own config and style.css. For modular waybar configs, you can also copy the config.d/ directory and modify specific modules.
Mako: Create ~/.config/mako/config with your notification preferences.
For different environments (work, home, etc.), you can customize Hyprland configuration:
# In ~/.config/hypr/hyprland.conf
# Include the system config as base
source=/etc/xdg/hypr/hyprland.conf
# Override specific settings
general {
layout = master # Use master layout instead of dwindle
}
# Add custom keybinds
bind = $mainMod, T, exec, alacritty # Use alacritty instead of kitty
# Override window rules
windowrulev2 = tile, class:.* # Tile all windows by default instead of floatingFor waybar specifically, you can override individual modules:
# Copy the modular config system
mkdir -p ~/.config/waybar/config.d
cp -r /etc/xdg/waybar/config.d/* ~/.config/waybar/config.d/
# Modify specific modules
echo '{
"custom/my-widget": {
"format": "My Custom Widget",
"on-click": "my-command"
}
}' > ~/.config/waybar/config.d/99-my-custom-widget.json
# Rebuild the config (run this after making changes)
cd ~/.config/waybar
/etc/xdg/waybar/build-config.sh
# Restart waybar to apply changes
killall waybar
waybar &- Backup your changes: User configurations are not managed by Nix, so back them up separately
- System updates: When this module is updated, you may want to compare your local configs with the new system configs
- Script paths: If you copy scripts, update their paths in your local configs to point to your home directory
- Restarting services: After changing configs, restart the relevant applications (waybar, mako, etc.)
None! This module is completely self-contained and doesn't require any external configuration.
modules/hyprland-desktop.nix- Main NixOS moduledotfiles/- Configuration files for Hyprland and related applicationsresources/- Images and other static resources
Enter development shell:
nix developFormat code:
nix fmtYou can test the desktop environment in a VM without affecting your main system:
# Run the test VM (builds automatically)
./run-vm.sh
# Or run directly:
nix run .#nixosConfigurations.vm-test.config.system.build.vmThe VM includes:
- 4GB RAM, 4 CPU cores, 8GB disk
- Auto-login as
testuser(password:test) - Full Hyprland desktop with all components including working taskbar
- Hardware-accelerated graphics (1920x1080)
- Basic applications for testing (Firefox, file manager, terminal)
- Floating windows by default with tiling mode available (Super+F)
If you're running a NixOS system that already imports this flake, you can test local changes before committing:
In your main system flake, temporarily override the hyprland-desktop input to point to your local development copy:
{
inputs = {
hyprland-desktop.url = "path:/path/to/your/local/nix-hyprland-desktop";
# Or use a relative path if your system flake is in a parent directory:
# hyprland-desktop.url = "path:./nix-hyprland-desktop";
# ... other inputs
};
}Then rebuild your system:
sudo nixos-rebuild switch --flake .#your-hostnameIf you've pushed changes to the remote repository:
# In your system flake directory, update only this flake
nix flake lock --update-input hyprland-desktop
# Then rebuild
sudo nixos-rebuild switch --flake .#your-hostnameCreate a branch with your changes and test it:
# In this repository
git checkout -b feature/my-changes
git add . && git commit -m "Test changes"
# In your system flake, temporarily change the input
# hyprland-desktop.url = "github:kartoza/nix-hyprland-desktop/feature/my-changes";For rapid waybar configuration testing without full system rebuilds:
cd /path/to/nix-hyprland-desktop/dotfiles/waybar
# Build the modular config
./build-config.sh
# Test waybar with your changes (creates temporary second instance)
waybar -c config -s style.css --log-level debugThis method is useful for CSS styling and layout changes, but won't reflect module-level changes.
- Make changes in this repository
- Use local path override method above
- Test with
sudo nixos-rebuild switch
- Commit and push changes to a branch
- Test the branch using Method 3 above
- Create a pull request and merge to main
- Update your system flake to use the new commit:
nix flake lock --update-input hyprland-desktop
- Deploy with
sudo nixos-rebuild switch
After system rebuild, configuration files are available system-wide in /etc. To deploy them to user home directories:
deploy-hyprland-configsThis is useful when users want to customize configurations locally.
This configuration provides seamless integration between SSH/GPG keys and the GNOME Keyring:
- Automatic unlock: GPG keys become available when you unlock your keychain at login
- SSH agent integration: SSH keys stored in GNOME Keyring are automatically available
- GUI password prompts: Uses
pinentry-gnome3for secure password entry - Session persistence: Keys remain unlocked for the duration of your session
- At Login: PAM automatically unlocks GNOME Keyring using your login password
- GPG Integration: The GPG agent connects to the keyring and uses GUI prompts for passwords
- SSH Integration: SSH agent socket is exposed via
SSH_AUTH_SOCKenvironment variable
If you need to manually unlock your keyring (e.g., after screen lock):
unlock-keyringThis script will:
- Check if GNOME Keyring is running
- Prompt for your password if the keyring is locked
- Connect the GPG agent to the newly unlocked keyring
- Display status notifications
To add SSH keys to the keyring:
ssh-add ~/.ssh/your_private_keyGPG keys are automatically detected when stored in ~/.gnupg/. The configuration includes:
- Keyserver: Uses
hkps://keys.openpgp.orgfor key retrieval - Caching: Keys are cached for 8 hours (28800 seconds)
- Auto-retrieval: Automatically downloads missing public keys when needed
The system automatically creates GPG configuration files in your home directory:
~/.gnupg/gpg-agent.conf: GPG agent configuration with GUI pinentry~/.gnupg/gpg.conf: Basic GPG settings with keyserver configuration
These files are created automatically by the deploy-hyprland-configs script if they don't already exist.
GPG keys not accessible:
# Check GPG agent status
gpg-connect-agent 'keyinfo --list' /bye
# Restart GPG agent if needed
gpg-connect-agent killagent /bye
gpg-connect-agent /byeSSH keys not loading:
# Check SSH agent
echo $SSH_AUTH_SOCK
ssh-add -l
# If keyring SSH agent isn't working, check:
pgrep gnome-keyring-daemonKeyring not unlocking:
- Ensure your user password matches your keyring password
- The keyring password is typically set to your login password during first login
- Use
seahorse(GNOME Passwords and Keys) to manage keyring passwords if needed