Chapter 2
Installation, Bootstrapping, and Hardware Integration
What does it take to build a system that installs itself exactly as intended, regardless of environment or hardware quirks? In this chapter, we expose the powerful tools and design principles behind reproducible NixOS deployments. Go beyond mere installation-discover how automation, declarative hardware integration, and advanced recovery workflows transform provisioning and hardware adaptation from a source of uncertainty into a foundation of reliability.
2.1 Customizing the NixOS Install Process
NixOS distinguishes itself in installation flexibility by leveraging its declarative configuration model, enabling users to script and automate the installation process with remarkable precision. This capability transforms what is frequently a manual, error-prone task into a repeatable and verifiable procedure, accommodating environments ranging from personal desktops to enterprise-scale deployments.
At the core of customization lies the installation configuration, typically residing in /etc/nixos/configuration.nix. Automating an installation begins with crafting or generating this configuration file before or during the installation. Since NixOS configurations are pure functional expressions producing system specifications, they can be modular, parameterized, and stored in version-controlled repositories.
Unattended, hands-free installations leverage preseeded configurations combined with automated partitioning and bootstrapping. The NixOS installer, nixos-install, supports specifying a -flake argument to apply a Nix flake defining the system configuration, including hardware and deployment-specific parameters.
A common pattern involves preparing the installation medium or an initial RAM disk environment with:
nixos-install --root /mnt --flake github:user/repo#hostname Here, the flake reference resolves to the desired system state, including network setup, user accounts, and services. To bootstrap the file system and partitions automatically, parted or sgdisk commands can be scripted within a pre-installation script or integrated into the flake's installScript attribute.
Fine-grained control over disk partitioning, encryption, and filesystem layout is achieved by defining boot.initrd configuration options and invoking standard tooling under the hood. This circumvents rigid or simplistic partition layouts and aligns the installation to organizational compliance standards.
The modular nature of NixOS implies that the installer itself can be extended or customized. While the distribution provides the standard installer, nixos-install, custom installation flows can be implemented by invoking low-level Nix tools such as nix-env, nix-build, and others within bespoke scripts.
For instance, customized installation routines may:
- Validate hardware compatibility and apply conditional configuration fragments.
- Integrate with hardware management interfaces such as IPMI for bare-metal provisioning.
- Enforce compliance checks before installation proceeding.
- Trigger post-install hooks that configure organizational monitoring, security hardening, or network policies.
Extending the installer requires leveraging the nixos-generate-config utility to create an initial configuration skeleton and then programmatically augmenting it by including additional Nix expressions or overlays. The extensibility is further enhanced by embracing flakes to manage these configurations declaratively.
Ensuring every deployment conforms precisely to its specification necessitates a policy enforcement mechanism. Within NixOS, this can be achieved by integrating declarative security and compliance frameworks directly into the installation configuration.
A typical approach is the definition of strict users.users and security options, combined with:
- Use of nixpkgs.config.allowUnfree = false; to restrict package selections.
- Locked-down service configurations, ensuring no unintended services start.
- Immutability of critical configuration files by mounting them with appropriate permissions at boot time.
To detect divergence from the prescribed system state post-installation, a continuous verification process can be scripted using the nix-collect-garbage and nix-store -verify commands, or through scheduled invocation of nixos-rebuild switch from centralized management nodes.
The declarative installation can be integrated into broader deployment pipelines through automation tools such as Jenkins, GitLab CI, or custom orchestration scripts. By committing NixOS configurations into repositories, continuous integration workflows can validate builds, test configuration changes, and stage deployments to diverse hardware.
Using flakes as a central mechanism simplifies this integration by unifying package and system configuration management, enabling atomic upgrades and rollbacks consistent across all environments.
The following example summarizes a minimalist automated installation procedure:
#!/bin/sh # Partition disks non-interactively parted /dev/sda --script mklabel gpt \ mkpart primary 1MiB 512MiB \ mkpart primary 512MiB 100% # Format partitions mkfs.ext4 /dev/sda2 mkfs.fat -F 32 /dev/sda1 # Mount target mount /dev/sda2 /mnt mkdir /mnt/boot ...