From 094f2b6c9d87da6348e2517936a3ad907c82d1cf Mon Sep 17 00:00:00 2001 From: Adam Stephens Date: Sat, 10 Aug 2024 12:40:16 -0400 Subject: [PATCH] nixos/incus: add incus-only vm and container images --- .../incus/incus-container-image-inner.nix | 34 +++++++ .../scripts/incus/incus-container-image.nix | 47 +++++++++ .../incus-virtual-machine-image-inner.nix | 34 +++++++ .../incus/incus-virtual-machine-image.nix | 48 ++++++++++ nixos/maintainers/scripts/incus/nix.tpl | 12 +++ .../virtualisation/incus-virtual-machine.nix | 61 ++++++++++++ .../modules/virtualisation/lxc-container.nix | 2 +- nixos/release.nix | 95 +++++++++++++++++++ nixos/tests/incus/container.nix | 6 +- nixos/tests/incus/incusd-options.nix | 6 +- nixos/tests/incus/virtual-machine.nix | 10 +- 11 files changed, 343 insertions(+), 12 deletions(-) create mode 100644 nixos/maintainers/scripts/incus/incus-container-image-inner.nix create mode 100644 nixos/maintainers/scripts/incus/incus-container-image.nix create mode 100644 nixos/maintainers/scripts/incus/incus-virtual-machine-image-inner.nix create mode 100644 nixos/maintainers/scripts/incus/incus-virtual-machine-image.nix create mode 100644 nixos/maintainers/scripts/incus/nix.tpl create mode 100644 nixos/modules/virtualisation/incus-virtual-machine.nix diff --git a/nixos/maintainers/scripts/incus/incus-container-image-inner.nix b/nixos/maintainers/scripts/incus/incus-container-image-inner.nix new file mode 100644 index 000000000000..68979306a610 --- /dev/null +++ b/nixos/maintainers/scripts/incus/incus-container-image-inner.nix @@ -0,0 +1,34 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ modulesPath, ... }: + +{ + imports = [ + # Include the default incus configuration. + "${modulesPath}/virtualisation/lxc-container.nix" + # Include the container-specific autogenerated configuration. + ./incus.nix + ]; + + networking = { + dhcpcd.enable = false; + useDHCP = false; + useHostResolvConf = false; + }; + + systemd.network = { + enable = true; + networks."50-eth0" = { + matchConfig.Name = "eth0"; + networkConfig = { + DHCP = "ipv4"; + IPv6AcceptRA = true; + }; + linkConfig.RequiredForOnline = "routable"; + }; + }; + + system.stateVersion = "@stateVersion@"; # Did you read the comment? +} diff --git a/nixos/maintainers/scripts/incus/incus-container-image.nix b/nixos/maintainers/scripts/incus/incus-container-image.nix new file mode 100644 index 000000000000..63b9353f7ee3 --- /dev/null +++ b/nixos/maintainers/scripts/incus/incus-container-image.nix @@ -0,0 +1,47 @@ +{ lib, pkgs, ... }: + +{ + imports = [ ../../../modules/virtualisation/lxc-container.nix ]; + + virtualisation.lxc.templates.nix = { + enable = true; + target = "/etc/nixos/incus.nix"; + template = ./nix.tpl; + when = [ + "create" + "copy" + ]; + }; + + # copy the config for nixos-rebuild + system.activationScripts.config = + let + config = pkgs.substituteAll { + src = ./incus-container-image-inner.nix; + stateVersion = lib.trivial.release; + }; + in + '' + if [ ! -e /etc/nixos/configuration.nix ]; then + install -m 0644 -D ${config} /etc/nixos/configuration.nix + fi + ''; + + networking = { + dhcpcd.enable = false; + useDHCP = false; + useHostResolvConf = false; + }; + + systemd.network = { + enable = true; + networks."50-eth0" = { + matchConfig.Name = "eth0"; + networkConfig = { + DHCP = "ipv4"; + IPv6AcceptRA = true; + }; + linkConfig.RequiredForOnline = "routable"; + }; + }; +} diff --git a/nixos/maintainers/scripts/incus/incus-virtual-machine-image-inner.nix b/nixos/maintainers/scripts/incus/incus-virtual-machine-image-inner.nix new file mode 100644 index 000000000000..cd176a38988f --- /dev/null +++ b/nixos/maintainers/scripts/incus/incus-virtual-machine-image-inner.nix @@ -0,0 +1,34 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ modulesPath, ... }: + +{ + imports = [ + # Include the default incus configuration. + "${modulesPath}/virtualisation/incus-virtual-machine.nix" + # Include the container-specific autogenerated configuration. + ./incus.nix + ]; + + networking = { + dhcpcd.enable = false; + useDHCP = false; + useHostResolvConf = false; + }; + + systemd.network = { + enable = true; + networks."50-enp5s0" = { + matchConfig.Name = "enp5s0"; + networkConfig = { + DHCP = "ipv4"; + IPv6AcceptRA = true; + }; + linkConfig.RequiredForOnline = "routable"; + }; + }; + + system.stateVersion = "@stateVersion@"; # Did you read the comment? +} diff --git a/nixos/maintainers/scripts/incus/incus-virtual-machine-image.nix b/nixos/maintainers/scripts/incus/incus-virtual-machine-image.nix new file mode 100644 index 000000000000..0742e7d75ac9 --- /dev/null +++ b/nixos/maintainers/scripts/incus/incus-virtual-machine-image.nix @@ -0,0 +1,48 @@ +{ lib, pkgs, ... }: + +{ + imports = [ ../../../modules/virtualisation/incus-virtual-machine.nix ]; + + virtualisation.lxc.templates.nix = { + enable = true; + target = "/etc/nixos/incus.nix"; + template = ./nix.tpl; + when = [ + "create" + "copy" + ]; + }; + + # copy the config for nixos-rebuild + system.activationScripts.config = + let + config = pkgs.substituteAll { + src = ./incus-virtual-machine-image-inner.nix; + stateVersion = lib.trivial.release; + }; + in + '' + if [ ! -e /etc/nixos/configuration.nix ]; then + install -m 0644 -D ${config} /etc/nixos/configuration.nix + fi + ''; + + # Network + networking = { + dhcpcd.enable = false; + useDHCP = false; + useHostResolvConf = false; + }; + + systemd.network = { + enable = true; + networks."50-enp5s0" = { + matchConfig.Name = "enp5s0"; + networkConfig = { + DHCP = "ipv4"; + IPv6AcceptRA = true; + }; + linkConfig.RequiredForOnline = "routable"; + }; + }; +} diff --git a/nixos/maintainers/scripts/incus/nix.tpl b/nixos/maintainers/scripts/incus/nix.tpl new file mode 100644 index 000000000000..38c2fc1ebffb --- /dev/null +++ b/nixos/maintainers/scripts/incus/nix.tpl @@ -0,0 +1,12 @@ +{ + lib, + config, + pkgs, + ... +}: + +# WARNING: THIS CONFIGURATION IS AUTOGENERATED AND WILL BE OVERWRITTEN AUTOMATICALLY + +{ + networking.hostName = "{{ container.name }}"; +} diff --git a/nixos/modules/virtualisation/incus-virtual-machine.nix b/nixos/modules/virtualisation/incus-virtual-machine.nix new file mode 100644 index 000000000000..d51e251aaba9 --- /dev/null +++ b/nixos/modules/virtualisation/incus-virtual-machine.nix @@ -0,0 +1,61 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + serialDevice = if pkgs.stdenv.hostPlatform.isx86 then "ttyS0" else "ttyAMA0"; +in +{ + meta = { + maintainers = lib.teams.lxc.members; + }; + + imports = [ + ./lxc-instance-common.nix + + ../profiles/qemu-guest.nix + ]; + + config = { + system.build.qemuImage = import ../../lib/make-disk-image.nix { + inherit pkgs lib config; + + partitionTableType = "efi"; + format = "qcow2-compressed"; + copyChannel = true; + }; + + fileSystems = { + "/" = { + device = "/dev/disk/by-label/nixos"; + autoResize = true; + fsType = "ext4"; + }; + "/boot" = { + device = "/dev/disk/by-label/ESP"; + fsType = "vfat"; + }; + }; + + boot.growPartition = true; + boot.loader.systemd-boot.enable = true; + + # image building needs to know what device to install bootloader on + boot.loader.grub.device = "/dev/vda"; + + boot.kernelParams = [ + "console=tty1" + "console=${serialDevice}" + ]; + + # CPU hotplug + services.udev.extraRules = '' + SUBSYSTEM=="cpu", CONST{arch}=="x86-64", TEST=="online", ATTR{online}=="0", ATTR{online}="1" + ''; + + virtualisation.incus.agent.enable = lib.mkDefault true; + }; +} diff --git a/nixos/modules/virtualisation/lxc-container.nix b/nixos/modules/virtualisation/lxc-container.nix index 95e3083ff9ed..0b528496bb33 100644 --- a/nixos/modules/virtualisation/lxc-container.nix +++ b/nixos/modules/virtualisation/lxc-container.nix @@ -74,7 +74,7 @@ ]; }; - system.build.installBootLoader = pkgs.writeScript "install-lxd-sbin-init.sh" '' + system.build.installBootLoader = pkgs.writeScript "install-lxc-sbin-init.sh" '' #!${pkgs.runtimeShell} ${pkgs.coreutils}/bin/ln -fs "$1/${initScript}" /sbin/init ''; diff --git a/nixos/release.nix b/nixos/release.nix index 2f31973569bf..eeca73ea4c55 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -318,6 +318,101 @@ in rec { ); + # An image that can be imported into incus and used for container creation + incusContainerImage = + forMatchingSystems + [ + "x86_64-linux" + "aarch64-linux" + ] + ( + system: + with import ./.. { inherit system; }; + + hydraJob ( + (import lib/eval-config.nix { + inherit system; + modules = [ + configuration + versionModule + ./maintainers/scripts/incus/incus-container-image.nix + ]; + }).config.system.build.squashfs + ) + ); + + # Metadata for the incus image + incusContainerMeta = + forMatchingSystems + [ + "x86_64-linux" + "aarch64-linux" + ] + ( + system: + + with import ./.. { inherit system; }; + + hydraJob ( + (import lib/eval-config.nix { + inherit system; + modules = [ + configuration + versionModule + ./maintainers/scripts/incus/incus-container-image.nix + ]; + }).config.system.build.metadata + ) + ); + + # An image that can be imported into incus and used for container creation + incusVirtualMachineImage = + forMatchingSystems + [ + "x86_64-linux" + "aarch64-linux" + ] + ( + system: + + with import ./.. { inherit system; }; + + hydraJob ( + (import lib/eval-config.nix { + inherit system; + modules = [ + configuration + versionModule + ./maintainers/scripts/incus/incus-virtual-machine-image.nix + ]; + }).config.system.build.qemuImage + ) + ); + + # Metadata for the incus image + incusVirtualMachineImageMeta = + forMatchingSystems + [ + "x86_64-linux" + "aarch64-linux" + ] + ( + system: + + with import ./.. { inherit system; }; + + hydraJob ( + (import lib/eval-config.nix { + inherit system; + modules = [ + configuration + versionModule + ./maintainers/scripts/incus/incus-virtual-machine-image.nix + ]; + }).config.system.build.metadata + ) + ); + # An image that can be imported into lxd and used for container creation lxdContainerImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system: diff --git a/nixos/tests/incus/container.nix b/nixos/tests/incus/container.nix index 10262cf2132b..d2b8037cae70 100644 --- a/nixos/tests/incus/container.nix +++ b/nixos/tests/incus/container.nix @@ -11,8 +11,8 @@ let extra; }; - container-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system}; - container-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system}; + container-image-metadata = releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system}; + container-image-rootfs = releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system}; in { inherit name; @@ -61,7 +61,7 @@ in machine.succeed("incus admin init --minimal") with subtest("Container image can be imported"): - machine.succeed("incus image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs}/*/*.tar.xz --alias nixos") + machine.succeed("incus image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs} --alias nixos") with subtest("Container can be launched and managed"): machine.succeed("incus launch nixos container") diff --git a/nixos/tests/incus/incusd-options.nix b/nixos/tests/incus/incusd-options.nix index 7b3a4d726e38..afa1805b9d19 100644 --- a/nixos/tests/incus/incusd-options.nix +++ b/nixos/tests/incus/incusd-options.nix @@ -16,8 +16,8 @@ import ../make-test-python.nix ( }; }; - container-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system}; - container-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system}; + container-image-metadata = releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system}; + container-image-rootfs = releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system}; in { name = "incusd-options"; @@ -87,7 +87,7 @@ import ../make-test-python.nix ( machine.wait_for_unit("incus-preseed.service") with subtest("Container image can be imported"): - machine.succeed("incus image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs}/*/*.tar.xz --alias nixos") + machine.succeed("incus image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs} --alias nixos") with subtest("Container can be launched and managed"): machine.succeed("incus launch nixos container") diff --git a/nixos/tests/incus/virtual-machine.nix b/nixos/tests/incus/virtual-machine.nix index 70e54191d330..f5ac4c8eee1f 100644 --- a/nixos/tests/incus/virtual-machine.nix +++ b/nixos/tests/incus/virtual-machine.nix @@ -11,8 +11,8 @@ let }; }; - vm-image-metadata = releases.lxdVirtualMachineImageMeta.${pkgs.stdenv.hostPlatform.system}; - vm-image-disk = releases.lxdVirtualMachineImage.${pkgs.stdenv.hostPlatform.system}; + vm-image-metadata = releases.incusVirtualMachineImageMeta.${pkgs.stdenv.hostPlatform.system}; + vm-image-disk = releases.incusVirtualMachineImage.${pkgs.stdenv.hostPlatform.system}; instance-name = "instance1"; in @@ -64,10 +64,10 @@ in with machine.nested("Waiting for instance to start and be usable"): retry(instance_is_up) - with subtest("lxd-agent is started"): - machine.succeed("incus exec ${instance-name} systemctl is-active lxd-agent") + with subtest("incus-agent is started"): + machine.succeed("incus exec ${instance-name} systemctl is-active incus-agent") - with subtest("lxd-agent has a valid path"): + with subtest("incus-agent has a valid path"): machine.succeed("incus exec ${instance-name} -- bash -c 'true'") with subtest("guest supports cpu hotplug"):