Loading nixos/doc/manual/installation/building-images-via-systemd-repart.chapter.md +46 −4 Original line number Diff line number Diff line Loading @@ -40,12 +40,18 @@ An example of how to build an image: } ``` ## Nix Store Partition {#sec-image-repart-store-partition} ## Nix Store Paths {#sec-image-repart-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 {#sec-image-repart-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. 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. ```nix { Loading @@ -54,7 +60,7 @@ that the prefix is stripped from the paths before copying them into the image. image.repart.partitions = { "store" = { storePaths = [ config.system.build.toplevel ]; stripNixStorePrefix = true; nixStorePrefix = "/"; repartConfig = { Type = "linux-generic"; Label = "nix-store"; Loading @@ -65,6 +71,42 @@ that the prefix is stripped from the paths before copying them into the image. } ``` ### Nix Store Subvolume {#sec-image-repart-store-subvolume} Alternatively, you can create a Btrfs subvolume `/@nix-store` containing the Nix store and mount it on `/nix/store`: ```nix { 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 {#sec-image-repart-appliance} The `image/repart.nix` module can also be used to build self-contained [software Loading nixos/doc/manual/redirects.json +6 −0 Original line number Diff line number Diff line Loading @@ -287,9 +287,15 @@ "sec-image-repart": [ "index.html#sec-image-repart" ], "sec-image-repart-store-paths": [ "index.html#sec-image-repart-store-paths" ], "sec-image-repart-store-partition": [ "index.html#sec-image-repart-store-partition" ], "sec-image-repart-store-subvolume": [ "index.html#sec-image-repart-store-subvolume" ], "sec-image-repart-appliance": [ "index.html#sec-image-repart-appliance" ], Loading nixos/modules/image/amend-repart-definitions.py +9 −7 Original line number Diff line number Diff line Loading @@ -36,11 +36,11 @@ def add_contents_to_definition( def add_closure_to_definition( definition: Path, closure: Path | None, strip_nix_store_prefix: bool | None definition: Path, closure: Path | None, nix_store_prefix: str | None ) -> None: """Add CopyFiles= instructions to a definition for all paths in the closure. If strip_nix_store_prefix is True, `/nix/store` is stripped from the target path. Replace `/nix/store` with the value of nix_store_prefix. """ if not closure: return Loading @@ -52,10 +52,12 @@ def add_closure_to_definition( continue source = Path(line.strip()) target = str(source.relative_to("/nix/store/")) target = f":/{target}" if strip_nix_store_prefix else "" option = f"CopyFiles={source}" if nix_store_prefix: target = nix_store_prefix / source.relative_to("/nix/store/") option = f"{option}:{target}" copy_files_lines.append(f"CopyFiles={source}{target}\n") copy_files_lines.append(f"{option}\n") with open(definition, "a") as f: f.writelines(copy_files_lines) Loading Loading @@ -102,8 +104,8 @@ def main() -> None: add_contents_to_definition(definition, contents) closure = config.get("closure") strip_nix_store_prefix = config.get("stripNixStorePrefix") add_closure_to_definition(definition, closure, strip_nix_store_prefix) nix_store_prefix = config.get("nixStorePrefix") add_closure_to_definition(definition, closure, nix_store_prefix) print(target_dir.absolute()) Loading nixos/modules/image/repart.nix +87 −70 Original line number Diff line number Diff line Loading @@ -15,7 +15,9 @@ let inherit (utils.systemdUtils.lib) GPTMaxLabelLength; partitionOptions = { partitionOptions = { config, ... }: { options = { storePaths = lib.mkOption { type = with lib.types; listOf path; Loading @@ -23,13 +25,21 @@ let description = "The store paths to include in the partition."; }; # Superseded by `nixStorePrefix`. Unfortunately, `mkChangedOptionModule` # does not support submodules. stripNixStorePrefix = lib.mkOption { type = lib.types.bool; default = false; default = "_mkMergedOptionModule"; visible = false; }; nixStorePrefix = lib.mkOption { type = lib.types.path; default = "/nix/store"; description = '' Whether to strip `/nix/store/` from the store paths. This is useful when you want to build a partition that only contains store paths and is mounted under `/nix/store`. The prefix to use for store paths. Defaults to `/nix/store`. This is useful when you want to build a partition that only contains store paths and is mounted under `/nix/store` or if you want to create the store paths below a parent path (e.g., `/@nix/nix/store`). ''; }; Loading Loading @@ -77,6 +87,10 @@ let ''; }; }; config = lib.mkIf (config.stripNixStorePrefix == true) { nixStorePrefix = "/"; }; }; mkfsOptionsToEnv = Loading Loading @@ -350,7 +364,7 @@ in } ) cfg.partitions; warnings = lib.filter (v: v != null) ( warnings = lib.flatten ( lib.mapAttrsToList ( fileName: partitionConfig: let Loading @@ -358,8 +372,7 @@ in suggestedMaxLabelLength = GPTMaxLabelLength - 2; labelLength = builtins.stringLength repartConfig.Label; in if (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) then '' lib.optional (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long. The suggested maximum label length is ${toString suggestedMaxLabelLength}. Loading @@ -370,8 +383,12 @@ in ${toString GPTMaxLabelLength} characters long (the maximum enforced by UEFI) and you're at version 9, you cannot increment this to 10. '' else null ++ lib.optional (partitionConfig.stripNixStorePrefix != "_mkMergedOptionModule") '' The option definition `image.repart.paritions.${fileName}.stripNixStorePrefix` has changed to `image.repart.paritions.${fileName}.nixStorePrefix` and now accepts the path to use as prefix directly. Use `nixStorePrefix = "/"` to achieve the same effect as setting `stripNixStorePrefix = true`. '' ) cfg.partitions ); }; Loading Loading
nixos/doc/manual/installation/building-images-via-systemd-repart.chapter.md +46 −4 Original line number Diff line number Diff line Loading @@ -40,12 +40,18 @@ An example of how to build an image: } ``` ## Nix Store Partition {#sec-image-repart-store-partition} ## Nix Store Paths {#sec-image-repart-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 {#sec-image-repart-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. 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. ```nix { Loading @@ -54,7 +60,7 @@ that the prefix is stripped from the paths before copying them into the image. image.repart.partitions = { "store" = { storePaths = [ config.system.build.toplevel ]; stripNixStorePrefix = true; nixStorePrefix = "/"; repartConfig = { Type = "linux-generic"; Label = "nix-store"; Loading @@ -65,6 +71,42 @@ that the prefix is stripped from the paths before copying them into the image. } ``` ### Nix Store Subvolume {#sec-image-repart-store-subvolume} Alternatively, you can create a Btrfs subvolume `/@nix-store` containing the Nix store and mount it on `/nix/store`: ```nix { 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 {#sec-image-repart-appliance} The `image/repart.nix` module can also be used to build self-contained [software Loading
nixos/doc/manual/redirects.json +6 −0 Original line number Diff line number Diff line Loading @@ -287,9 +287,15 @@ "sec-image-repart": [ "index.html#sec-image-repart" ], "sec-image-repart-store-paths": [ "index.html#sec-image-repart-store-paths" ], "sec-image-repart-store-partition": [ "index.html#sec-image-repart-store-partition" ], "sec-image-repart-store-subvolume": [ "index.html#sec-image-repart-store-subvolume" ], "sec-image-repart-appliance": [ "index.html#sec-image-repart-appliance" ], Loading
nixos/modules/image/amend-repart-definitions.py +9 −7 Original line number Diff line number Diff line Loading @@ -36,11 +36,11 @@ def add_contents_to_definition( def add_closure_to_definition( definition: Path, closure: Path | None, strip_nix_store_prefix: bool | None definition: Path, closure: Path | None, nix_store_prefix: str | None ) -> None: """Add CopyFiles= instructions to a definition for all paths in the closure. If strip_nix_store_prefix is True, `/nix/store` is stripped from the target path. Replace `/nix/store` with the value of nix_store_prefix. """ if not closure: return Loading @@ -52,10 +52,12 @@ def add_closure_to_definition( continue source = Path(line.strip()) target = str(source.relative_to("/nix/store/")) target = f":/{target}" if strip_nix_store_prefix else "" option = f"CopyFiles={source}" if nix_store_prefix: target = nix_store_prefix / source.relative_to("/nix/store/") option = f"{option}:{target}" copy_files_lines.append(f"CopyFiles={source}{target}\n") copy_files_lines.append(f"{option}\n") with open(definition, "a") as f: f.writelines(copy_files_lines) Loading Loading @@ -102,8 +104,8 @@ def main() -> None: add_contents_to_definition(definition, contents) closure = config.get("closure") strip_nix_store_prefix = config.get("stripNixStorePrefix") add_closure_to_definition(definition, closure, strip_nix_store_prefix) nix_store_prefix = config.get("nixStorePrefix") add_closure_to_definition(definition, closure, nix_store_prefix) print(target_dir.absolute()) Loading
nixos/modules/image/repart.nix +87 −70 Original line number Diff line number Diff line Loading @@ -15,7 +15,9 @@ let inherit (utils.systemdUtils.lib) GPTMaxLabelLength; partitionOptions = { partitionOptions = { config, ... }: { options = { storePaths = lib.mkOption { type = with lib.types; listOf path; Loading @@ -23,13 +25,21 @@ let description = "The store paths to include in the partition."; }; # Superseded by `nixStorePrefix`. Unfortunately, `mkChangedOptionModule` # does not support submodules. stripNixStorePrefix = lib.mkOption { type = lib.types.bool; default = false; default = "_mkMergedOptionModule"; visible = false; }; nixStorePrefix = lib.mkOption { type = lib.types.path; default = "/nix/store"; description = '' Whether to strip `/nix/store/` from the store paths. This is useful when you want to build a partition that only contains store paths and is mounted under `/nix/store`. The prefix to use for store paths. Defaults to `/nix/store`. This is useful when you want to build a partition that only contains store paths and is mounted under `/nix/store` or if you want to create the store paths below a parent path (e.g., `/@nix/nix/store`). ''; }; Loading Loading @@ -77,6 +87,10 @@ let ''; }; }; config = lib.mkIf (config.stripNixStorePrefix == true) { nixStorePrefix = "/"; }; }; mkfsOptionsToEnv = Loading Loading @@ -350,7 +364,7 @@ in } ) cfg.partitions; warnings = lib.filter (v: v != null) ( warnings = lib.flatten ( lib.mapAttrsToList ( fileName: partitionConfig: let Loading @@ -358,8 +372,7 @@ in suggestedMaxLabelLength = GPTMaxLabelLength - 2; labelLength = builtins.stringLength repartConfig.Label; in if (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) then '' lib.optional (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) '' The partition label '${repartConfig.Label}' defined for '${fileName}' is ${toString labelLength} characters long. The suggested maximum label length is ${toString suggestedMaxLabelLength}. Loading @@ -370,8 +383,12 @@ in ${toString GPTMaxLabelLength} characters long (the maximum enforced by UEFI) and you're at version 9, you cannot increment this to 10. '' else null ++ lib.optional (partitionConfig.stripNixStorePrefix != "_mkMergedOptionModule") '' The option definition `image.repart.paritions.${fileName}.stripNixStorePrefix` has changed to `image.repart.paritions.${fileName}.nixStorePrefix` and now accepts the path to use as prefix directly. Use `nixStorePrefix = "/"` to achieve the same effect as setting `stripNixStorePrefix = true`. '' ) cfg.partitions ); }; Loading