1# Building Images via `systemd-repart` {#sec-image-repart}
2
3You can build disk images in NixOS with the `image.repart` option provided by
4the module [image/repart.nix][]. This module uses `systemd-repart` to build the
5images and exposes it's entire interface via the `repartConfig` option.
6
7[image/repart.nix]: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/image/repart.nix
8
9An example of how to build an image:
10
11```nix
12{ config, modulesPath, ... }: {
13
14 imports = [ "${modulesPath}/image/repart.nix" ];
15
16 image.repart = {
17 name = "image";
18 partitions = {
19 "esp" = {
20 contents = {
21 ...
22 };
23 repartConfig = {
24 Type = "esp";
25 ...
26 };
27 };
28 "root" = {
29 storePaths = [ config.system.build.toplevel ];
30 repartConfig = {
31 Type = "root";
32 Label = "nixos";
33 ...
34 };
35 };
36 };
37 };
38
39}
40```
41
42## Nix Store Partition {#sec-image-repart-store-partition}
43
44You can define a partition that only contains the Nix store and then mount it
45under `/nix/store`. Because the `/nix/store` part of the paths is already
46determined by the mount point, you have to set `stripNixStorePrefix = true;` so
47that the prefix is stripped from the paths before copying them into the image.
48
49```nix
50fileSystems."/nix/store".device = "/dev/disk/by-partlabel/nix-store"
51
52image.repart.partitions = {
53 "store" = {
54 storePaths = [ config.system.build.toplevel ];
55 stripNixStorePrefix = true;
56 repartConfig = {
57 Type = "linux-generic";
58 Label = "nix-store";
59 ...
60 };
61 };
62};
63```
64
65## Appliance Image {#sec-image-repart-appliance}
66
67The `image/repart.nix` module can also be used to build self-contained [software
68appliances][].
69
70[software appliances]: https://en.wikipedia.org/wiki/Software_appliance
71
72The generation based update mechanism of NixOS is not suited for appliances.
73Updates of appliances are usually either performed by replacing the entire
74image with a new one or by updating partitions via an A/B scheme. See the
75[Chrome OS update process][chrome-os-update] for an example of how to achieve
76this. The appliance image built in the following example does not contain a
77`configuration.nix` and thus you will not be able to call `nixos-rebuild` from
78this system.
79
80[chrome-os-update]: https://chromium.googlesource.com/aosp/platform/system/update_engine/+/HEAD/README.md
81
82```nix
83let
84 pkgs = import <nixpkgs> { };
85 efiArch = pkgs.stdenv.hostPlatform.efiArch;
86in
87(pkgs.nixos [
88 ({ config, lib, pkgs, modulesPath, ... }: {
89
90 imports = [ "${modulesPath}/image/repart.nix" ];
91
92 boot.loader.grub.enable = false;
93
94 fileSystems."/".device = "/dev/disk/by-label/nixos";
95
96 image.repart = {
97 name = "image";
98 partitions = {
99 "esp" = {
100 contents = {
101 "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source =
102 "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";
103
104 "/loader/entries/nixos.conf".source = pkgs.writeText "nixos.conf" ''
105 title NixOS
106 linux /EFI/nixos/kernel.efi
107 initrd /EFI/nixos/initrd.efi
108 options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
109 '';
110
111 "/EFI/nixos/kernel.efi".source =
112 "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}";
113
114 "/EFI/nixos/initrd.efi".source =
115 "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
116 };
117 repartConfig = {
118 Type = "esp";
119 Format = "vfat";
120 SizeMinBytes = "96M";
121 };
122 };
123 "root" = {
124 storePaths = [ config.system.build.toplevel ];
125 repartConfig = {
126 Type = "root";
127 Format = "ext4";
128 Label = "nixos";
129 Minimize = "guess";
130 };
131 };
132 };
133 };
134
135 })
136]).image
137```