nixpkgs/nixos/modules/image/repart.md
2023-07-26 23:36:18 +02:00

3.9 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 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 stripNixStorePrefix = true; so that the prefix 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 ];
    stripNixStorePrefix = true;
    repartConfig = {
      Type = "linux-generic";
      Label = "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.

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";

            "/loader/entries/nixos.conf".source = pkgs.writeText "nixos.conf" ''
              title NixOS
              linux /EFI/nixos/kernel.efi
              initrd /EFI/nixos/initrd.efi
              options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
            '';

            "/EFI/nixos/kernel.efi".source =
              "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}";

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

  })
]).image