Reliable and reproducible Linux installation with NixOS

NixOS is a Linux distribution that provides reliability and makes it easy to reproduce system states. We introduce with Nix and deploying NixOS on your machine to start Python full stack development course.


Let’s talk about how NixOS works, how to get and install it, and how Nix provides reliability. Your machine will boot up with a running NixOS system, and you will learn how NixOS, the Nix package manager, and the Home Manager interact.

What is NixOS?

NixOS is a Linux distribution based on Nix, a functional package manager whose language is inspired by functional programming. NixOS takes the power of the Nix package manager and applies it to the entire system. This means that, among other things, it allows you to easily return all system settings to a previous state. In addition to the system running NixOS, Home Manager controls the user environment.

Why NixOS?

NixOS applies the basic principles of Nix to the entire system. It means:

  • System reproducibility. Depending on the system specification (in the NixOS configuration file), it is possible to replay the entire system (except mutable state: database contents, etc.) on another machine.

  • Atomic updates and rollbacks. Changes at the system or package level are always reversible.

  • Dependency management. NixOS uses the Nix package management system. Nix makes sure that dependency declarations are made when a package is installed. Because Nix stores packages in isolation from each other, multiple versions of the same package are allowed on the same machine. Thus, different packages may use different versions of the same dependency. This dependency management does not lead to gigantic applications, as Flatpack does.

Installing NixOS

The installation process is demonstrated on a Dell Precision 5520 laptop with a 1TB solid state drive (SSD) and 32GB of RAM. The instructions below apply to any machine, be it a development PC, a laptop, or a virtual machine.

Obtaining the NixOS ISO Image

NixOS ISO image can be downloaded from the page downloads NixOS. This file is available in two versions:

  • A graphical ISO image is the easiest option. With this image, installation is much easier, since it comes with the necessary and completely ready-made graphical interface and network connection.

  • Minimalistic in content and non-graphical ISO image. The advantage is the smaller file size. But its disadvantage is that the file requires preparation before installation. Read more about at the construction site network connection in the installer.

To download the necessary dependencies, you must set up a network connection before starting the installation.

I’m installing a graphical ISO image from environment Gnome desktop. The file size is relatively small – about 2 GB.

Installer download

An .iso disk image is used to create a bootable USB device. The creation process is described in official documentation for NixOS. You can read Ubuntu documentation – it explains how to use balenaEtcher make downloading more convenient for the user.

When finished, reboot your machine and run the file from the UBS device. A graphical interface will appear on the screen through which the installation and configuration of NixOS will be carried out. The first screen offers several installer options. Choose the first one. In a few seconds, you have Gnome already up and running from your USB system. Open a new terminal.

Partitioning

The NixOS installer does not partition or format. The user is responsible for this. To perform this operation, you need to know the name of the hard disk. The command below will let you know how to access the hard disk:

lsblk -p

In our case, the name of the hard disk is /dev/nvme0n1. But for different types of disk (SATA, SSD, NVMe, etc.), the values ​​\u200b\u200bmay differ (for example, /dev/sda). The following commands in the article are run on a drive named /dev/nvme0n1.

Having dealt with the name of the disk, you can proceed to creating partitions. In our example, one partition is entirely dedicated to the operating system. Hibernation saves on reboot condition system on disk to the swap partition (or swap area). So we need to create chapter swap. It is not recommended to enable hibernation on a system with large RAM resources (for example, a server). If you decide to enable hibernation, then set the swap size to 1.5 times the amount of RAM.

The UEFI partitioning scheme is taken as the boot method. The swap partition uses 50 GB. For clarity, the MBR (Master Boot Record) partitioning scheme is also presented.

In a terminal, login as root with sudo su –. Both fdisk and Parted are equally suitable for creating a disk partition.

# Enter fdisk
fdisk /dev/nvme0n1
# Partition 1
g # Create a new empty GTP partition table
n # Create a new partition
1 # First partition
(default) # First sector
+512M # 512 MB
t # Change the partition type
1 # Select the first partition
1 # Use EFI System Partition, or ESP.
# Partition 2
n # Create a new partition
2 # Second partition
(default) # First sector start at the end of first partition
-50G # All disk minus 50G for swap
# Partition 3
n # Create a new partition
3 # Third partition
(default) # First sector start at the end of second partition
(default) # Last sector is the end of the disk
t # Change the partition type
3 # Select the third partition
19 # Use Linux swap
# Finalize
v # Check the settings
w # Write and quit
parted /dev/nvme0n1 -- mklabel msdos
parted /dev/nvme0n1 -- mkpart primary 1MiB -50GiB
parted /dev/nvme0n1 -- mkpart primary linux-swap -50GiB 100%

Formatting

To refresh our memory, our article installs NixOS on the /dev/nvme0n1 disk. /dev/nvme0n1p2 is the root partition of the Linux system and /dev/nvme0n1p3 is the swap partition.

The purpose of this step is to format the partitions, activate the swap partition, and build the target file system for installing NixOS. Below are the commands for UEFI and MBR (Legacy) boot modes.

# Disk format
mkfs.ext4 -L nixos /dev/nvme0n1p2
mkswap -L swap /dev/nvme0n1p3
mkfs.fat -F 32 -n boot /dev/nvme0n1p1
# System mount
mount /dev/disk/by-label/nixos /mnt
swapon /dev/nvme0n1p3
mkdir -p /mnt/boot
mount /dev/disk/by-label/boot /mnt/boot
mkfs.ext4 -L nixos /dev/nvme0n1p1
mkswap -L swap /dev/nvme0n1p2
mount /dev/disk/by-label/nixos /mnt
swapon /dev/nvme0n1p2
nixos-generate-config --root /mnt

Configuring NixOS

Installation is done through the NixOS configuration file in /mnt/etc/nixos/configuration.nix. To generate a configuration file and open it for editing, run the following code:

nixos-generate-config --root /mnt
nano /mnt/etc/nixos/configuration.nix

According to the philosophy of NixOS, the configuration file should reflect all information about the system. This includes information about packages being installed, services being started, settings applied, network configurations, and more. To quickly understand everything, we will write down the minimum configuration and execute it after the system reboots. It is recommended to commit this configuration in the future. Then, when installing on a new machine, it will be possible to clone the configuration and reuse it (in whole or in part) on a new environment.

The minimal NixOS configuration file for the Gnome desktop environment with UEFI boot mode is shown below. If you want to start with a more complex system, then add additional properties to the configuration file or use the detailed file that can be found at the end of the article:

{ config, pkgs, ... }:

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

  # Use the systemd-boot EFI boot loader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  
  # The global useDHCP flag is deprecated, therefore explicitly set to false here.
  # Per-interface useDHCP will be mandatory in the future, so this generated config
  # replicates the default behaviour.
  networking.useDHCP = false;
  networking.interfaces.wlp2s0.useDHCP = true;
  networking.networkmanager.enable = true;

  # Enable the X11 windowing system.
  services.xserver.enable = true;

  # Enable the GNOME Desktop Environment.
  services.xserver.displayManager.gdm.enable = true;
  services.xserver.desktopManager.gnome.enable = true;
  
  # Configure keymap in X11
  services.xserver.layout = "fr";

  # Enable sound.
  sound.enable = true;
  hardware.pulseaudio.enable = true;

  # Enable touchpad support (enabled default in most desktopManager).
  services.xserver.libinput.enable = true;

  # Define a user account. 
  # Don't forget to set a password with ‘passwd’ using the root account if you don't use the initialPassword field.
  users.users.florent = {
    isNormalUser = true;
    initialPassword = "secret";  # Define the user initial password
    extraGroups = [ "wheel" ]; # wheel to enable ‘sudo’ for the user.
  };

  # List packages installed in system profile.
  # To search, run: `nix search wget`
  environment.systemPackages = with pkgs; [
    vim
  ];

  # Enable the OpenSSH daemon.
  services.openssh.enable = true;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "21.05"; # Did you read the comment?
}

Installation

This is the last step before rebooting the system. An internet connection is required to download dependencies. Installation comes down to performing the configuration that was prescribed above. Command to run the installation:

nixos-install

You will need to enter the root user password, after which the system is ready to reboot.

Changing the NixOS configuration

The working system begins to be supplemented to suit your needs. New tools are installed, services are started, and the configuration is updated. This is part of the life cycle of any system, be it a development computer or a production server.

The NixOS configuration file reflects system-level settings, such settings apply to all users of a particular machine. In addition, the Home manager works at the user level, installing applications and configuration for an individual user.

The curl package at the system level is added via the following configuration:

{ config, pkgs, ... }:

{
  ...
  environment.systemPackages = with pkgs; [
    vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
    curl
  ];
  ...
}

Any change to the NixOS configuration file creates a new bootstrap configuration. The commands below create the configuration declared in the NixOS configuration file and make it the default for bootstrap:

nixos-rebuild switch

With each use of the nixos-rebuild switch command at operating system startup, a new boot configuration appears. The following is an example of a reload window:

The command to list the NixOS boot configurations is:

sudo nix-env -p /nix/var/nix/profiles/system --list-generations

IN leadership on Nix you can find the most popular commands.

What is Home Manager?

Home Manager is a tool for managing the user environment through the Nix package manager. Thus, it complements NixOS. There are 2 options for working with Home Manager:

This method allows you to manage the user’s home directory independently of the overall system. You need to maintain 2 configuration files: one for system-level configuration (/etc/nixos/configuration.nix) and one for user-level configuration (~/config/nixpkgs/home.nix). The former requires root privileges, while the latter is run by a user without sudoers permissions.

This way you can manage system and user level configuration in one file (/etc/nixos/configuration.nix). Root rights are required to apply Home Manager updates.

I find it easier to maintain system configuration in a single file. After all, I’m the only one working on my dev computer.

Let’s look at installing Home Manager as a module inside the NixOS system configuration below.

Home Manager as a NixOS Module

Installing Home manager as a NixOS module requires superuser (root) privileges. In a terminal, login as root with sudo su -. Then follow this guide to set up Home Manager:

nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
# If you follow a Nixpkgs version 21.11 channel, run nix-channel add https://github.com/nix-community/home-manager/archive/release-21.11.tar.gz home-manager instead of the command below
nix-channel --update

If in the NixOS configuration file from the section “Creating and configuring a NixOS configuration file” add the Home Manager module with the installation of the python3 package and setting the dot-file.git for the florent user, then the following will be obtained:

{ config, pkgs, ... }:

{
  imports =
    [
      ./hardware-configuration.nix
      # To introduce the NixOS option called home-manager.users
      <home-manager/nixos>
    ];

  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  networking.useDHCP = false;
  networking.interfaces.wlp2s0.useDHCP = true;
  networking.networkmanager.enable = true;
  services.xserver.enable = true;
  services.xserver.displayManager.gdm.enable = true;
  services.xserver.desktopManager.gnome.enable = true;
  services.xserver.layout = "fr";
  sound.enable = true;
  hardware.pulseaudio.enable = true;
  services.xserver.libinput.enable = true;
  users.users.florent = {
    isNormalUser = true;
    initialPassword = "titi"  # Define the user initial password
    extraGroups = [ "wheel" ]; # wheel to enable ‘sudo’ for the user.
  };
  # Home Manager configuration for user florent
  home-manager.users.florent = { pkgs, ...}: {
    # List packages to install in user profile
    home.packages = [ 
      pkgs.python3
    ];
    # Git config for the user
    programs.git = {
      enable = true;
      userName = "Florent";
      userEmail = "florent@adaltas.com";
    };
  };

  environment.systemPackages = with pkgs; [
    vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
    curl
  ];
  services.openssh.enable = true;
  system.stateVersion = "21.05"; # Did you read the comment?
}

Commit the changes again with the nixos-rebuild switch.

Conclusion

NixOS applies the core principles of Nix to the entire system to provide you with a complete Nix experience. Nix makes it easy to save, share, and duplicate your machine’s configuration; it creates a flexible, reliable and reproducible Linux distribution.

You can easily imagine all the benefits of using NixOS in CI / CD environments and distributed clusters. And we will help you to upgrade your skills or from the very beginning to master a profession that is in demand at any time:

Choose another in-demand profession.

Brief catalog of courses and professions

Data Science and Machine Learning

Python, web development

Mobile development

Java and C#

From basics to depth

As well as

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *