diff --git a/nixos/lib/make-squashfs.nix b/nixos/lib/make-squashfs.nix index b7c7078b73b1..4b6b56739948 100644 --- a/nixos/lib/make-squashfs.nix +++ b/nixos/lib/make-squashfs.nix @@ -1,15 +1,22 @@ { lib, stdenv, squashfsTools, closureInfo +, fileName ? "squashfs" , # The root directory of the squashfs filesystem is filled with the # closures of the Nix store paths listed here. storeContents ? [] + # Pseudo files to be added to squashfs image +, pseudoFiles ? [] +, noStrip ? false , # Compression parameters. # For zstd compression you can use "zstd -Xcompression-level 6". comp ? "xz -Xdict-size 100%" }: +let + pseudoFilesArgs = lib.concatMapStrings (f: ''-p "${f}" '') pseudoFiles; +in stdenv.mkDerivation { - name = "squashfs.img"; + name = "${fileName}.img"; __structuredAttrs = true; nativeBuildInputs = [ squashfsTools ]; @@ -31,8 +38,8 @@ stdenv.mkDerivation { '' + '' # Generate the squashfs image. - mksquashfs nix-path-registration $(cat $closureInfo/store-paths) $out \ - -no-hardlinks -keep-as-directory -all-root -b 1048576 -comp ${comp} \ + mksquashfs nix-path-registration $(cat $closureInfo/store-paths) $out ${pseudoFilesArgs} \ + -no-hardlinks ${lib.optionalString noStrip "-no-strip"} -keep-as-directory -all-root -b 1048576 -comp ${comp} \ -processors $NIX_BUILD_CORES ''; } diff --git a/nixos/modules/virtualisation/lxc-container.nix b/nixos/modules/virtualisation/lxc-container.nix index 1034c699629d..61d7c4cb73fe 100644 --- a/nixos/modules/virtualisation/lxc-container.nix +++ b/nixos/modules/virtualisation/lxc-container.nix @@ -37,7 +37,6 @@ in { ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system ''; - # TODO: build rootfs as squashfs for faster unpack system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix { extraArgs = "--owner=0"; @@ -64,6 +63,23 @@ in { extraCommands = "mkdir -p proc sys dev"; }; + system.build.squashfs = pkgs.callPackage ../../lib/make-squashfs.nix { + fileName = "nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}"; + + noStrip = true; # keep directory structure + comp = "zstd -Xcompression-level 6"; + + storeContents = [config.system.build.toplevel]; + + pseudoFiles = [ + "/sbin d 0755 0 0" + "/sbin/init s 0555 0 0 ${config.system.build.toplevel}/init" + "/dev d 0755 0 0" + "/proc d 0555 0 0" + "/sys d 0555 0 0" + ]; + }; + system.build.installBootLoader = pkgs.writeScript "install-lxd-sbin-init.sh" '' #!${pkgs.runtimeShell} ${pkgs.coreutils}/bin/ln -fs "$1/init" /sbin/init diff --git a/nixos/release.nix b/nixos/release.nix index abaa7ef9a711..60f4cc94399c 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -328,6 +328,21 @@ in rec { ); + lxdContainerImageSquashfs = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system: + + with import ./.. { inherit system; }; + + hydraJob ((import lib/eval-config.nix { + inherit system; + modules = + [ configuration + versionModule + ./maintainers/scripts/lxd/lxd-container-image.nix + ]; + }).config.system.build.squashfs) + + ); + # Metadata for the lxd image lxdContainerMeta = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system: diff --git a/nixos/tests/lxd/container.nix b/nixos/tests/lxd/container.nix index bdaaebfc0028..0ebe73d872f2 100644 --- a/nixos/tests/lxd/container.nix +++ b/nixos/tests/lxd/container.nix @@ -13,6 +13,7 @@ let lxd-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system}; lxd-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system}; + lxd-image-rootfs-squashfs = releases.lxdContainerImageSquashfs.${pkgs.stdenv.hostPlatform.system}; in { name = "lxd-container"; @@ -23,7 +24,7 @@ in { nodes.machine = { lib, ... }: { virtualisation = { - diskSize = 4096; + diskSize = 6144; # Since we're testing `limits.cpu`, we've gotta have a known number of # cores to lean on @@ -65,6 +66,16 @@ in { machine.succeed("echo true | lxc exec container /run/current-system/sw/bin/bash -") machine.succeed("lxc delete -f container") + with subtest("Squashfs image is functional"): + machine.succeed( + "lxc image import ${lxd-image-metadata}/*/*.tar.xz ${lxd-image-rootfs-squashfs} --alias nixos-squashfs" + ) + machine.succeed("lxc launch nixos-squashfs container") + with machine.nested("Waiting for instance to start and be usable"): + retry(instance_is_up) + machine.succeed("echo true | lxc exec container /run/current-system/sw/bin/bash -") + machine.succeed("lxc delete -f container") + with subtest("Container is mounted with lxcfs inside"): machine.succeed("lxc launch nixos container") with machine.nested("Waiting for instance to start and be usable"):