nixpkgs/nixos/doc/manual/installation/building-images-via-systemd-repart.chapter.md
2025-09-16 08:11:12 +02:00

4.8 KiB

Building Images via systemd-repart

You can build disk images in NixOS with the image.repart option provided by the module image/repart.nix. This module uses systemd-repart to build the images and exposes it's entire interface via the repartConfig option.

An example of how to build an image:

{ config, modulesPath, ... }:
{

  imports = [ "${modulesPath}/image/repart.nix" ];

  image.repart = {
    name = "image";
    partitions = {
      "esp" = {
        contents = {
          # ...
        };
        repartConfig = {
          Type = "esp";
          # ...
        };
      };
      "root" = {
        storePaths = [ config.system.build.toplevel ];
        repartConfig = {
          Type = "root";
          Label = "nixos";
          # ...
        };
      };
    };
  };

}

Nix Store Paths

If you want to rewrite Nix store paths, e.g., to remove the /nix/store prefix or to nest it below a parent path, you can do that through the nixStorePrefix option.

Nix Store Partition

You can define a partition that only contains the Nix store and then mount it under /nix/store. Because the /nix/store part of the paths is already determined by the mount point, you have to set nixStorePrefix = "/" so that /nix/store is stripped from the paths before copying them into the image.

{
  fileSystems."/nix/store".device = "/dev/disk/by-partlabel/nix-store";

  image.repart.partitions = {
    "store" = {
      storePaths = [ config.system.build.toplevel ];
      nixStorePrefix = "/";
      repartConfig = {
        Type = "linux-generic";
        Label = "nix-store";
        # ...
      };
    };
  };
}

Nix Store Subvolume

Alternatively, you can create a Btrfs subvolume /@nix-store containing the Nix store and mount it on /nix/store:

{
  fileSystems."/" = {
    device = "/dev/disk/by-partlabel/root";
    fsType = "btrfs";
    options = [ "subvol=/@" ];
  };

  fileSystems."/nix/store" = {
    device = "/dev/disk/by-partlabel/root";
    fsType = "btrfs";
    options = [ "subvol=/@nix-store" ];
  };

  image.repart.partitions = {
    "root" = {
      storePaths = [ config.system.build.toplevel ];
      nixStorePrefix = "/@nix-store";
      repartConfig = {
        Type = "root";
        Label = "root";
        Format = "btrfs";
        Subvolumes = "/@ /@nix-store";
        MakeDirectories = "/@ /@nix-store";
        # ...
      };
    };
  };
}

Appliance Image

The image/repart.nix module can also be used to build self-contained software appliances.

The generation based update mechanism of NixOS is not suited for appliances. Updates of appliances are usually either performed by replacing the entire image with a new one or by updating partitions via an A/B scheme. See the Chrome OS update process for an example of how to achieve this. The appliance image built in the following example does not contain a configuration.nix and thus you will not be able to call nixos-rebuild from this system. Furthermore, it uses a Unified Kernel Image.

let
  pkgs = import <nixpkgs> { };
  efiArch = pkgs.stdenv.hostPlatform.efiArch;
in
(pkgs.nixos [
  (
    {
      config,
      lib,
      pkgs,
      modulesPath,
      ...
    }:
    {

      imports = [ "${modulesPath}/image/repart.nix" ];

      boot.loader.grub.enable = false;

      fileSystems."/".device = "/dev/disk/by-label/nixos";

      image.repart = {
        name = "image";
        partitions = {
          "esp" = {
            contents = {
              "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source =
                "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";

              "/EFI/Linux/${config.system.boot.loader.ukiFile}".source =
                "${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
            };
            repartConfig = {
              Type = "esp";
              Format = "vfat";
              SizeMinBytes = "96M";
            };
          };
          "root" = {
            storePaths = [ config.system.build.toplevel ];
            repartConfig = {
              Type = "root";
              Format = "ext4";
              Label = "nixos";
              Minimize = "guess";
            };
          };
        };
      };

    }
  )
]).image