Part 4: Your First NixOS Configuration
You know the language. Now it is time to write the blueprint.
In this part, we are going to edit /etc/nixos/configuration.nix to set up a functional, daily-driver system. We will define your user, your core tools, and—crucially—prepare the system for the modern "Flakes" workflow we will adopt in the next article.
Open your configuration file:
sudo nvim /etc/nixos/configuration.nix
The bootloader & networking
At the top of the file, you will see the bootloader settings. The installer usually gets this right, but it's good to verify.
{ config, pkgs, ... }:
{
imports = [ ./hardware-configuration.nix ];
# Use systemd-boot (Modern, fast, works great with UEFI)
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# Networking
networking.hostName = "nixos"; # Define your computer's name
networking.networkmanager.enable = true; # Use the standard NetworkManager
}
Pragmatic Tip: Do not mess with manual networking.wireless configurations unless you are setting up a headless server. networkmanager gives you the nmcli tool and the GUI applet you are used to on Ubuntu/Fedora. It just works.
User management
NixOS forces you to declare your user explicitly. Warning: If you delete this block and rebuild, you literally lock yourself out of the system.
users.users.oliviero = {
isNormalUser = true;
description = "Oliviero Taleghani";
# "wheel" allows 'sudo', "networkmanager" allows using the wifi GUI
extraGroups = [ "networkmanager" "wheel" "audio" ];
shell = pkgs.zsh; # We will enable ZSH in Section 6
};
The "allow unfree" switch
This is the first "Gotcha" for new users. By default, NixOS follows the Free Software Foundation's philosophy strictly. It will refuse to install proprietary software like Steam, Spotify, Discord, or NVIDIA drivers.
You probably want these. Add this line:
nixpkgs.config.allowUnfree = true;
System packages vs. project tools
This is where our "Pragmatic" philosophy kicks in. In environment.systemPackages, we only want utilities that are useful globally. We do NOT want specific language versions (like Node.js v18 or Python 3.11) here, because those belong in project folders (which we will cover in the next parts).
Add your core survival tools:
environment.systemPackages = with pkgs; [
# Editors
neovim
git
# Utilities
wget
curl
unzip
ripgrep # A faster grep
fzf # Fuzzy finder
btop # System monitor
# Terminal
tmux
];
Enabling the future
We are going to migrate to Nix Flakes in the next few articles. To do that, we need to tell the current Nix installation that it is allowed to use them (since they are technically still "experimental").
Add this block now. It is essential for the rest of this series:
nix.settings.experimental-features = [ "nix-command" "flakes" ];
The programs block
Some complex programs need more than just "installing"—they need system-level configuration (setting up /etc/ files, environment variables, etc.).
For example, just adding pkgs.zsh to packages isn't enough; you need to tell NixOS to configure the shell environment.
# Enable ZSH (so our user shell defined above actually works)
programs.zsh.enable = true;
# Example: Enable Hyprland (only if you want a tiling window manager)
# programs.hyprland.enable = true;
The trap: system.stateVersion
Scroll to the bottom of the file. You will see something like system.stateVersion = "24.11";. This is the most misunderstood line in NixOS.
1. What you think it does: "This sets my OS version. If I want to upgrade to the next release, I change this number."
2. What it actually does: It tells NixOS: "I was originally installed as version 24.11, so please keep my database locations and config defaults compatible with 24.11."
It exists to prevent data corruption. If PostgreSQL changes its default data directory in the next version, NixOS checks this number. If it sees the old version, it uses the old paths so you don't lose your data.
When should you change it?
Almost never.
Even if you upgrade your entire system to a new release, you should leave system.stateVersion exactly as it is. You only change it if you are formatting the disk and doing a fresh install.
# Do not change this unless you know what you are doing!
system.stateVersion = "24.11";
The feedback loop
Now that you have edited the file, save it. It is time to run the magic command:
sudo nixos-rebuild switch
What just happened?
- Parsing: Nix read your file and checked for syntax errors (did you miss a semicolon?).
- Fetching: It downloaded Zsh, Btop, and their dependencies.
- Building: It constructed a new system environment.
- Switching: It atomically swapped the symlinks.
If the command finished without red text, congratulations. You have successfully configured NixOS.
You unlocked a side quest: check out SQ Understanding Derivations to understand what derivations actually are and how the are used as the building block of NixOS.
Next step: 05 Basic commands
Previous step: 03 Nix Language
Go back to the index: Nixology