Press ESC to close Press / to search

NixOS Complete Beginner’s Guide 2026: Declarative, Reproducible Linux Configuration

🎯 Key Takeaways

  • What Makes NixOS Different
  • The Nix Package Manager Basics
  • Installing NixOS
  • Understanding configuration.nix
  • nix-env vs nix shell

πŸ“‘ Table of Contents

Most Linux distributions work roughly the same way: you install packages imperatively (apt install, dnf install, pacman -S), files get written to various system directories, configuration is scattered across /etc, and over time your system accumulates a history of changes that is difficult to fully understand or reproduce. NixOS takes a fundamentally different approach. Your entire system β€” every installed package, every configuration file, every system service β€” is described in a single declarative configuration written in the Nix language. To change anything about your system, you change the configuration and rebuild. The result is a system that is reproducible, rollback-capable, and impossible to drift into an inconsistent state.

What Makes NixOS Different

The core philosophy of NixOS rests on a few key ideas:

  • Declarative configuration: Instead of running a sequence of commands to configure your system, you describe the desired state. NixOS figures out how to get there.
  • Atomic upgrades: System upgrades are transactional. Either the entire upgrade succeeds, or nothing changes. There is no in-between state where half your system is updated.
  • Rollback at boot: Every system rebuild generates a new "generation." GRUB lists your last several generations, so if an upgrade breaks something, you reboot and select the previous generation from the boot menu.
  • No dependency conflicts: The Nix package manager installs packages into content-addressed paths under /nix/store/. Multiple versions of the same library can coexist without conflict.
  • Reproducibility: Given the same configuration, NixOS will produce (almost) identical systems. This is invaluable for DevOps work where "works on my machine" is an unacceptable answer.

The Nix Package Manager Basics

NixOS is built on the Nix package manager, which can also be installed on other Linux distributions and macOS without switching to NixOS. Understanding Nix’s storage model is key to understanding everything else.

Every package in Nix is stored in a path like:

/nix/store/ywlgk3mg7wnbhwfcr8m6bfhh6b4bldg5-firefox-121.0/

The hash at the beginning is derived from every input that went into building the package β€” the source code, the build script, every dependency, every compiler flag. If any input changes, the hash changes, and the package gets its own directory in /nix/store/. This is why multiple versions can coexist: they have different hashes and therefore different paths.

Your user environment and system profile are symbolic links that point into /nix/store/. When you "install" a package, Nix adds a symlink to the package’s binaries in your profile. When you "uninstall" a package, the symlink is removed. The actual files in /nix/store/ are never modified β€” only created (when building) and garbage collected (when no longer referenced).

Installing NixOS

Step 1: Download the ISO

Download the NixOS ISO from the official website at https://nixos.org/download/. For most users, the GNOME graphical ISO is the easiest starting point. There is also a minimal ISO for those comfortable with command-line installation.

Step 2: Boot and Partition

Boot from the ISO. For a UEFI system, partition your disk with a tool like parted:

# Open parted on your target disk (adjust /dev/sda as needed)
sudo parted /dev/sda

# In the parted prompt:
(parted) mklabel gpt
(parted) mkpart ESP fat32 1MiB 512MiB
(parted) set 1 esp on
(parted) mkpart primary 512MiB 100%
(parted) quit

Format the partitions:

# Format the EFI partition
sudo mkfs.fat -F 32 /dev/sda1

# Format the root partition (ext4 or btrfs β€” btrfs recommended for snapshotting)
sudo mkfs.btrfs /dev/sda2

Step 3: Mount and Generate Configuration

# Mount the root partition
sudo mount /dev/sda2 /mnt

# Create and mount the EFI directory
sudo mkdir -p /mnt/boot/efi
sudo mount /dev/sda1 /mnt/boot/efi

# Generate the initial configuration
sudo nixos-generate-config --root /mnt

# This creates two files:
# /mnt/etc/nixos/configuration.nix  -- your main config
# /mnt/etc/nixos/hardware-configuration.nix  -- auto-detected hardware

Understanding configuration.nix

The generated configuration.nix is where you define your entire system. Here is an annotated example configuration for a typical desktop system:

# /etc/nixos/configuration.nix
{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan
      ./hardware-configuration.nix
    ];

  # Bootloader configuration
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # Networking
  networking.hostName = "my-nixos";
  networking.networkmanager.enable = true;

  # Timezone and locale
  time.timeZone = "America/New_York";
  i18n.defaultLocale = "en_US.UTF-8";

  # Enable the X11 windowing system with GNOME
  services.xserver.enable = true;
  services.xserver.displayManager.gdm.enable = true;
  services.xserver.desktopManager.gnome.enable = true;

  # Enable sound
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    pulse.enable = true;
  };

  # Define a user account
  users.users.alice = {
    isNormalUser = true;
    description = "Alice";
    extraGroups = [ "networkmanager" "wheel" "docker" ];
    shell = pkgs.zsh;
  };

  # System-wide packages
  environment.systemPackages = with pkgs; [
    vim
    wget
    curl
    git
    firefox
    htop
    ripgrep
    tmux
  ];

  # Enable Docker
  virtualisation.docker.enable = true;

  # Enable SSH daemon
  services.openssh.enable = true;

  # Enable zsh
  programs.zsh.enable = true;

  # Allow unfree packages (needed for some proprietary software)
  nixpkgs.config.allowUnfree = true;

  # NixOS version β€” do not change this on existing systems
  system.stateVersion = "25.05";
}

Apply the Configuration

# Install NixOS with your configuration
sudo nixos-install

# Set the root password when prompted
# Then reboot into your new system
sudo reboot

Once booted, you can modify /etc/nixos/configuration.nix and rebuild:

# After making changes to configuration.nix
sudo nixos-rebuild switch

# This builds the new configuration, makes it the current system,
# and starts/stops services as needed

# To build and test without making it the default boot entry
sudo nixos-rebuild test

# To roll back to the previous generation
sudo nixos-rebuild switch --rollback

nix-env vs nix shell

Beyond system configuration, Nix offers two main ways to install software at the user level:

nix-env (imperative, classic approach) installs packages into your user profile:

# Install a package to your user profile
nix-env -iA nixpkgs.nodejs

# List installed packages
nix-env -q

# Uninstall a package
nix-env -e nodejs

nix shell (declarative, modern approach) creates a temporary environment with specified packages, without permanently installing them:

# Start a shell with Node.js and Python available
nix shell nixpkgs#nodejs nixpkgs#python3

# Run a command in a temporary environment without entering a shell
nix run nixpkgs#cowsay -- "Hello from Nix"

# Start a development environment for a project (reads flake.nix)
nix develop

Introduction to Nix Flakes

Flakes are a modern Nix feature that adds reproducibility and composability to Nix expressions. A flake is a directory containing a flake.nix file that explicitly declares all inputs (other flakes it depends on) and produces well-defined outputs.

# flake.nix example for a development environment
{
  description = "My project development environment";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in {
        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            nodejs_20
            yarn
            postgresql_16
            redis
          ];

          shellHook = ''echo "Development environment loaded"'';
        };
      }
    );
}

To enable flakes on NixOS (they are still experimental but widely used), add to your configuration.nix:

nix.settings.experimental-features = [ "nix-command" "flakes" ];

Home Manager

Home Manager extends NixOS’s declarative approach to user-level dotfiles and applications. Instead of manually maintaining ~/.bashrc, ~/.config/git/config, and similar files, you declare them in a Home Manager configuration:

# home.nix
{ config, pkgs, ... }:

{
  home.username = "alice";
  home.homeDirectory = "/home/alice";

  programs.git = {
    enable = true;
    userName = "Alice Smith";
    userEmail = "alice@example.com";
    extraConfig.init.defaultBranch = "main";
  };

  programs.zsh = {
    enable = true;
    enableAutosuggestions = true;
    enableSyntaxHighlighting = true;
    oh-my-zsh = {
      enable = true;
      theme = "robbyrussell";
    };
  };

  home.packages = with pkgs; [
    fzf
    bat
    eza
    fd
  ];

  home.stateVersion = "25.05";
}

Common Beginner Mistakes

NixOS has a learning curve, and certain mistakes come up repeatedly:

  • Editing files outside of Nix: Do not manually edit files in /etc/ expecting them to persist. NixOS manages those files. Put your configuration in configuration.nix.
  • Forgetting to run nixos-rebuild: Changes to configuration.nix do nothing until you run sudo nixos-rebuild switch.
  • Letting /nix/store grow unchecked: Nix never automatically deletes old generations. Run sudo nix-collect-garbage -d periodically to remove old generations and free disk space.
  • Using nix-env instead of declarative config: nix-env installs are not tracked in your system configuration and will not survive a system rebuild that does not include the package. Prefer environment.systemPackages in configuration.nix.

NixOS has one of the steepest learning curves of any Linux distribution, but the payoff is equally steep. Once you have experienced truly reproducible systems, atomic upgrades, and one-command rollbacks, it is difficult to go back to traditional package management. For developers and sysadmins who manage multiple machines or who value infrastructure-as-code principles in their personal systems, NixOS in 2026 is a serious and viable daily driver choice.

Troubleshooting Common NixOS Issues

NixOS’s declarative model means most problems have clear solutions, but newcomers encounter some predictable stumbling blocks. Here are the most common issues and how to resolve them.

Boot Failures and System Rollback

If your system fails to boot after a nixos-rebuild switch, NixOS’s greatest safety feature activates: the GRUB or systemd-boot menu shows all previous generations, each of which is a complete, bootable system state.

# At the boot menu, select a previous generation
# Once booted into the working generation:

# Check what changed in the broken generation
nix-env --list-generations --profile /nix/var/nix/profiles/system

# Roll back to the previous generation
sudo nix-env --rollback --profile /nix/var/nix/profiles/system

# Or switch to a specific generation
sudo nix-env --switch-generation 42 --profile /nix/var/nix/profiles/system

Enabling Unfree Packages

NixOS blocks installation of packages with non-free licenses by default. This commonly surprises users trying to install NVIDIA drivers, Steam, or Slack:

# In configuration.nix, allow unfree packages globally:
nixpkgs.config.allowUnfree = true;

# Or allow specific packages only (more principled approach):
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
  "nvidia-x11"
  "nvidia-settings"
  "steam"
  "steam-original"
  "slack"
  "vscode"
];

# For NVIDIA drivers, also add:
services.xserver.videoDrivers = [ "nvidia" ];
hardware.nvidia.modesetting.enable = true;

Fixing Missing Firmware and Wi-Fi

# Enable firmware redistribution (required for many Wi-Fi cards)
hardware.enableRedistributableFirmware = true;
hardware.enableAllFirmware = true;

# For Intel Wi-Fi (iwlwifi)
hardware.firmware = [ pkgs.linux-firmware ];

# Check if your Wi-Fi card is recognized
lspci | grep -i wireless
# 03:00.0 Network controller: Intel Corporation Wi-Fi 6 AX200 (rev 1a)

# After rebuild, verify driver loaded
dmesg | grep -i iwlwifi

When You Break the System: Recovery Mode

# If nixos-rebuild fails mid-switch and the system is in a bad state:

# 1. Boot from NixOS ISO in rescue mode
# 2. Mount your partitions:
sudo mount /dev/nvme0n1p2 /mnt
sudo mount /dev/nvme0n1p1 /mnt/boot

# 3. Chroot into your system
sudo nixos-enter --root /mnt

# 4. Fix configuration.nix
nano /etc/nixos/configuration.nix

# 5. Rebuild
nixos-rebuild switch

# 6. Exit and reboot
exit
sudo reboot

Essential NixOS Commands Reference

Here is a quick reference for the commands you will use most often:

# System Management
nixos-rebuild switch          # Apply configuration, switch immediately
nixos-rebuild boot            # Apply on next boot only
nixos-rebuild test            # Apply temporarily (reverts on reboot)
nixos-rebuild dry-build       # Show what would be built, no changes
sudo nix-collect-garbage -d   # Delete old generations and free disk space

# Package Management
nix search nixpkgs packagename    # Search for a package
nix-env -iA nixpkgs.packagename   # Install to user profile (not recommended)
nix shell nixpkgs#packagename     # Temporary shell with package available
nix run nixpkgs#packagename       # Run package without installing

# Flakes
nix flake update              # Update all flake inputs
nix flake show                # Show flake outputs
nix build .#package-name      # Build a specific output

# Debugging
nixos-option services.nginx.enable    # Inspect option values
nix-store --query --references /nix/store/HASH   # Show package dependencies
journalctl -u service-name    # View service logs

Was this article helpful?

Advertisement
🏷️ Tags: declarative linux nix package manager nixos nixos flakes nixos guide
R

About Ramesh Sundararamaiah

Red Hat Certified Architect

Expert in Linux system administration, DevOps automation, and cloud infrastructure. Specializing in Red Hat Enterprise Linux, CentOS, Ubuntu, Docker, Ansible, and enterprise IT solutions.

🐧 Stay Updated with Linux Tips

Get the latest tutorials, news, and guides delivered to your inbox weekly.

Advertisement

Add Comment


↑