Linux Trending Tutorial

NixOS 2026: The Declarative Linux Revolution

πŸ“… Feb 27, 2026 ⏱️ 18 min read 🐧 NixOS 24.11

Imagine installing a Linux system, configuring it perfectly, and then being able to replicate that exact setup on any machine with a single command. No more "works on my machine," no more configuration drift, no more fear of breaking your system with an update. This is the promise of NixOS, and in 2026, it has evolved from a niche curiosity into a legitimate contender for production infrastructure.

NixOS is unlike any other Linux distribution. While traditional distros mutate state over time, NixOS treats your entire operating system as a pure function: input a configuration file, output a working system. This article covers everything you need to know to get started with NixOS in 2026, from basic installation to advanced deployment patterns.

What Makes NixOS Different?

Most Linux distributions manage state imperatively. You install packages with apt or dnf, edit configuration files scattered across /etc, and hope you remember what you changed when something breaks. Over time, this leads to configuration driftβ€”the gradual divergence between your mental model of the system and its actual state.

NixOS inverts this model entirely. Instead of issuing commands that modify state, you declare what you want in a central configuration file:

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

{
  imports = [ ./hardware-configuration.nix ];

  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  networking.hostName = "webserver";
  time.timeZone = "Europe/Berlin";

  users.users.alice = {
    isNormalUser = true;
    extraGroups = [ "wheel" "docker" ];
    packages = with pkgs; [ git vim ];
  };

  services.openssh.enable = true;
  services.nginx = {
    enable = true;
    recommendedGzipSettings = true;
    virtualHosts."example.com" = {
      root = "/var/www";
    };
  };

  system.stateVersion = "24.11";
}

This single file defines users, services, system settings, and installed packages. Run nixos-rebuild switch, and NixOS makes it so. The result is reproducible: give this file to another NixOS installation, and you'll get an identical system.

The Nix Philosophy

Nix (the package manager underlying NixOS) is built on functional programming principles. Packages are built in isolation, with their dependencies explicitly declared. This eliminates "dependency hell" and allows multiple versions of the same package to coexist peacefully.

Installing NixOS in 2026

NixOS provides graphical and minimal ISOs. For servers, the minimal ISO is preferred. Download it, flash to USB, and boot. The installation process differs from traditional Linux installersβ€”you'll write your configuration before the first boot.

Step 1: Partition and Format

Partitioning for UEFI
# Create partitions
parted /dev/nvme0n1 -- mklabel gpt
parted /dev/nvme0n1 -- mkpart primary 512MiB -8GiB
parted /dev/nvme0n1 -- mkpart primary linux-swap -8GiB 100%
parted /dev/nvme0n1 -- mkpart ESP fat32 1MiB 512MiB
parted /dev/nvme0n1 -- set 3 esp on

# Format
mkfs.ext4 -L nixos /dev/nvme0n1p1
mkswap -L swap /dev/nvme0n1p2
mkfs.fat -F 32 -n boot /dev/nvme0n1p3

# Mount
mount /dev/disk/by-label/nixos /mnt
mkdir -p /mnt/boot
mount /dev/disk/by-label/boot /mnt/boot
swapon /dev/nvme0n1p2

Step 2: Generate Configuration

Generate hardware config
nixos-generate-config --root /mnt

This creates /mnt/etc/nixos/configuration.nix and hardware-configuration.nix. The hardware file detects your partitions, filesystems, and kernel modules. You edit configuration.nix to define your system.

Step 3: Install

Install NixOS
nixos-install

After installation, reboot, and you'll have a working NixOS system. But the real power comes from how you manage it going forward.

The Nix Language: A Primer

NixOS configurations are written in the Nix expression language. It's a functional, lazy, dynamically typed language that looks like JSON mixed with Python:

Nix language basics
# Variables
let
  username = "alice";
  packages = [ "git" "vim" "nodejs" ];
in

# Attribute sets (like objects)
{
  user = {
    name = username;
    shell = "/bin/zsh";
  };
  
  # Lists
  services = [ "nginx" "postgresql" "redis" ];
  
  # Functions
  mkUser = name: { inherit name; home = "/home/${name}"; };
  
  # Conditionals
  enableDocker = true;
  packages = if enableDocker then [ "docker" "docker-compose" ] else [ ];
}

The key insight: everything in Nix is an expression that evaluates to a value. There are no statements, no side effects during evaluation. This purity enables the reproducibility that makes NixOS powerful.

Flakes: Modern NixOS Workflow

Introduced as an experimental feature in 2020 and now the standard in 2026, flakes bring structure and composability to Nix. A flake is a flake.nix file that declares inputs (dependencies) and outputs (what your flake provides).

flake.nix
{
  description = "My NixOS Configuration";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    home-manager.url = "github:nix-community/home-manager/release-24.11";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { self, nixpkgs, home-manager, ... }@inputs:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
    in
    {
      nixosConfigurations.webserver = nixpkgs.lib.nixosSystem {
        inherit system;
        specialArgs = { inherit inputs; };
        modules = [
          ./hosts/webserver/configuration.nix
          home-manager.nixosModules.home-manager
        ];
      };
    };
}

Flakes solve several problems: they pin exact dependency versions (via flake.lock), enable easy sharing of configurations, and provide a standard interface for Nix operations.

Flake commands
# Update all inputs
nix flake update

# Update specific input
nix flake lock --update-input nixpkgs

# Build and switch to new configuration
sudo nixos-rebuild switch --flake .#webserver

# Build without switching (test first)
sudo nixos-rebuild build --flake .#webserver

# Switch to previous generation (instant rollback)
sudo nixos-rebuild switch --flake .#webserver --rollback

Declarative User Environments with Home Manager

NixOS configures the system, but what about user-specific dotfiles and applications? Enter Home Manager, a Nix-powered tool that brings the same declarative approach to your home directory.

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

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

  # User packages
  home.packages = with pkgs; [
    firefox
    thunderbird
    obsidian
    slack
  ];

  # Git configuration
  programs.git = {
    enable = true;
    userName = "Alice Developer";
    userEmail = "[email protected]";
    extraConfig = {
      init.defaultBranch = "main";
      push.autoSetupRemote = true;
    };
  };

  # Zsh with plugins
  programs.zsh = {
    enable = true;
    enableCompletion = true;
    autosuggestion.enable = true;
    syntaxHighlighting.enable = true;
    oh-my-zsh = {
      enable = true;
      theme = "robbyrussell";
      plugins = [ "git" "docker" "kubectl" ];
    };
  };

  # Dotfiles as code
  home.file = {
    ".config/kitty/kitty.conf".text = ''
      font_family JetBrains Mono
      font_size 12
      background_opacity 0.95
    '';
  };

  programs.home-manager.enable = true;
}

With Home Manager integrated into your NixOS flake, user environments become reproducible too. New team member? They get your exact shell, editor, and tool configuration by deploying the same flake.

Deploying NixOS at Scale

For managing multiple NixOS machines, several tools have emerged. The most popular in 2026:

Tool Use Case Deployment Model
nixos-anywhere Remote installation Install NixOS over SSH on any Linux system
colmena Multi-host deployment Parallel deployments to many machines
deploy-rs GitOps deployments Profile-based remote activation
agenix Secret management age-encrypted secrets in your repo

Remote Deployment with deploy-rs

flake.nix with deploy-rs
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    deploy-rs.url = "github:serokell/deploy-rs";
  };

  outputs = { self, nixpkgs, deploy-rs, ... }:
    let
      system = "x86_64-linux";
    in
    {
      nixosConfigurations.web-01 = nixpkgs.lib.nixosSystem {
        inherit system;
        modules = [ ./hosts/web-01/configuration.nix ];
      };

      deploy = {
        nodes.web-01 = {
          hostname = "203.0.113.10";
          profiles.system = {
            user = "root";
            path = deploy-rs.lib.${system}.activate.nixos self.nixosConfigurations.web-01;
          };
        };
      };
    };
}
Deploy
# Deploy to web-01
deploy .#web-01

# Deploy with magic rollback on failure
deploy .#web-01 --magic-rollback

Secret Management with agenix

Storing secrets (passwords, API keys, certificates) in your Nix configuration requires care. agenix encrypts secrets with age public keys, storing only ciphertext in your repository. The private keys reside on target machines.

secrets.nix
let
  # Public keys of machines that can decrypt
  web-01 = "age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2el6...";
  web-02 = "age1g5h8l2z4z9w3k2h7j6f9d3s5a8q2w4e6r8t...";
in
{
  "database-password.age".publicKeys = [ web-01 web-02 ];
  "jwt-secret.age".publicKeys = [ web-01 web-02 ];
  "ssl-certificate.age".publicKeys = [ web-01 ];
}
Using secrets in configuration
{ config, pkgs, agenix, ... }:

{
  imports = [ agenix.nixosModules.default ];

  age.secrets.database-password = {
    file = ./secrets/database-password.age;
    owner = "postgres";
    group = "postgres";
  };

  services.postgresql = {
    enable = true;
    initialScript = pkgs.writeText "init-sql" ''
      ALTER USER postgres WITH PASSWORD '$(cat ${config.age.secrets.database-password.path})';
    '';
  };
}

When to Choose NixOS

NixOS isn't for everyone. It has a learning curve, and some workflows feel alien if you're coming from traditional Linux. But it excels in specific scenarios:

NixOS Shines When:

You need reproducible server configurations across dev, staging, and production
You want atomic upgrades with instant rollback capability
You're managing multiple similar machines (home lab, VPS fleet)
You value declarative configuration over imperative commands
You need multiple package versions without conflicts
You want your entire system configuration version-controlled
When to Skip NixOS

NixOS may not be ideal if you need proprietary software with hardcoded paths, rely heavily on dynamically linked binaries without Nix packaging, or want a system that "just works" without learning a new paradigm. Traditional distros are perfectly fine for many use cases.

Common Patterns and Best Practices

Modular Configuration Structure

As your configuration grows, split it into modules:

Directory structure
nixos-config/
β”œβ”€β”€ flake.nix
β”œβ”€β”€ flake.lock
β”œβ”€β”€ hosts/
β”‚   β”œβ”€β”€ webserver/
β”‚   β”‚   β”œβ”€β”€ configuration.nix
β”‚   β”‚   └── hardware-configuration.nix
β”‚   └── laptop/
β”‚       β”œβ”€β”€ configuration.nix
β”‚       └── hardware-configuration.nix
β”œβ”€β”€ modules/
β”‚   β”œβ”€β”€ base.nix           # Common settings for all hosts
β”‚   β”œβ”€β”€ desktop.nix        # GUI applications
β”‚   β”œβ”€β”€ development.nix    # Dev tools
β”‚   β”œβ”€β”€ server.nix         # Server services
β”‚   └── security.nix       # Hardening
└── home/
    └── alice.nix          # Home manager config

Handling Imperative State

Some things can't be fully declarative: database data, uploaded files, SSL certificates from ACME. Use systemd.tmpfiles.rules for directories and handle backups separately.

Managing stateful directories
{
  # Create persistent directories
  systemd.tmpfiles.rules = [
    "d /var/lib/myapp 0755 myapp myapp -"
    "d /var/www/uploads 0755 nginx nginx -"
  ];

  # Automated backups with borgmatic
  services.borgmatic.enable = true;
  services.borgmatic.configurations.main = {
    source_directories = [ "/var/lib/myapp" "/var/www/uploads" ];
    repositories = [ "ssh://[email protected]/./backups/webserver" ];
    keep_daily = 7;
    keep_weekly = 4;
    keep_monthly = 6;
  };
}

2026 NixOS Ecosystem Highlights

The Nix ecosystem has matured significantly. Notable developments:

Getting Started: Your First Hour

The fastest way to evaluate NixOS without commitment:

Try NixOS in a VM
# Install the Nix package manager on any Linux
$ curl -L https://nixos.org/nix/install | sh

# Run a NixOS container
$ nix run github:NixOS/nixpkgs#nixos-container

# Or use the official VM image
$ qemu-system-x86_64 -enable-kvm -m 4G -cdrom nixos-minimal-24.11.iso

For a permanent installation, start with a simple configuration and add complexity incrementally. The NixOS manual is excellent, and the community Matrix/Discord channels are welcoming to newcomers.

Conclusion

NixOS represents a fundamental shift in how we think about operating system management. By treating configuration as code and systems as pure functions, it eliminates entire categories of problems that plague traditional Linux administration.

The learning curve is realβ€”expect to spend time understanding the Nix language and unlearning habits from imperative systems. But for those who invest the effort, NixOS offers something unique: a Linux distribution that behaves predictably, rolls back gracefully, and deploys reproducibly.

In 2026, with flakes stabilized, deployment tools mature, and the package repository larger than ever, NixOS has transitioned from experimental to production-ready. Whether you're managing a home lab or a cloud fleet, it's worth serious consideration.

Need Help With NixOS?

Our team designs and manages NixOS infrastructure for companies across Europe. From initial migration to ongoing operations, we can help.

Discuss Your Project