NixOS my new linux distro

Posted in linux on June 1, 2025 by Adrian Wyssmann ‐ 6 min read

Reason for NixOs

Some months ago I got a new Notebook and took the chance to checkout NixOS. I used Archlinux for many years and was very happe. However as DevOps/Platform Engineer I am used to make things reproducible - I use(d) Ansible and Terraform which allows me to create repoducible environments. I even [used Ansible][https://gitlab.com/papanito/devenv] for some aspcets. Then I stumbled upon NixOs which states

Declarative builds and deployments. Nix is a tool that takes a unique approach to package management and system configuration. Learn how to make reproducible, declarative and reliable systems.

Sounds amazing, so let’s give it a try

What is Nix

Nix is actually 3 things

  • A language or better an expression language

    The Nix language is designed for conveniently creating and composing derivations – precise descriptions of how contents of existing files are used to derive new files.

  • A package manager

    Nix is a powerful package manager for Linux and other Unix systems that makes package management reliable and reproducible.

    It offer the lagrest seletion of packages with over 120000 packages and can be used independently on other Linux distributions and macOS.

  • An operating system

A quick intro to NixOS

Instead of manually installing and configuring software, you define your entire system (packages, services, users, etc.) in a single configuration file (/nixos/configuration.nix). This allows you to

  • Reproduce your system on another machine
  • Roll back to previous configurations
  • Share setups with others

Every change to the system (like installing a package or updating the OS) is atomic. If something goes wrong, you can roll back to a previous working state with a simple reboot or command. a

# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).
{ config, pkgs, ... }:

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

  # Omit previous configuration settings...

  # Add user 'ryan'
  users.users.ryan = {
    isNormalUser = true;
    description = "ryan";
    extraGroups = [ "networkmanager" "wheel" ];
    openssh.authorizedKeys.keys = [
        # Replace with your own public key
        "ssh-ed25519 <some-public-key> ryan@ryan-pc"
    ];
    packages = with pkgs; [
      firefox
    #  thunderbird
    ];
  };

  # Enable the OpenSSH daemon.
  services.openssh = {
    enable = true;
    settings = {
      X11Forwarding = true;
      PermitRootLogin = "no"; # disable root login
      PasswordAuthentication = false; # disable password login
    };
    openFirewall = true;
  };

  # Omit the rest of the configuration...
}

As you can see it also imports a file called hardware-configuration.nix, a file that contains hardware-specific settings. It is automatically generated by nixos-generate-config. It’s a crucial part of the system configuration, providing details about your hardware, such as the kernel, modules, and systemd settings. You typically don’t edit this file directly; it’s meant to be automatically generated and updated as needed. Usually, when you install NixOS for the first time both files are present on the system.

Channels

One important element is nix-channels, the git repository containing all packages and NixOS modules/expressions.

A “channel” is a name for the latest “verified” git commits in Nixpkgs. Each channel has a different definition of what “verified” means. Each time a new git commit is verified, the channel declaring this verification gets updated. Contrary to a user of the git master branch, a channel user will benefit from both verified commits and binary packages from the binary cache. This is what traditionally provides in the Nix language.

Channels can be broadly categorized into stable and unstable channels, and large and small channels. Channels are managed at user-level:

NixOS uses the channels set for the root user to update the system-wide configuration; channels set for other users control only the user environment for that user.

So you add a channel with

nix-channel --add https://nixos.org/channels/channel-name nixos

Organize and apply config

Despide you have a configuration.nix it is best, you split your config in different files, which makes it much more easy to handle. I for instance in my nixos-configuration split it in different modules, so I have the following import statement:

  imports = [
    ./common
    ./modules
  ];

While modules has multiple files

  • cloud.nix
  • container.nix
  • default.nix
  • development.nix
  • fonts.nix …

Important is the defaults.nix which ensures, that when you import a folder, all .nix-files are read:


{ lib, config, pkgs, ... }:
{
  imports = [
    ./cloud.nix
    ./container.nix
    ./development.nix
    ./fonts.nix
    ./fun.nix
    ./kde.nix
    ./gnome.nix
    ./multimedia.nix
    ./office.nix
    ./solokey.nix
    ./printing.nix
    ./security.nix
    ./virt.nix
    ./wine.nix
  ];
}

To apply your configuration you run sudo nixos-rebuild switch while the switch ensures the configuration is switched. You always can rollback with sudo nixos-rebuild --rollback or select a previous configuration from the boot menu when you restart your computer. For more details check Nixos-rebuild.

Flakes

Despite marked as experimental feature, flakes is a major development for Nix and indeed widely embraced.

Important

However, it’s important to note that Flakes is still an experimental feature. Some issues persist, and there is a possibility of introducing breaking changes during the stabilization process. The extent of these breaking changes remains uncertain.

Flakes similar something similar like package.json, to describe the dependencies between Nix packages and how to build projects. It introduce flake.nix, as well as flake.lock, akin to package-lock.json, to lock the versions of dependencies, ensuring project reproducibility.

{
  description = "A simple NixOS flake";

  inputs = {
    # NixOS official package source, here using the nixos-25.05 branch
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
  };

  outputs = { self, nixpkgs, ... }@inputs: {
    # The host with the hostname `my-nixos` will use this configuration
    nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ./configuration.nix
      ];
    };
  };
}

The flake.nix has to elements

  • inputs: defines all the dependencies of this flake, most commonly the nixpkgs (instead of the channels on user-level). There can be multiple inputs, incl. other flakes. -outputs: It is a function that takes the dependencies from inputs as its parameters, and its return value is an attribute set, which represents the build results of the flake

To apply the configuration, the command is slighty different to the one when using no flakes:

sudo nixos-rebuild switch --flake /path/to/your/flake#your-hostname

For more details on flakes checkout

What else is there?

There are some interesting other elements to nix worth mentioning:

  • nix-shell: It creates a temporary shell environment, with specific nix packages. The same can be achieved with the new cli running nix shell
  • nix run: creates an environment with the specified Nix package and directly runs that package within the environment (without installing it into the system environment)
  • nix-env: nix-env is a core command-line tool for classic Nix used to manage software packages in the user environment. The command is used to manipulate Nix user environments, in other words to manage software packages in the user environment. Packages installed with nix-env are not automatically recorded in Nix’s declarative configuration and are completely independent of its control, making them challenging to reproduce on other machines. Upgrading packages installed by nix-env is slow and may produce unexpected results because the attribute name where the package was found in nixpkgs is not saved.

Further reading

There is much more amazing things, so I recommend to checkout Introduction to Nix & NixOS for a more detailed introduction to NixOS.