NixOS & Flakes Book

repository·main·Indexed 25 days ago

https://github.com/ryan4yin/nixos-and-flakes-book

An unofficial, opinionated, and beginner-friendly tutorial for learning NixOS and Nix Flakes. The guide covers detailed lessons on Nix configurations, debugging with nix repl, accelerating dotfiles debugging using mkOutOfStoreSymlink, and remote host deployment. It also provides recommendations for community tools such as flake-parts, flake-utils-plus, NUR, and various ecosystem projects for secrets management, deployment, and containerization.

Tokens
31.2K
Snippets
77
Records
147
Agent score
85%

What's inside nixos-and-flakes-book

  1. Understand the scope of the NixOS & Flakes Book

    main

    This book is a beginner-friendly guide specifically designed for users who want to use NixOS with Flakes. Unlike many other resources, it intentionally disregards the traditional Nix configuration approach to focus entirely on the Flakes-enabled workflow.

    Key characteristics:

    • Flakes-centric: Focuses on using flake.nix for dependency recording and flake.lock for version locking.
    • Progressive Learning: Designed as a step-by-step guide for newcomers with existing Linux and programming experience.
    • Reference-heavy: Most chapters include reference links for deeper investigation.
  2. Understand Nix and NixOS concepts

    main

    Nix

    Nix is a declarative package manager. Instead of manually installing packages, you declare the desired system state in configuration files. Nix handles the underlying details, such as dependencies, uninstallation of conflicting packages, and environment variable adjustments.

    NixOS

    NixOS is a Linux distribution built on the Nix package manager, often described as "OS as Code." It uses declarative Nix configuration files to describe the entire state of the operating system.

    Key Limitations & Scope:

    • Static State: NixOS primarily manages the static portion of the system state (software packages, system configuration files, etc.).
    • Dynamic Data: Dynamic data (e.g., PostgreSQL, MySQL, or MongoDB databases) and the contents of the user's /home directory are not managed by NixOS declarative configuration and remain unaffected when rolling back to a previous generation.
    • User Configuration: To manage user-level packages and dotfiles within the /home directory, the community project home-manager is recommended.
  3. Use Nix Binary Cache to speed up installations

    main

    Nix uses a binary cache to avoid time-consuming local builds. Because the Nix Store is input-addressed, build results can be shared across machines. When a build is requested, Nix first checks the remote cache server for the corresponding hash.

    • Official Cache: Nix provides an official binary cache at https://cache.nixos.org which contains build results for most nixpkgs packages on common architectures.
    • Workflow: If the hash is found in the cache, Nix downloads the pre-built result to /nix/store instead of compiling it locally.
  4. Understand NIX_PATH and its impact on Flakes

    main

    The NIX_PATH environment variable controls the Nix search path for expressions using the <name> syntax (e.g., <nixpkgs>).

    Warning: Using <name> syntax in Flake-based projects is discouraged because it introduces a dependency on a mutable environment variable, which compromises build reproducibility.

    Use Case: You may still need NIX_PATH for interactive commands like nix repl '<nixpkgs>', which relies on NIX_PATH to resolve the package set.

  5. Understand Flake Outputs

    main
    In a flake.nix file, the outputs section defines what a flake can produce. A single flake can simultaneously provide multiple types of outputs, such as packages, development environments, NixOS configurations, and helper libraries. These outputs are categorized by attribute names (e.g., packages, devShells, nixosConfigurations) and often require a system attribute (e.g., packages.<system>.<name>).
  6. Understand the advantages and disadvantages of NixOS

    main

    NixOS offers a declarative approach to system management, but it comes with specific trade-offs that users should be aware of before committing to the platform.

    Advantages

    • Declarative Configuration (OS as Code): Manage your entire system via configuration files that can be version-controlled with Git.
    • Reproducibility with Nix Flakes: Using flake.lock ensures that dependencies (data source addresses, hashes, etc.) are locked, providing consistent build results similar to Cargo or npm.
    • System Customization: Easily swap system components (like switching between GNOME, KDE, i3, or sway) using declarative parameters.
    • Rollback Capability: NixOS includes historical system versions in the boot options by default, allowing you to revert to a previous working state if a change fails.
    • No Dependency Conflicts: Packages are stored in unique paths based on their hashes, allowing multiple versions of the same software to coexist.

    Disadvantages

    • High Learning Curve: Requires understanding Nix's design and declarative management rather than using imperative commands like nix-env -i.
    • Documentation Gaps: Much documentation focuses on the classic /etc/nixos/configuration.nix rather than the newer Nix Flakes (flake.nix). Some core features like the Nixpkgs Module System lack detailed official documentation.
    • Disk Space Usage: Retaining historical environments for rollbacks increases disk consumption, which may impact resource-constrained cloud servers.
    • Obscure Error Messages: The Nixpkgs module system can produce unhelpful errors, such as Infinite recursion encountered.
    • Implementation Complexity: The underlying abstraction is more complex than traditional imperative tools, though this primarily affects package maintainers.

    Recommendation

    NixOS is best suited for developers with Linux experience and programming knowledge. It is not recommended for absolute beginners to Linux.

  7. Customize Nix packages using callPackage, Overriding, and Overlays

    main

    When you need to modify the build parameters or configuration of existing Nix packages, you can use three primary techniques:

    1. callPackage: Used to instantiate a package by providing its required dependencies.
    2. Overriding: Used to change specific arguments or parameters of a package without redefining the entire package. This is useful for packages with many configurable build options (e.g., changing rimeDataPkgs in fcitx5-rime or vscodeExtensions in vscode).
    3. Overlays: Used to replace or augment packages within a Nixpkgs set, allowing you to provide a custom version of a package globally across your configuration.
  8. Understand the NixOS and Home Manager Module System

    main
    The NixOS and Home Manager module systems are built upon a universal module system implemented in nixpkgs. While most users only need to set existing options (found via search.nixos.org), advanced users can define custom options to create parameterized, reusable configurations. This avoids the redundancy of creating multiple separate files for slight variations of the same configuration.
  9. Understand Nix Flakes concepts

    main

    Nix Flakes is an experimental feature that introduces a standardized way to manage dependencies and ensure reproducibility in the Nix ecosystem. It uses two primary files:

    • flake.nix: Similar to package.json or Cargo.toml, it describes the dependencies between Nix packages and how to build projects.
    • flake.lock: Similar to package-lock.json or Cargo.lock, it locks the specific versions of dependencies to ensure project reproducibility.

    Flakes act as a wrapper for other Nix configurations, providing a more convenient way to manage dependencies without breaking Nix's original design.

  10. Understand the Nix Store and its path format

    main

    The Nix Store is a read-only file system used to store immutable software packages, their build results, metadata, and build inputs. It follows an Input-addressed Model, meaning the same build inputs always result in the same storage path.

    Paths follow this format: /nix/store/<digest>-<name>-<version>

    • digest: A hash calculated from all input information (build parameters, dependencies, etc.).
    • name: The software package name.
    • version: The version number.
    /nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1
    |--------| |------------------------------| |----------|
    store directory         digest                  name
  11. Access the NixOS & Flakes Book

    main

    The NixOS & Flakes Book is an unofficial, opinionated, and beginner-friendly tutorial for learning NixOS and Nix Flakes.

    Author-Maintained Versions

    Community-Maintained Versions

  12. Understand the Flakes Registry

    main

    The Flakes Registry allows you to use short IDs (like nixpkgs) instead of full GitHub repository URLs when using commands such as nix run, nix shell, or nix repl.

    By default, Nix resolves these IDs using the registry hosted at: https://github.com/NixOS/flake-registry/blob/master/flake-registry.json.

    Example: Running nix run nixpkgs#ponysay hello tells Nix to look up the nixpkgs ID in the registry, find its repository address, download it, and execute the package.