git.iko.soy/typeable/nixpkgs
on master help sign in
Merge pull request #120965 from mkg20001/lxd-roundup
commit19781e666325b6803c559ba18d4d4008705c369d authorMaciej Krüger <mkg20001@gmail.com> dateWed 3 Nov 2021, 11:10 (5 years ago) parent8cafc541c31f8d
10 files changed+453−14
nixos/doc/manual/from_md/release-notes/rl-2111.section.xml+19 nixos/doc/manual/release-notes/rl-2111.section.md+4 nixos/maintainers/scripts/lxd/lxd-image-inner.nix+102 nixos/maintainers/scripts/lxd/lxd-image.nix+34 nixos/maintainers/scripts/lxd/nix.tpl+9 nixos/modules/system/boot/systemd.nix+1−1 nixos/modules/virtualisation/lxc-container.nix+161−13 nixos/release.nix+31 nixos/tests/all-tests.nix+1 nixos/tests/lxd-image.nix+91
nixos/doc/manual/from_md/release-notes/rl-2111.section.xml+19
@@ -100,6 +100,25 @@
100100 Notes</link> for details.
101101 </para>
102102 </listitem>
103+ <listitem>
104+ <para>
105+ LXD support was greatly improved:
106+ </para>
107+ <itemizedlist spacing="compact">
108+ <listitem>
109+ <para>
110+ building LXD images from configurations is now directly
111+ possible with just nixpkgs
112+ </para>
113+ </listitem>
114+ <listitem>
115+ <para>
116+ hydra is now building nixOS LXD images that can be used
117+ standalone with full nixos-rebuild support
118+ </para>
119+ </listitem>
120+ </itemizedlist>
121+ </listitem>
103122 </itemizedlist>
104123 </section>
105124 <section xml:id="sec-release-21.11-new-services">
nixos/doc/manual/release-notes/rl-2111.section.md+4
@@ -35,6 +35,10 @@ In addition to numerous new and upgraded packages, this release has the followin
3535
3636- GNOME has been upgraded to 41. Please take a look at their [Release Notes](https://help.gnome.org/misc/release-notes/41.0/) for details.
3737
38+- LXD support was greatly improved:
39+ - building LXD images from configurations is now directly possible with just nixpkgs
40+ - hydra is now building nixOS LXD images that can be used standalone with full nixos-rebuild support
41+
3842## New Services {#sec-release-21.11-new-services}
3943
4044- [btrbk](https://digint.ch/btrbk/index.html), a backup tool for btrfs subvolumes, taking advantage of btrfs specific capabilities to create atomic snapshots and transfer them incrementally to your backup locations. Available as [services.btrbk](options.html#opt-services.brtbk.instances).
nixos/maintainers/scripts/lxd/lxd-image-inner.nixnew file+102
@@ -0,0 +1,102 @@
1+# Edit this configuration file to define what should be installed on
2+# your system. Help is available in the configuration.nix(5) man page
3+# and in the NixOS manual (accessible by running ‘nixos-help’).
4+
5+{ config, pkgs, lib, ... }:
6+
7+with lib;
8+
9+{
10+ imports =
11+ [ # Include the default lxd configuration.
12+ ../../../modules/virtualisation/lxc-container.nix
13+ # Include the container-specific autogenerated configuration.
14+ ./lxd.nix
15+ ];
16+
17+ # networking.hostName = mkForce "nixos"; # Overwrite the hostname.
18+ # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
19+
20+ # Set your time zone.
21+ # time.timeZone = "Europe/Amsterdam";
22+
23+ # The global useDHCP flag is deprecated, therefore explicitly set to false here.
24+ # Per-interface useDHCP will be mandatory in the future, so this generated config
25+ # replicates the default behaviour.
26+ networking.useDHCP = false;
27+ networking.interfaces.eth0.useDHCP = true;
28+
29+ # Configure network proxy if necessary
30+ # networking.proxy.default = "http://user:password@proxy:port/";
31+ # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
32+
33+ # Select internationalisation properties.
34+ # i18n.defaultLocale = "en_US.UTF-8";
35+ # console = {
36+ # font = "Lat2-Terminus16";
37+ # keyMap = "us";
38+ # };
39+
40+ # Enable the X11 windowing system.
41+ # services.xserver.enable = true;
42+
43+ # Configure keymap in X11
44+ # services.xserver.layout = "us";
45+ # services.xserver.xkbOptions = "eurosign:e";
46+
47+ # Enable CUPS to print documents.
48+ # services.printing.enable = true;
49+
50+ # Enable sound.
51+ # sound.enable = true;
52+ # hardware.pulseaudio.enable = true;
53+
54+ # Enable touchpad support (enabled default in most desktopManager).
55+ # services.xserver.libinput.enable = true;
56+
57+ # Define a user account. Don't forget to set a password with ‘passwd’.
58+ # users.users.jane = {
59+ # isNormalUser = true;
60+ # extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
61+ # };
62+
63+ # List packages installed in system profile. To search, run:
64+ # $ nix search wget
65+ # environment.systemPackages = with pkgs; [
66+ # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
67+ # wget
68+ # firefox
69+ # ];
70+
71+ # Some programs need SUID wrappers, can be configured further or are
72+ # started in user sessions.
73+ # programs.mtr.enable = true;
74+ # programs.gnupg.agent = {
75+ # enable = true;
76+ # enableSSHSupport = true;
77+ # };
78+
79+ # List services that you want to enable:
80+
81+ # Enable the OpenSSH daemon.
82+ # services.openssh.enable = true;
83+
84+ # Open ports in the firewall.
85+ # networking.firewall.allowedTCPPorts = [ ... ];
86+ # networking.firewall.allowedUDPPorts = [ ... ];
87+ # Or disable the firewall altogether.
88+ # networking.firewall.enable = false;
89+
90+ # This value determines the NixOS release from which the default
91+ # settings for stateful data, like file locations and database versions
92+ # on your system were taken. It‘s perfectly fine and recommended to leave
93+ # this value at the release version of the first install of this system.
94+ # Before changing this value read the documentation for this option
95+ # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
96+ system.stateVersion = "21.05"; # Did you read the comment?
97+
98+ # As this is intended as a stadalone image, undo some of the minimal profile stuff
99+ documentation.enable = true;
100+ documentation.nixos.enable = true;
101+ environment.noXlibs = false;
102+}
nixos/maintainers/scripts/lxd/lxd-image.nixnew file+34
@@ -0,0 +1,34 @@
1+{ lib, config, pkgs, ... }:
2+
3+with lib;
4+
5+{
6+ imports = [
7+ ../../../modules/virtualisation/lxc-container.nix
8+ ];
9+
10+ virtualisation.lxc.templates.nix = {
11+ enable = true;
12+ target = "/etc/nixos/lxd.nix";
13+ template = ./nix.tpl;
14+ when = [ "create" "copy" ];
15+ };
16+
17+ # copy the config for nixos-rebuild
18+ system.activationScripts.config = ''
19+ if [ ! -e /etc/nixos/configuration.nix ]; then
20+ mkdir -p /etc/nixos
21+ cat ${./lxd-image-inner.nix} > /etc/nixos/configuration.nix
22+ sed 's|../../../modules/virtualisation/lxc-container.nix|<nixpkgs/nixos/modules/virtualisation/lxc-container.nix>|g' -i /etc/nixos/configuration.nix
23+ fi
24+ '';
25+
26+ # Network
27+ networking.useDHCP = false;
28+ networking.interfaces.eth0.useDHCP = true;
29+
30+ # As this is intended as a stadalone image, undo some of the minimal profile stuff
31+ documentation.enable = true;
32+ documentation.nixos.enable = true;
33+ environment.noXlibs = false;
34+}
nixos/maintainers/scripts/lxd/nix.tplnew file+9
@@ -0,0 +1,9 @@
1+{ lib, config, pkgs, ... }:
2+
3+with lib;
4+
5+# WARNING: THIS CONFIGURATION IS AUTOGENERATED AND WILL BE OVERWRITTEN AUTOMATICALLY
6+
7+{
8+ networking.hostName = "{{ container.name }}";
9+}
nixos/modules/system/boot/systemd.nix+1−1
@@ -42,7 +42,7 @@ let
4242 "systemd-udevd-kernel.socket"
4343 "systemd-udevd.service"
4444 "systemd-udev-settle.service"
45− "systemd-udev-trigger.service"
45+ ] ++ (optional (!config.boot.isContainer) "systemd-udev-trigger.service") ++ [
4646 # hwdb.bin is managed by NixOS
4747 # "systemd-hwdb-update.service"
4848
nixos/modules/virtualisation/lxc-container.nix+161−13
@@ -1,26 +1,174 @@
1−{ lib, ... }:
1+{ lib, config, pkgs, ... }:
22
33with lib;
44
5+let
6+ templateSubmodule = { ... }: {
7+ options = {
8+ enable = mkEnableOption "this template";
9+
10+ target = mkOption {
11+ description = "Path in the container";
12+ type = types.path;
13+ };
14+ template = mkOption {
15+ description = ".tpl file for rendering the target";
16+ type = types.path;
17+ };
18+ when = mkOption {
19+ description = "Events which trigger a rewrite (create, copy)";
20+ type = types.listOf (types.str);
21+ };
22+ properties = mkOption {
23+ description = "Additional properties";
24+ type = types.attrs;
25+ default = {};
26+ };
27+ };
28+ };
29+
30+ toYAML = name: data: pkgs.writeText name (generators.toYAML {} data);
31+
32+ cfg = config.virtualisation.lxc;
33+ templates = if cfg.templates != {} then let
34+ list = mapAttrsToList (name: value: { inherit name; } // value)
35+ (filterAttrs (name: value: value.enable) cfg.templates);
36+ in
37+ {
38+ files = map (tpl: {
39+ source = tpl.template;
40+ target = "/templates/${tpl.name}.tpl";
41+ }) list;
42+ properties = listToAttrs (map (tpl: nameValuePair tpl.target {
43+ when = tpl.when;
44+ template = "${tpl.name}.tpl";
45+ properties = tpl.properties;
46+ }) list);
47+ }
48+ else { files = []; properties = {}; };
49+
50+in
551{
652 imports = [
7− ../profiles/docker-container.nix # FIXME, shouldn't include something from profiles/
53+ ../installer/cd-dvd/channel.nix
54+ ../profiles/minimal.nix
55+ ../profiles/clone-config.nix
856 ];
957
10− # Allow the user to login as root without password.
11− users.users.root.initialHashedPassword = mkOverride 150 "";
58+ options = {
59+ virtualisation.lxc = {
60+ templates = mkOption {
61+ description = "Templates for LXD";
62+ type = types.attrsOf (types.submodule (templateSubmodule));
63+ default = {};
64+ example = literalExample ''
65+ {
66+ # create /etc/hostname on container creation
67+ "hostname" = {
68+ enable = true;
69+ target = "/etc/hostname";
70+ template = builtins.writeFile "hostname.tpl" "{{ container.name }}";
71+ when = [ "create" ];
72+ };
73+ # create /etc/nixos/hostname.nix with a configuration for keeping the hostname applied
74+ "hostname-nix" = {
75+ enable = true;
76+ target = "/etc/nixos/hostname.nix";
77+ template = builtins.writeFile "hostname-nix.tpl" "{ ... }: { networking.hostName = "{{ container.name }}"; }";
78+ # copy keeps the file updated when the container is changed
79+ when = [ "create" "copy" ];
80+ };
81+ # copy allow the user to specify a custom configuration.nix
82+ "configuration-nix" = {
83+ enable = true;
84+ target = "/etc/nixos/configuration.nix";
85+ template = builtins.writeFile "configuration-nix" "{{ config_get(\"user.user-data\", properties.default) }}";
86+ when = [ "create" ];
87+ };
88+ };
89+ '';
90+ };
91+ };
92+ };
93+
94+ config = {
95+ boot.isContainer = true;
96+ boot.postBootCommands =
97+ ''
98+ # After booting, register the contents of the Nix store in the Nix
99+ # database.
100+ if [ -f /nix-path-registration ]; then
101+ ${config.nix.package.out}/bin/nix-store --load-db < /nix-path-registration &&
102+ rm /nix-path-registration
103+ fi
104+
105+ # nixos-rebuild also requires a "system" profile
106+ ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
107+ '';
108+
109+ system.build.metadata = pkgs.callPackage ../../lib/make-system-tarball.nix {
110+ contents = [
111+ {
112+ source = toYAML "metadata.yaml" {
113+ architecture = builtins.elemAt (builtins.match "^([a-z0-9_]+).+" (toString pkgs.system)) 0;
114+ creation_date = 1;
115+ properties = {
116+ description = "NixOS ${config.system.nixos.codeName} ${config.system.nixos.label} ${pkgs.system}";
117+ os = "nixos";
118+ release = "${config.system.nixos.codeName}";
119+ };
120+ templates = templates.properties;
121+ };
122+ target = "/metadata.yaml";
123+ }
124+ ] ++ templates.files;
125+ };
12126
13− # Some more help text.
14− services.getty.helpLine =
15− ''
127+ # TODO: build rootfs as squashfs for faster unpack
128+ system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
129+ extraArgs = "--owner=0";
16130
17− Log in as "root" with an empty password.
131+ storeContents = [
132+ {
133+ object = config.system.build.toplevel;
134+ symlink = "none";
135+ }
136+ ];
137+
138+ contents = [
139+ {
140+ source = config.system.build.toplevel + "/init";
141+ target = "/sbin/init";
142+ }
143+ ];
144+
145+ extraCommands = "mkdir -p proc sys dev";
146+ };
147+
148+ # Add the overrides from lxd distrobuilder
149+ systemd.extraConfig = ''
150+ [Service]
151+ ProtectProc=default
152+ ProtectControlGroups=no
153+ ProtectKernelTunables=no
18154 '';
19155
20− # Containers should be light-weight, so start sshd on demand.
21− services.openssh.enable = mkDefault true;
22− services.openssh.startWhenNeeded = mkDefault true;
156+ # Allow the user to login as root without password.
157+ users.users.root.initialHashedPassword = mkOverride 150 "";
158+
159+ system.activationScripts.installInitScript = mkForce ''
160+ ln -fs $systemConfig/init /sbin/init
161+ '';
162+
163+ # Some more help text.
164+ services.getty.helpLine =
165+ ''
166+
167+ Log in as "root" with an empty password.
168+ '';
23169
24− # Allow ssh connections
25− networking.firewall.allowedTCPPorts = [ 22 ];
170+ # Containers should be light-weight, so start sshd on demand.
171+ services.openssh.enable = mkDefault true;
172+ services.openssh.startWhenNeeded = mkDefault true;
173+ };
26174}
nixos/release.nix+31
@@ -251,6 +251,37 @@ in rec {
251251
252252 );
253253
254+ # An image that can be imported into lxd and used for container creation
255+ lxdImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
256+
257+ with import ./.. { inherit system; };
258+
259+ hydraJob ((import lib/eval-config.nix {
260+ inherit system;
261+ modules =
262+ [ configuration
263+ versionModule
264+ ./maintainers/scripts/lxd/lxd-image.nix
265+ ];
266+ }).config.system.build.tarball)
267+
268+ );
269+
270+ # Metadata for the lxd image
271+ lxdMeta = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
272+
273+ with import ./.. { inherit system; };
274+
275+ hydraJob ((import lib/eval-config.nix {
276+ inherit system;
277+ modules =
278+ [ configuration
279+ versionModule
280+ ./maintainers/scripts/lxd/lxd-image.nix
281+ ];
282+ }).config.system.build.metadata)
283+
284+ );
254285
255286 # Ensure that all packages used by the minimal NixOS config end up in the channel.
256287 dummy = forAllSystems (system: pkgs.runCommand "dummy"
nixos/tests/all-tests.nix+1
@@ -236,6 +236,7 @@ in
236236 login = handleTest ./login.nix {};
237237 loki = handleTest ./loki.nix {};
238238 lxd = handleTest ./lxd.nix {};
239+ lxd-image = handleTest ./lxd-image.nix {};
239240 lxd-nftables = handleTest ./lxd-nftables.nix {};
240241 #logstash = handleTest ./logstash.nix {};
241242 lorri = handleTest ./lorri/default.nix {};
nixos/tests/lxd-image.nixnew file+91
@@ -0,0 +1,91 @@
1+# This test ensures that the nixOS lxd images builds and functions properly
2+# It has been extracted from `lxd.nix` to seperate failures of just the image and the lxd software
3+
4+import ./make-test-python.nix ({ pkgs, ...} : let
5+ release = import ../release.nix {
6+ /* configuration = {
7+ environment.systemPackages = with pkgs; [ stdenv ]; # inject stdenv so rebuild test works
8+ }; */
9+ };
10+
11+ metadata = release.lxdMeta.${pkgs.system};
12+ image = release.lxdImage.${pkgs.system};
13+
14+ lxd-config = pkgs.writeText "config.yaml" ''
15+ storage_pools:
16+ - name: default
17+ driver: dir
18+ config:
19+ source: /var/lxd-pool
20+
21+ networks:
22+ - name: lxdbr0
23+ type: bridge
24+ config:
25+ ipv4.address: auto
26+ ipv6.address: none
27+
28+ profiles:
29+ - name: default
30+ devices:
31+ eth0:
32+ name: eth0
33+ network: lxdbr0
34+ type: nic
35+ root:
36+ path: /
37+ pool: default
38+ type: disk
39+ '';
40+in {
41+ name = "lxd-image";
42+
43+ meta = with pkgs.lib.maintainers; {
44+ maintainers = [ mkg20001 ];
45+ };
46+
47+ machine = { lib, ... }: {
48+ virtualisation = {
49+ # OOMs otherwise
50+ memorySize = 1024;
51+ # disk full otherwise
52+ diskSize = 2048;
53+
54+ lxc.lxcfs.enable = true;
55+ lxd.enable = true;
56+ };
57+ };
58+
59+ testScript = ''
60+ machine.wait_for_unit("sockets.target")
61+ machine.wait_for_unit("lxd.service")
62+ machine.wait_for_file("/var/lib/lxd/unix.socket")
63+
64+ # It takes additional second for lxd to settle
65+ machine.sleep(1)
66+
67+ # lxd expects the pool's directory to already exist
68+ machine.succeed("mkdir /var/lxd-pool")
69+
70+ machine.succeed(
71+ "cat ${lxd-config} | lxd init --preseed"
72+ )
73+
74+ # TODO: test custom built container aswell
75+
76+ with subtest("importing container works"):
77+ machine.succeed("lxc image import ${metadata}/*/*.tar.xz ${image}/*/*.tar.xz --alias nixos")
78+
79+ with subtest("launching container works"):
80+ machine.succeed("lxc launch nixos machine -c security.nesting=true")
81+ # make sure machine boots up properly
82+ machine.sleep(5)
83+
84+ with subtest("container shell works"):
85+ machine.succeed("echo true | lxc exec machine /run/current-system/sw/bin/bash -")
86+ machine.succeed("lxc exec machine /run/current-system/sw/bin/true")
87+
88+ # with subtest("rebuilding works"):
89+ # machine.succeed("lxc exec machine /run/current-system/sw/bin/nixos-rebuild switch")
90+ '';
91+})