Computers are like Old Testament gods; lots of rules and no mercy, Joseph Campbell
To err is human - and to blame it on a computer is even more so, Robert Orben
NixOS is a unique, innovative, and powerful Linux distribution that leverages the Nix package manager. Unlike traditional Linux distributions that update packages and system configurations in-place, NixOS uses a purely functional and declarative approach to define the system state, reducing the risk of system breakage.
NixOS is a Linux distribution that uses the Nix package manager to handle packages and system configuration in a purely functional manner. This approach ensures that builds are reproducible and that the system state can be reliably replicated or rolled back.
sudo nix-env ‐‐rollback is a command used to revert your system to the previous configuration. It’s a powerful tool for undoing unintended changes or recovering from failed package installations. Before rolling back, consider if there’s a more targeted solution, like uninstalling specific packages or reverting configuration files.
Hyprshot. Grim is a lightweight command-line utility that allows you to capture screenshots of your screen and slurp works alongside Grim to let you select a region on the screen with your mouse for the screenshot.
However, Grim + Slurp provides the best balance of simplicity and functionality for Hyprland. It’s lightweight, scriptable (easy to incorporate into custom scripts), and integrates seamlessly with Wayland compositors, including Hyprland.
Step 1. Install the packages:
environment.systemPackages = with pkgs; [
grim # Screenshot tool for full-screen or region-based screenshot
slurp # Tool to select a specific region on the screen.
wl-clipboard # For clipboard integration,...
# it ensures you can pipe image or text to your Wayland clipboard
];
Step 2. Create a keybinding for them (bindings.nix):
{ modifier, terminal, browser, scriptsDir, powerMenuCommand, ... }:
let
screenshotDir = "$HOME/Downloads";
in
''
bind = ${modifier},P,exec,sh -c 'grim "${screenshotDir}/$(date +%Y-%m-%d_%H-%M-%S).png"'
# Modifier (Super/Window refers to the main key you hold) + P (this is the key to be pressed alongside the modifier)
# exec tells Hyprland to run a command
# sh -c '---' runs the specified shell command
# grim ... calls Grim to take a full screenshot and save it to ${screenshotDir}/$(date +%Y-%m-%d_%H-%M-%S).png
bind = ${modifier}+ALT,P,exec,sh -c 'grim -g "$(slurp)" "${screenshotDir}/$(date +%Y-%m-%d_%H-%M-%S).png"'
# Similar to the above, but it includes the Alt key, too
# Modifier + Alt + P: To capture a user-selected region of the screen...
# and saves the file in the same directory
Pressing the modifier key (usually Win/Super) + number switches directly to that specific workspace. Modifier + SHIFT + Arrow Keys moves the current/active window in the specified direction: l = left, r = right, u = up, and d = down. Modifier + CTRL + Arrow Keys resizes the active window: Left/Right (-20, 0; shrinks horizontally.) or (20, 0; expands horizontally); Up/Down (0, -20; shrinks vertically) or (0, 20; expands vertically),
# Workspace management keybindings
bind = ${modifier},1,workspace,1
bind = ${modifier},2,workspace,2
bind = ${modifier},3,workspace,3
bind = ${modifier},4,workspace,4
bind = ${modifier},5,workspace,5
bind = ${modifier},6,workspace,6
bind = ${modifier},7,workspace,7
bind = ${modifier},8,workspace,8
# Move window keybindings
bind = ${modifier}+SHIFT,Left,movewindow,l
bind = ${modifier}+SHIFT,Right,movewindow,r
bind = ${modifier}+SHIFT,Up,movewindow,u
bind = ${modifier}+SHIFT,Down,movewindow,d
# Resize window keybindings
bind = ${modifier}+CTRL,Left,resizeactive,-20 0
bind = ${modifier}+CTRL,Right,resizeactive,20 0
bind = ${modifier}+CTRL,Up,resizeactive,0 -20
bind = ${modifier}+CTRL,Down,resizeactive,0 20
# Miscellaneous window management keybindings
bind = ${modifier},F,fullscreen # Pressing Modifier + F toggles fullscreen.
bind = ${modifier}+SHIFT,1,movetoworkspace,1 # Move to workspace 1
bind = ${modifier}+SHIFT,2,movetoworkspace,2 # Move to workspace 2
bind = ${modifier}+SHIFT,3,movetoworkspace,3 # Move to workspace 3
bind = ${modifier}+SHIFT,4,movetoworkspace,4 # Move to workspace 4
bind = ${modifier}+SHIFT,5,movetoworkspace,5 # Move to workspace 5
bind = ${modifier}+SHIFT,6,movetoworkspace,6 # Move to workspace 6
bind = ${modifier}+SHIFT,7,movetoworkspace,7 # Move to workspace 7
bind = ${modifier}+SHIFT,8,movetoworkspace,8 # Move to workspace 8
bind = ${modifier}+SHIFT,9,movetoworkspace,9 # Move to workspace 9
'';
Inicio.sh (~/dotfiles/scripts/inicio.sh). It is started by the user.
#!/bin/bash
# Exit immediately if a command exits with a non-zero status
set -e
swww-daemon & # Start the swww daemon in the background, which handles wallpapers and transitions on Wayland.
sleep 1 # Waits for 1 second to ensure the daemon is ready
WALLPAPER=$(find ~/wallpapers -type f | shuf -n 1)
# Selects a random file from the wallpaper directory using find and shuf.
swww img --transition-type grow "$WALLPAPER"
# Applies the selected wallpaper with the grow transition effect.
# Function to launch an application in a specific workspace
# Takes two parameters: workspace (e.g. "1", "2") and app (the command to launch).
launch_app_in_workspace() {
local workspace="$1"
local app="$2"
# Switch to the desired workspace
hyprctl dispatch workspace "$workspace"
sleep 0.5 # Wait for the workspace to switch
# Launch the application in the workspace given as an argument
hyprctl dispatch exec "$app" &
sleep 0.5 # Wait for the application to launch
}
# Launch applications in respective workspaces
launch_app_in_workspace "1" "alacritty"
launch_app_in_workspace "2" "firefox"
launch_app_in_workspace "3" "md.obsidian.Obsidian"
launch_app_in_workspace "4" "code ~/justtothepoint/"
launch_app_in_workspace "4" "com.google.Chrome"
launch_app_in_workspace "5" "pcmanfm"
launch_app_in_workspace "special:geany" "geany"
We launch alacritty in workspace 1, firefox in workspace 2, Obsidian in workspace 3, etc. For a “special” workspace called special:geany, you launch geany.
waybar is a highly customizable bar for Wayland compositors. It supports Hyprland by default. waybar has a modular design. You can place modules on the left, center, and right sections or sides of the bar where different functionalities would be displayed.
First step. In your NixOS configuration (/etc/nixos/configuration.nix), install some packages and fonts.
{ config, pkgs, ... }: {
# System-wide installation
environment.systemPackages = with pkgs; [
...
waybar # The bar itself
pavucontrol # A GUI for controlling audio levels in PulseAudio.
pulseaudio # The PulseAudio sound server (needed for volume modules in Waybar).
playerctl # Controls media players from the command line (many Waybar modules rely on playerctl to display currently playing songs).
networkmanagerapplet # A system tray utility to manage networks.
];
fonts = {
packages = with pkgs; [
fira-code
fira-code-symbols
font-awesome
dejavu_fonts
# Nerd Fonts provide many additional icons and glyphs, useful for displaying icons in Waybar.
(nerdfonts.override { fonts = [ "NerdFontsSymbolsOnly" ]; })
(nerdfonts.override { fonts = [ "FiraCode" "SourceCodePro" ]; })
];
};
# For Waybar to interact with system inputs and have full functionality, you need to add your user to the input group,...
# wheel (run admin commands), and networkmanager groups (manage networks).
users.users.nmaximo7 = {
isNormalUser = true;
description = "nmaximo7";
extraGroups = [ "networkmanager" "wheel" "docker" "input"];
shell = "${pkgs.zsh}/bin/zsh";
packages = with pkgs; [
# ...
];
};
Second Step. If you’re using Home Manager to manage your user-level environment, settings, and packages, you can install Waybar at the user level, e.g., /home/${username}/dotfiles/home-manager.nix:
# Install Waybar
home.packages = with pkgs; [
waybar
# ... other packages ...
];
Third Step. In your Hyprland configuration (hyprland.nix):
{ config, pkgs, ... }:
{
home.file = {
# Specify the source for Waybar configuration file
".config/waybar/config".source = "/home/${username}/dotfiles/waybar/config";
# Specify the source for Waybar style CSS file
".config/waybar/style.css".source = "/home/${username}/dotfiles/waybar/style.css";
# We’re telling Home Manager to link our custom Waybar config and CSS from /home/${username}/dotfiles/waybar/.
};
wayland.windowManager.hyprland = {
enable = true; # Enable Hyprland as the Wayland window manager
xwayland = {
enable = true; # Enable XWayland for compatibility with X11 applications
};
systemd.enable = true; # Enable systemd support for managing services
package = pkgs.hyprland; # Specify the package for Hyprland
# Additional configuration for Hyprland
extraConfig = let
modifier = "SUPER"; # Define the modifier key (e.g., Super/Windows key as your main key)
in ''
[...]
# Execute nm-applet for the Network Management tray icon
exec-once = nm-applet --indicator
# Start Waybar with a small delay to ensure other services(like nm-applet) are ready
exec-once = sleep 1 && waybar
[...]
'';
};
}
Fourth step. Create and configure the Waybar configuration and the style CSS file for theming which is a standard CSS file.
{ // /home/${username}/dotfiles/waybar/config
"layer": "top", // Position of the Waybar above other UI layers
"modules-left": ["custom/arch", "hyprland/workspaces", "group/quicklaunch"], // Modules on the left side of the bar
"modules-center": ["clock", "keyboard-state", "custom/weather"], // Centered modules
"modules-right": ["cpu", "memory", "pulseaudio", "network", "custom/power"], // Modules on the right side of the bar
Each module has:
// Custom module to display the NixOS Linux logo
"custom/arch": {
# Font-awesome, Material icons or Nerd fonts provide a series of really nice unicode icons which can be used in Waybar.
"format": "Go to FontAwesome", // Icon for NixOS
"tooltip": false, // No tooltip on hover
"on-click": "rofi -show run" // Opens Rofi application launcher on click
},
// Workspace management for Hyprland.
// The workspaces module displays the current active workspaces in your Wayland compositor.
"hyprland/workspaces": {
"format": "{icon}", // Display the workspace icon
"tooltip": false, // No tooltip on hover
"all-outputs": true, // Show workspaces across all outputs
"format-icons": {
"active": "", // Icon for active workspace
"default": "" // Icon for inactive workspaces
}
},
// A group module for launching your favorite apps quickly.
// Module groups allow stacking modules in the direction "orientation" to the bar direction.
"group/quicklaunch": {
"orientation": "horizontal", // Arrange quick launch icons horizontally
"modules": [
"custom/firefox", // Custom module for Firefox
"custom/vscode", // Custom module for VSCode
"custom/alacritty", // Custom module for Alacritty terminal
"custom/pcmanfm" // Custom module for PCManFM file manager
]
},
// Custom module for launching the web browser Firefox
// custom/ modules are user-defined. You specify the text/icon and an on-click action.
"custom/firefox": {
"format": "", // Firefox icon
"on-click": "firefox" // Command to launch Firefox
},
// Custom module for launching Visual Studio Code
"custom/vscode": {
"format": "", // VSCode icon
"on-click": "code" // Command to launch VSCode
},
// Custom module for launching the Alacritty terminal
"custom/alacritty": {
"format": "", // Alacritty icon
"on-click": "alacritty" // Command to launch Alacritty
},
// Custom module for launching PCManFM file manager
"custom/pcmanfm": {
"format": "", // PCManFM icon
"on-click": "pcmanfm" // Command to launch PCManFM
},
// Clock module configuration.
// It displays the current date and time.
"clock": {
"format": " {:%H:%M}", // Display time (04:35) with a clock icon and custom color
"format-alt": "{:%d·%m·%y}", // day-month-year, e.g., 19-12-24.
"tooltip-format": "{calendar}" // Tooltip for showing the current calendar
},
// Keyboard state module configuration
// It displays the state of number lock, caps lock, and scroll lock.
"keyboard-state": {
"numlock": true, // Show NumLock status
"capslock": true, // Show CapsLock status
"format": "{name} {icon} ", // Format for displaying keyboard state
"format-icons": {
"locked": " ", // Icon for locked state
"unlocked": "" // Icon for unlocked state
}
},
// PulseAudio volume control module
// It displays the current volume reported by PulseAudio.
// Besides, you can control the volume by scrolling up or down while the cursor is over the module.
"pulseaudio": {
"format": "{icon} {volume}%", // It displays the volume with an icon and custom color
"format-muted": "", // Icon for muted state
"tooltip": false, // No tooltip on hover
"format-icons": {
"headphone": "", // Icon for headphone connection
"default": ["", "", "", "", "", "", "", ""] // Based on the current volume, the corresponding icon gets selected.
},
"scroll-step": 1, // The speed in which to change the volume when scrolling.
"on-click": "pavucontrol" // Opens PulseAudio Volume Control on click.
},
// CPU usage module configuration
"cpu": {
"interval": 10, // Update interval in seconds
"format": " {usage}%" // It displays current CPU usage with an illustrated icon.
},
// Memory usage module configuration
"memory": {
"interval": 30, // Update interval in seconds
"format": " {used:0.1f}GiB/{total:0.1f}GiB ({percentage}%)" // Display current memory usage
},
// Network status module configuration.
// It displays information about the current network connections.
"network": {
"interface": "enp5s0", // Network interface to monitor (optional)
"format": "{ifname}", // Display interface name
"format-wifi": " {essid}", // Display Name (SSID) of the wireless network.
"format-ethernet": " {ipaddr}/{cidr} ", // Display IP address and subnetmask corresponding to the IP for Ethernet
"format-disconnected": " No Network", // Message when disconnected
"tooltip-format": "{ifname} via {gwaddr} ", // Tooltip for network info (interface name and default gateway for the interface)
"format-alt": "{ifname}: {ipaddr}/{cidr}"
// Alternative format for displaying network info: Interface name: IP/Mask.
},
// Custom power management module
"custom/power": {
"format": "⏻", // Power icon
"tooltip": false, // No tooltip on hover
"on-click": "rofi -show power-menu -modi power-menu:rofi-power-menu" // Opens power menu with Rofi
// Rofi Power Menu provides a mode for offering basic power menu operations...
// such as shutting down, logging out, rebooting and suspending.
},
// Custom weather module configuration
"custom/weather": {
"format": "{}", // Display format for the weather
"exec": "curl 'wttr.in/yourCity?format=1'", // Command to fetch weather using curl from wttr.in
"interval": 1800, // Update interval in seconds (30 minutes)
"on-click": "firefox 'https://www.meteoblue.com/en/weather/week/yourCity_yourCountry'" // Opens weather website on click
}
}