141 views
# Hands-on NixOS for Beginners Workshop CfgMgmtCamp 2025 Ghent 2025-02-05, 09:00–13:00, Niks (B.1.036) ### Workshop Documentation: Getting Started with NixOS --- ## 1. Introduction ### 1.a. **Introduction to NixOS** NixOS is a declarative Linux distribution powered by the Nix package manager. It uses Nix configuration files to enforce infrastructure-as-code, provides atomic rollbacks for risk-free deployments, and isolates packages to prevent dependency conflicts. The Nix package manager builds packages defined in the Nix language. All packages are stored in the Nix Store, usually located on `/nix/store`, where each package is a unique directory identified by a cryptographic hash of its build inputs. Example: ```text /nix/store/12nq4g3nmjlcri7185csx8668v7ibyzk-btop-1.4.0/ ├── bin │   └── btop └── share ├── applications │   └── btop.desktop ├── btop │   └── themes │   ├── adapta.theme │   ├── ... └── icons └── ... ``` All packages and programs are stored in the Nix Store. Environment variables and symlinks are used to make the right packages available in the user's current environment. The Linux [Filesystem Hierarchy Standard](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard) is not respected. Where most distributions store programs in `/bin` and `/usr`, those is basically empty (`/bin/sh` and `/usr/bin/env` provide compatibility with scripts that hardcode these paths). ```text / ├── bin │   └── sh -> /nix/store/x9d49vaqlrkw97p9ichdwrnbh013kq7z-bash-interactive-5.2p37/bin/sh ... ├── usr │   └── bin │   └── env -> /nix/store/6wgd8c9vq93mqxzc7jhkl86mv6qbc360-coreutils-9.5/bin/env ``` System configuration is still stored in `/etc`, which on NixOS contains a mix between local files and symlinks to the Nix Store. > ℹ️ NixOS only needs /boot and /nix in order to boot. ### 1.b. Objectives of the workshop This hands-on workshop has as goal to guide participants to actively install NixOS and get a working system they can customize to their taste. ### 1.c. Support Links to the official documentations of NixOS are available at the end of this document. The NixOS Wiki is often helpful: https://wiki.nixos.org/wiki/NixOS_Wiki Two Matrix channels for instant messaging are available: - [#hands-on-nixos:okeso.eu](https://matrix.to/#/#hands-on-nixos:okeso.eu) : Channel for this workshop - [#users:nixos.org](https://matrix.to/#/#users:nixos.org) : Nix/NixOS user help channel For slower interactions, NixOS hosts a resourceful [Discourse Forum](https://discourse.nixos.org/). ## 2. Installing NixOS There are a few different ways to install NixOS. The most popular are: - Booting an ISO image and an installer. - Similar to other Linux distributions. - There are both graphical and command-line installers. - Downloading an existing system. - Virtual machine, UEFI disk, ... - NixOS provides tools to easily build customized ones. - Converting an existing Linux system to NixOS. - Most useful in cloud environments that do not provide NixOS ### 2.a. Booting an ISO image An ISO image can be obtained from the NixOS website: https://nixos.org/download/#nixos-iso ### 2.b. Downloading an existing system NixOS used to distributed VirtualBox images but does not do it anymore. Using an ISO may be the most straightforward approach. Alternatively, a VirtualBox image can be generated using Nix. ### 2.c. Converting an existing Linux system #### NixOS-Infect [NixOS-Infect](https://github.com/elitak/nixos-infect) is currently the easiest way to convert an existing Linux system to NixOS. It consists mainly in a script that converts an existing Linux distribution to NixOS, while copying some configuration data (SSH public keys, network configuration) to the new system. Supported hosting providers, plans and initial distributions are well documented, with the addition of some provider specific notes. The only requirement on supported hosts is an access to a shell or Cloud-Init configuration. NixOS-Infect has successfully been tested on at least the follow hosting providers and plans: * [DigitalOcean](https://www.digitalocean.com/products/droplets/) * [Hetzner Cloud](https://www.hetzner.com/cloud) * [Vultr](https://www.vultr.com/) * [Interserver VPS](https://www.interserver.net/vps/) * [Tencent Cloud Lighthouse](https://cloud.tencent.com/product/lighthouse) * [OVHcloud](https://www.ovh.com/) * [Oracle Cloud Infrastructure](https://www.oracle.com/cloud/) * [GalaxyGate](https://galaxygate.net) * [Cockbox](https://cockbox.org) * [Google Cloud Platform](https://cloud.google.com/) * [Contabo](https://contabo.com) * [Liga Hosting](https://ligahosting.ro) * [AWS Lightsail](https://aws.amazon.com/lightsail/) * [Windcloud](https://windcloud.de/) * [Clouding.io](https://clouding.io) * [Scaleway](https://scaleway.com) * [RackNerd](https://my.racknerd.com/index.php?rp=/store/black-friday-2022) https://github.com/elitak/nixos-infect #### NixOS-Anywhere [NixOS-Anywhere](https://github.com/nix-community/nixos-anywhere) is a more complex and complete tool to convert an existing Linux system to NixOS over SSH. Compared to NixOS-Infect, it can also partition and format the hard drive and apply additional configuration. A machine with Nix already installed is required in order to use NixOS-Anywhere. Nix can be installed on most Linux and macOS systems, but this requires root access and more involvement. https://github.com/nix-community/nixos-anywhere/blob/main/docs/quickstart.md ## 3. Configuring NixOS ### 3.a. Configuration files On a freshly installed NixOS system, its configuration is located in two files: - `/etc/nixos/configuration.nix` - `/etc/nixos/hardware-configuration.nix` These two files can be regenerated anytime using the command `nixos-generate-config`. The first file, `configuration.nix`, is the starting point to configuring a Linux system. This is the file you want to start editing. The second file, `hardware-configuration.nix`, contains device specific information such as filesystems and kernel modules to load. __Example__: `configuration.nix`: ```nix= { config, lib, 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; # Define a user account. Don't forget to set a password with ‘passwd’. users.users.alice = { isNormalUser = true; extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. packages = with pkgs; [ tree ]; }; # System packages are available to all users environment.systemPackages = with pkgs; [ vim wget ]; ... system.stateVersion = "24.11"; # Did you read the comment? } ``` `hardware-configuration.nix`: ```nix= { config, lib, pkgs, modulesPath, ... }: { boot.kernelModules = [ "kvm-intel" ]; fileSystems."/boot" = { device = "/dev/disk/by-label/NIXBOOT"; fsType = "vfat"; }; swapDevices = [ ]; ... } ``` The file `configuration.nix` contains many examples of initial configuration to get started. ### 3.b. Applying configurations The command `nixos-rebuild` reconfigures a NixOS machine with a given configuration file. This command updates the system so that it corresponds to the configuration specified in `/etc/nixos/configuration.nix`, `/etc/nixos/flake.nix` or a path in argument. You must run `nixos-rebuild` to make changes take effect. It builds the new system in `/nix/store`. A few different operations can be used to specify what do do after the build (excerpt from `man nixos-rebuild`): - `nixos-rebuild switch` runs the activation script, and stop and (re)starts any system services if needed. It also makes the new configuration the default at boot. Previous configurations activated remain available in the boot menu. - `nixos-rebuild dry-activate` shows what changes would be performed by the activation (ex. services that would restart). - `nixos-rebuild test` switches to the new configuration but does not affect boot. - `nixos-rebuild boot` only makes the new configuration the default at boot. - `nixos-rebuild build` only builds the new configuration. - `nixos-rebuild dry-build` only shows what would be built or downloaded. - `nixos-rebuild build-vm` builds a script that starts a virtual machine with the desired configuration. - `nixos-rebuild switch --rollback` reverts the system to the previously applied configuration. - `nixos-rebuild list-generations` lists previous versions of the system still available. Configurations are applied locally by default, but can instead be applied to a remote machine over SSH with the `--target-host` argument. Similarly, packages are built locally by default, but can be built on a remote machine instead with `--build-host`. This is pretty useful on laptops and less powerful machines when compilation is involved. Old generations and unusued packages can be removed with the command `nix-collect-garbage --delete-old` or `nix-collect-garbage --delete-older-than 1d`. ### 3.c. Configuring services #### Packages A large amount of software has been packaged for NixOS, with "over 120 000 packages" available. Packages are written in Nix and available in the [nixpkgs](https://github.com/NixOS/nixpkgs/), one of the most active repositories public on GitHub. The package index available on https://search.nixos.org/packages can be used from a web browser or from the `nix-search` command. Packages can be made available system wise: ```nix= environment.systemPackages = with pkgs; [ tree ]; ``` > ℹ️ This can also be written `environment.systemPackages = [ pkgs.tree ];` Or to a specific user: ```nix= users.users.alice = { packages = with pkgs; [ tree ]; }; ``` #### Options NixOS options are configuration parameters defined in modular Nix expressions. They unify system settings, services, and packages under a single declarative model, allowing to manage every aspect of an operating system’s configuration. #### Services Services are NixOS modules that configure and manage system or user processes (usually via systemd). They define daemons, dependencies, and configuration options to run and control background functionality. __Example__: ```nix= services.nextcloud = { enable = true; hostName = "localhost"; config.dbtype = "pgsql"; package = pkgs.nextcloud_30; }; ``` This service will run Nextcloud, a PHP application, with php-fpm, Nginx and a PostgreSQL database, on the domain name `localhost`. > ℹ️ It is common for services to expose the `package` option to allow overriding the version of the underlying software. Find options, including services, on https://search.nixos.org/options > ℹ️ Complex services are often documented on the [NixOS Wiki](https://wiki.nixos.org/wiki/NixOS_Wiki). ### 3.d. Channels Packages, including the Nix packages collection, are distributed through _channels_. By default, only one channel is present in `sudo nix-channel --list`: ```shell nixos https://nixos.org/channels/nixos-24. ``` Popular channels are: ``` nixos https://channels.nixos.org/nixos-24.11 nixos-unstable https://nixos.org/channels/nixos-unstable nixos-hardware https://github.com/NixOS/nixos-hardware/archive/master.tar.gz ``` **nixos** Users of NixOS generally use one of the official `nixos-*` channels, e.g. `nixos-24.11`, which includes all packages and modules for the stable NixOS 24.11. **nixos-unstable** The latest version of NixOS and the Nix packages is available in the rolling release `nixos-unstable`. It is possible to use `nixos-unstable` for the entire system, or only for a few selected packages. In order to use only some packages from unsable: First add the channel: ```shell= sudo nix-channel --add https://nixos.org/channels/nixos-unstable nixos-unstable ``` Then import the unstable channel: ```nix= { config, pkgs, lib, ...}: let pkgs-unstable = <nixos-unstable> { }; in { ... environment.systemPackages = [ pkgs.tree pkgs-unstable.btop ]; } ``` **Updates** Updating a NixOS sytem consists in updating its channels, and then rebuilding and switching to the new configuration. ```shell nix-channel --update nixos-rebuild switch ``` A reboot may be necessary for kernel and driver updates. ### 3.e. Hardware support The [NixOS-Hardware](https://github.com/NixOS/nixos-hardware) project provides configuration for supporting different hardware. While not very useful inside virtual machines, this eases the support of vendor specific hardware and is worth looking at on bare metal installations. ## 4. Running containers Linux containers is a generic term for an implementation of operating system-level virtualization for the Linux operating system. The most popular implementation is [OCI Containers](https://opencontainers.org/), initiated by **Docker**. These containers rely on "images" and are expected to run a single process. Both Docker and Podman are supported on NixOS. **Systemd-nspawn** is another popular tool to run containers in a stateful manner (like an improved `chroot`). NixOS provides tooling to configure and manage such containers declaratively using Nix. ### 4.a. OCI Containers To enable Docker support, add following lines to your system configuration: ```nix= virtualisation.docker.enable = true; users.users.<myuser>.extraGroups = [ "docker" ]; ``` Source: https://wiki.nixos.org/wiki/Docker In order to use Podman instead: ```nix= virtualisation.containers.enable = true; virtualisation = { podman = { enable = true; # Create a `docker` alias for podman, to use it as a drop-in replacement dockerCompat = true; # Required for containers under podman-compose to be able to talk to each other. defaultNetwork.settings.dns_enabled = true; }; }; users.users.<myuser>.extraGroups = [ "podman" ]; ``` Source: https://wiki.nixos.org/wiki/Podman Containers can then be configured declaratively: ```nix= virtualisation.oci-containers.containers = { website = { image = "nginx:latest"; ports = [ "127.0.0.1:80:80" ]; volumes = [ "/srv/website:/usr/share/nginx/html:ro" ]; autoStart = true; }; }; ``` [Search for all oci-containers options](https://search.nixos.org/options?channel=24.11&from=0&size=50&sort=relevance&type=packages&query=virtualisation.oci-containers). ### 4.b. NixOS Containers NixOS containers provide isolated NixOS systems that may share some resources with the host, such as networking and access to devices. A simple example running Nginx would be: ```nix= containers.webserver = { autoStart = true; privateNetwork = false; # Share the network of the host config = { config, pkgs, lib, ... }: { # NixOS configuration goes here. services.nginx = { enable = true; virtualHosts.localhost = { locations."/" = { return = "200 '<html><body>It works</body></html>'"; extraConfig = '' default_type text/html; ''; }; }; }; system.stateVersion = "24.11"; }; }; ``` The container can then be managed by running the following commands as root: ```shell= machinectl list systemctl status container@webserver nixos-container root-login webserver nixos-container start webserver nixos-container stop webserver ``` Examples of networking configuration and extended usage can be found on the NixOS Wiki: https://wiki.nixos.org/wiki/NixOS_Containers NixOS Containers share read-only access to the Nix Store of the host, making them very lightweight and easy to backup. The root filesystems can be accessed in `/var/lib/nixos-containers/<container>`. ## 5. Dotfiles and home configuration Home Manager is a system for managing a user environment and configuring user applications using the Nix package manager. Typical applications are the configuration of user shell, window manager, SSH client, developer tools, browser extensions, ... Home Manager can be used as a standalone tool on any Linux or macOS system with Nix installed or integrated into a NixOS system configuration. ### 5.b. Installation Home Manager can be installed by adding the corresponding _channels_: ```shell= nix-channel --add https://github.com/nix-community/home-manager/archive/release-24.11.tar.gz home-manager nix-channel --update ``` ### 5.c. In the global configuration On NixOS, Home Manager can be included as a NixOS module. This enables user configurations to be managed system-wide through `/etc/nixos/configuration.nix`. Example: ```nix { config, pkgs, ... }: { imports = [ <home-manager/nixos> ]; home-manager.users.alice = { pkgs, ... }: { home.packages = with pkgs; [ neovim git ]; programs.bash.enable = true; programs.git = { enable = true; userName = "Alice Doe"; userEmail = "alice@example.com"; extraConfig = { init.defaultBranch = "main"; pull.rebase = true; merge.ff = "only"; }; }; home.stateVersion = "24.11"; }; } ``` To apply: ```sh sudo nixos-rebuild switch ``` ### 5.d. As a user tool ```shell nix-shell '<home-manager>' -A install ``` [Home Manager](https://home-manager-options.extranix.com/) configurations are typically stored in `~/.config/home-manager/home.nix`. This file defines packages, shell settings, and dotfiles to be managed. Example: ```nix { config, pkgs, ... }: { home.username = "alice"; home.homeDirectory = "/home/alice"; # Install user packages home.packages = with pkgs; [ neovim git ]; # Shell configuration programs.zsh.enable = true; programs.git = { enable = true; userName = "Alice Doe"; userEmail = "alice@example.com"; extraConfig = { init.defaultBranch = "main"; pull.rebase = true; merge.ff = "only"; }; }; # Enable Home Manager home.stateVersion = "24.11"; } ``` To apply the configuration: ```shell home-manager switch ``` #### 5.d. Managing specific files Home Manager can manage dotfiles declaratively using `xdg.configFile` or `home.file`. Example: ```nix home.file.".vimrc".source = ./dotfiles/vimrc; home.file.".config/nvim/init.vim".text = "set number"; ``` #### 5.e. Home Manager Options Similar to NixOS Services, a website provides a search tool through the many options of home-manager: https://home-manager-options.extranix.com/ ## 6. Next steps ### 6.a. Flakes Flakes provide an alternative to global channels that allows users to lock the versions of the package sources being used. Using nix flakes with NixOS: https://wiki.nixos.org/wiki/Flakes#Using_nix_flakes_with_NixOS ### 6.b. System tuning Use the latest version of the Linux kernel: ``` boot.kernelPackages = pkgs.linuxPackages_6_13; ``` ## 7. References and documentation - NixOS Manual: https://nixos.org/manual/nixos/stable/ - Nix Manual: https://nixos.org/manual/nix/stable - Nixpkgs Manual: https://nixos.org/manual/nixpkgs/stable - Nixpkgs Package Search: https://search.nixos.org/packages - Nixpkgs Options Search: https://search.nixos.org/options - Home Manager Manual: [https://nix-community.github.io/home-manager/](https://nix-community.github.io/home-manager/) - Home Manager Options: https://home-manager-options.extranix.com/