This guide is generated by ChatGPT.
Comprehensive Guide to Learning NixOS for Daily Use
Switching from Arch (EndeavourOS) to NixOS can be a rewarding experience, offering declarative configuration, rollback features, and powerful package management. However, NixOS comes with a steep learning curve, especially with new concepts like Flakes and Home Manager. This guide will take you step-by-step through everything you need to learn and understand in order to confidently use NixOS as your daily driver without getting stuck.
1. Introduction to NixOS
NixOS is a Linux distribution built around the Nix package manager, which allows declarative configuration and reliable upgrades. Unlike Arch, which emphasizes manual, user-driven configuration, NixOS manages your entire system through configuration files. The core idea is that everything on your system can be defined, reproduced, and rolled back using Nix.
In NixOS, the entire system (from installed packages to services and settings) is described in a set of configuration files, with the most important being configuration.nix
. This file dictates how your system is built, what packages are installed, and how services run. You’ll never need to worry about manually managing packages or configuration drift because the system itself can be “rebuilt” at any time from this file.
2. Key Concepts in NixOS
2.1 Declarative Configuration
In NixOS, instead of manually installing packages or configuring services, you declare everything in configuration files. This has several advantages:
- Reproducibility: You can reproduce your entire system on a new machine or after a fresh install simply by copying your configuration.
- Rollback: NixOS tracks every system change, so you can easily roll back to a previous state.
- Atomic upgrades: You can upgrade your system without fear of breaking things—if something goes wrong, just roll back.
2.2 The Nix Package Manager
At the heart of NixOS is the Nix package manager, which allows you to install packages in a way that avoids dependency hell. Nix achieves this by isolating each package and its dependencies, unlike traditional package managers (e.g., pacman in Arch), which install everything globally.
2.3 Nix Store and Derivations
- Nix Store: The
/nix/store
is where Nix installs all packages and system components, each stored in a unique directory identified by a hash. This ensures that multiple versions of the same software can coexist. - Derivations: A derivation is the build recipe used by Nix to create a package. These recipes specify dependencies, build steps, and configuration options.
3. Installation Process
3.1 Pre-installation Steps
Before you begin the installation, back up your important files and consider setting up a virtual machine to experiment with NixOS. Make sure you have access to another device or guide to reference during installation.
3.2 NixOS Installation
The NixOS installation process differs from Arch, as it is less manual but more declarative. The key steps are:
- Partitioning and Formatting: Use tools like
fdisk
orparted
to create the partitions. - Mounting the Filesystems: Mount the root and boot partitions.
- Generate Configuration: Run
nixos-generate-config
to create the basic system configuration. - Edit Configuration: Open
/mnt/etc/nixos/configuration.nix
to edit system settings, add users, define services, and specify packages. - Install: Run
nixos-install
, which uses yourconfiguration.nix
to set up the system. - Bootloader: NixOS will automatically configure your bootloader (GRUB) during installation.
3.3 Configuring the System (/etc/nixos/configuration.nix
)
This file is the heart of your system. By editing this, you can control the packages, services, and system settings. Key sections include:
environment.systemPackages
: Define all the packages you want installed.services
: Enable or disable system services.users.users
: Define user accounts and permissions.
3.4 Managing Disk Partitions
Make sure to have separate partitions for:
/boot
(important for UEFI systems)/
(root filesystem)- Optionally,
/home
3.5 UEFI and BIOS Booting
NixOS supports both UEFI and BIOS booting. For UEFI systems, ensure that the boot.loader.systemd-boot.enable
option is set to true
in your configuration.
4. Nix Package Manager Deep Dive
4.1 Installing and Removing Packages
Unlike Arch, where you use pacman
, in NixOS you use nix-env
or add packages to the environment.systemPackages
in configuration.nix
.
- Installing a package:
nix-env -iA nixpkgs.packageName
- Removing a package:
nix-env -e packageName
4.2 Searching for Packages
To search for a package, use:
nix-env -qaP | grep searchTerm
Alternatively, you can browse the official Nix Packages website.
4.3 Channels and How They Work
NixOS uses “channels” to track versions of the Nix Packages collection. Think of channels like Arch’s stable
and testing
repositories. The two main NixOS channels are:
- nixos-stable: The stable release.
- nixos-unstable: The bleeding-edge development channel.
To switch channels:
sudo nix-channel --add https://nixos.org/channels/nixos-unstable nixos
sudo nix-channel --update
4.4 Understanding Profiles
Every time you change the system state, NixOS creates a new “generation.” You can roll back to any previous generation if something breaks. To list generations:
nix-env --list-generations
To roll back:
sudo nix-env --rollback
5. Working with System Configurations
5.1 Rebuilds and Rollbacks (nixos-rebuild
)
nixos-rebuild
is the primary command for applying changes to your configuration:
sudo nixos-rebuild switch
If something goes wrong, simply reboot and select a previous generation from the boot menu.
5.2 Pinning Package Versions
If you need to stick to a particular version of a package, you can pin it by using overlays or directly specifying the version in configuration.nix
.
5.3 Managing Configuration Files
In NixOS, configuration files like configuration.nix
control every aspect of the system. Regularly edit this file to add or remove packages, enable or disable services, and modify system settings.
5.4 Using nix-shell
for Development Environments
nix-shell
allows you to create development environments on the fly, without permanently installing dependencies:
nix-shell -p packageName
This is particularly useful for isolated development setups.
6. Home Manager
6.1 Overview and Installation
Home Manager allows you to manage user-specific configurations declaratively. It’s perfect for managing your shell, editor, or even applications like Firefox.
To install Home Manager:
nix-channel --add https://github.com/nix-community/home-manager/archive/release-21.11.tar.gz home-manager
nix-channel --update
6.2 Home Manager Configuration
Home Manager has its own configuration file (home.nix
). You can configure everything from your terminal prompt to your GTK theme.
6.3 Using Home Manager with System Nix Configurations
Home Manager can work in conjunction with your system-wide NixOS configuration. This is particularly useful if you want to manage user-specific settings without modifying the system’s global configuration (/etc/nixos/configuration.nix
).
There are two ways to integrate Home Manager:
- Standalone Home Manager: This is the default setup, where Home Manager operates separately from your NixOS system configurations. You’ll use
home-manager switch
to apply user-level configurations. - Integrated into
configuration.nix
: This method integrates Home Manager into your system-level configuration, allowing you to rebuild both the system and user environments together usingnixos-rebuild switch
.
To integrate Home Manager with NixOS, you need to import Home Manager in configuration.nix
:
{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
(import <home-manager/nixos>)
];
home-manager.users.yourusername = {
programs.zsh.enable = true;
programs.zsh.promptInit = "powerlevel10k";
# Define more user-specific settings here
};
}
After making these changes, you can apply both system and user configurations using:
sudo nixos-rebuild switch
6.4 Configuring User-Specific Settings (Shells, Fonts, etc.)
Home Manager gives you full control over your user environment. You can configure everything from your default shell to individual application settings. Here are a few common configuration examples:
-
Changing your default shell:
programs.zsh.enable = true; programs.zsh.promptInit = "powerlevel10k";
-
Setting up a custom terminal:
programs.alacritty.enable = true;
-
Managing dotfiles: Home Manager can manage your dotfiles declaratively. For instance, you can store your
zshrc
inhome.nix
like this:programs.zsh = { enable = true; oh-my-zsh = { enable = true; plugins = ["git" "zsh-syntax-highlighting"]; }; dotfiles = { ".zshrc" = '' export PATH=$PATH:/some/custom/path alias ll='ls -la' ''; }; };
-
Setting fonts:
fonts = { enable = true; fontconfig = { enable = true; fonts = with pkgs; [ dejavu_fonts noto-fonts ]; }; };
You can even install desktop environments and customize them through Home Manager. For instance, to install i3wm:
services.xserver = {
enable = true;
windowManager.i3.enable = true;
windowManager.i3.config = {
workspaceNames = [ "1: term" "2: web" "3: code" ];
};
};
7. Flakes: The Future of NixOS
Flakes are a relatively new addition to the Nix ecosystem, designed to improve reproducibility and modularity in Nix configurations. While still experimental, Flakes are rapidly becoming the preferred way to manage Nix projects and system configurations.
7.1 Introduction to Flakes
At their core, Flakes are a more structured way to define Nix environments. They introduce a standardized project structure and allow for more consistent, reproducible builds.
- Inputs: These are dependencies that a flake relies on, like Nixpkgs or other flakes.
- Outputs: These define what the flake produces, such as packages, configurations, and environments.
Flakes are especially powerful when combined with Home Manager, system configurations, and development environments.
7.2 Setting Up Flakes
To start using Flakes, first enable them by adding the following to your /etc/nixos/configuration.nix
:
{
nix = {
package = pkgs.nixUnstable;
extraOptions = ''
experimental-features = nix-command flakes
'';
};
}
You can now use Flake commands such as:
nix flake init
This will create a basic flake.nix
file, which defines your inputs (dependencies) and outputs (packages, environments, etc.). Here’s an example of a simple flake.nix
:
{
description = "My NixOS configuration";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11";
inputs.home-manager.url = "github:nix-community/home-manager/release-21.11";
outputs = { nixpkgs, home-manager, ... }:
let
system = "x86_64-linux";
in {
nixosConfigurations.mySystem = nixpkgs.lib.nixosSystem {
system = system;
modules = [
./configuration.nix
home-manager.nixosModules.home-manager
];
};
};
}
7.3 Flake Inputs, Outputs, and Commands
-
Inputs: These are the building blocks of Flakes. They can point to Git repositories, Nix channels, or other Flakes.
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
-
Outputs: This is where you define what your Flake produces. You can define NixOS configurations, Home Manager configurations, packages, and more.
outputs = { nixpkgs, ... }: { nixosConfigurations.myConfig = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./configuration.nix ]; }; };
-
Commands: Flakes introduce new commands, such as:
nix flake update
: Update all the inputs in your Flake.nix flake check
: Verify that your Flake is valid and up-to-date.
7.4 Integrating Flakes with Home Manager and System Config
One of the most powerful features of Flakes is the ability to integrate both system-wide and user-specific configurations into a single Flake. Here’s an example Flake that integrates both:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
};
outputs = { nixpkgs, home-manager, ... }:
let
system = "x86_64-linux";
in {
nixosConfigurations.mySystem = nixpkgs.lib.nixosSystem {
system = system;
modules = [
./configuration.nix
home-manager.nixosModules.home-manager
];
};
homeManagerConfigurations.myUser = home-manager.lib.homeManagerConfiguration {
system = system;
userName = "myUser";
homeDirectory = "/home/myUser";
configuration = { config, pkgs, ... }: {
programs.zsh.enable = true;
};
};
};
}
8. Common NixOS Workflows
8.1 System Upgrades and Channel Management
Upgrading your system in NixOS is as simple as:
sudo nixos-rebuild switch --upgrade
This pulls the latest packages from the channels you’ve defined in /etc/nixos/configuration.nix
. You can also pin specific versions of Nixpkgs by setting:
nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11";
8.2 Creating and Managing Custom Packages
One of the strengths of NixOS is the ease of creating custom packages. Here’s a minimal example of how you can create your own Nix package:
{ stdenv, fetchurl }:
stdenv.mkDerivation {
name = "my-package-1.0";
src = fetchurl {
url = "https://example.com/my-package.tar.gz";
sha256 = "0l5zii9npp5fv4yhm2vbn7r1h5m7zsy5h3vzwid9qz7rszshp5mq";
};
buildInputs = [ ];
installPhase = ''
mkdir -p $out/bin
cp my-binary $out/bin/
'';
}
To use this, you can include it in your configuration.nix
or Flake.
8.3 Using Overlays for Customization
Overlays allow you to override or add new packages to Nixpkgs. For example, to replace the version of firefox
in your system:
{
nixpkgs.overlays = [
(self: super: {
firefox = super.firefox.overrideAttrs (oldAttrs: {
version = "95.0";
src = super.fetchurl {
url = "https://example.com/firefox-95.0.tar.bz2";
sha256 = "...";
};
});
})
];
}
8.4 Handling External and Non-NixOS Packages
For packages that aren’t available in Nixpkgs, you can use buildFHSUserEnv
to create a traditional FHS (Filesystem Hierarchy Standard)
environment:
pkgs.buildFHSUserEnv {
name = "steam-env";
targetPkgs = pkgs: [ pkgs.steam ];
}
This helps in cases where software requires a traditional Linux environment.
9. Backups and Rollbacks
One of the best features of NixOS is its rollback capability. Every time you run nixos-rebuild switch
, NixOS creates a new generation (system snapshot). You can roll back to a previous generation by selecting it from the bootloader.
Alternatively, you can roll back using:
sudo nixos-rebuild switch --rollback
For more advanced backups, consider using tools like restic
or borg
alongside NixOS.
10. Advanced Topics: Declarative Containers and Virtual Machines
NixOS supports declarative container and VM creation, which is incredibly useful for testing environments or isolating applications.
10.1 Declarative Containers
NixOS allows you to define containers in configuration.nix
:
containers.myContainer = {
autoStart = true;
config = { config, pkgs, ... }: {
services.nginx.enable = true;
};
};
Start the container with:
sudo nixos-rebuild switch
10.2 Using Virtual Machines
You can also define virtual machines declaratively:
virtualisation.libvirtd.enable = true;
virtualisation.qemu = {
enable = true;
memory = 1024; # Set memory for the VM
};
This is a great way to test NixOS configurations without affecting your primary system.
Conclusion
By now, you should have a solid understanding of NixOS, its core concepts, and how to manage both system-level and user-level configurations using tools like Home Manager and Flakes. Mastering NixOS requires hands-on experimentation, and the more you customize, the more comfortable you’ll become.
In summary, here are the key areas to focus on for daily driving NixOS:
- Understand the declarative nature of NixOS: Learn how
configuration.nix
works. - Master package management: Know how to install, update, and rollback packages.
- Learn Home Manager: It’s essential for managing your user environment.
- Explore Flakes: They’re the future of NixOS configuration management.
- Get comfortable with backups and rollbacks: These are lifesavers during system upgrades or mistakes.
With time and practice, you’ll find that NixOS offers an unparalleled level of flexibility and stability for a daily driver system.
Happy hacking!