Merge pull request #120965 from mkg20001/lxd-roundup

This commit is contained in:
Maciej Krüger 2021-11-03 11:10:24 +01:00 committed by GitHub
commit 19781e6663
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 453 additions and 14 deletions

View file

@ -100,6 +100,25 @@
Notes</link> for details.
</para>
</listitem>
<listitem>
<para>
LXD support was greatly improved:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
building LXD images from configurations is now directly
possible with just nixpkgs
</para>
</listitem>
<listitem>
<para>
hydra is now building nixOS LXD images that can be used
standalone with full nixos-rebuild support
</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-release-21.11-new-services">

View file

@ -35,6 +35,10 @@ In addition to numerous new and upgraded packages, this release has the followin
- 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.
- LXD support was greatly improved:
- building LXD images from configurations is now directly possible with just nixpkgs
- hydra is now building nixOS LXD images that can be used standalone with full nixos-rebuild support
## New Services {#sec-release-21.11-new-services}
- [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).

View file

@ -0,0 +1,102 @@
# 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).
{ config, pkgs, lib, ... }:
with lib;
{
imports =
[ # Include the default lxd configuration.
../../../modules/virtualisation/lxc-container.nix
# Include the container-specific autogenerated configuration.
./lxd.nix
];
# networking.hostName = mkForce "nixos"; # Overwrite the hostname.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
# i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# };
# Enable the X11 windowing system.
# services.xserver.enable = true;
# Configure keymap in X11
# services.xserver.layout = "us";
# services.xserver.xkbOptions = "eurosign:e";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# sound.enable = true;
# hardware.pulseaudio.enable = true;
# Enable touchpad support (enabled default in most desktopManager).
# services.xserver.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
# users.users.jane = {
# isNormalUser = true;
# extraGroups = [ "wheel" ]; # Enable sudo for the user.
# };
# List packages installed in system profile. To search, run:
# $ nix search wget
# environment.systemPackages = with pkgs; [
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
# wget
# firefox
# ];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
# services.openssh.enable = true;
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "21.05"; # Did you read the comment?
# As this is intended as a stadalone image, undo some of the minimal profile stuff
documentation.enable = true;
documentation.nixos.enable = true;
environment.noXlibs = false;
}

View file

@ -0,0 +1,34 @@
{ lib, config, pkgs, ... }:
with lib;
{
imports = [
../../../modules/virtualisation/lxc-container.nix
];
virtualisation.lxc.templates.nix = {
enable = true;
target = "/etc/nixos/lxd.nix";
template = ./nix.tpl;
when = [ "create" "copy" ];
};
# copy the config for nixos-rebuild
system.activationScripts.config = ''
if [ ! -e /etc/nixos/configuration.nix ]; then
mkdir -p /etc/nixos
cat ${./lxd-image-inner.nix} > /etc/nixos/configuration.nix
sed 's|../../../modules/virtualisation/lxc-container.nix|<nixpkgs/nixos/modules/virtualisation/lxc-container.nix>|g' -i /etc/nixos/configuration.nix
fi
'';
# Network
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
# As this is intended as a stadalone image, undo some of the minimal profile stuff
documentation.enable = true;
documentation.nixos.enable = true;
environment.noXlibs = false;
}

View file

@ -0,0 +1,9 @@
{ lib, config, pkgs, ... }:
with lib;
# WARNING: THIS CONFIGURATION IS AUTOGENERATED AND WILL BE OVERWRITTEN AUTOMATICALLY
{
networking.hostName = "{{ container.name }}";
}

View file

@ -42,7 +42,7 @@ let
"systemd-udevd-kernel.socket"
"systemd-udevd.service"
"systemd-udev-settle.service"
"systemd-udev-trigger.service"
] ++ (optional (!config.boot.isContainer) "systemd-udev-trigger.service") ++ [
# hwdb.bin is managed by NixOS
# "systemd-hwdb-update.service"

View file

@ -1,26 +1,174 @@
{ lib, ... }:
{ lib, config, pkgs, ... }:
with lib;
let
templateSubmodule = { ... }: {
options = {
enable = mkEnableOption "this template";
target = mkOption {
description = "Path in the container";
type = types.path;
};
template = mkOption {
description = ".tpl file for rendering the target";
type = types.path;
};
when = mkOption {
description = "Events which trigger a rewrite (create, copy)";
type = types.listOf (types.str);
};
properties = mkOption {
description = "Additional properties";
type = types.attrs;
default = {};
};
};
};
toYAML = name: data: pkgs.writeText name (generators.toYAML {} data);
cfg = config.virtualisation.lxc;
templates = if cfg.templates != {} then let
list = mapAttrsToList (name: value: { inherit name; } // value)
(filterAttrs (name: value: value.enable) cfg.templates);
in
{
files = map (tpl: {
source = tpl.template;
target = "/templates/${tpl.name}.tpl";
}) list;
properties = listToAttrs (map (tpl: nameValuePair tpl.target {
when = tpl.when;
template = "${tpl.name}.tpl";
properties = tpl.properties;
}) list);
}
else { files = []; properties = {}; };
in
{
imports = [
../profiles/docker-container.nix # FIXME, shouldn't include something from profiles/
../installer/cd-dvd/channel.nix
../profiles/minimal.nix
../profiles/clone-config.nix
];
# Allow the user to login as root without password.
users.users.root.initialHashedPassword = mkOverride 150 "";
options = {
virtualisation.lxc = {
templates = mkOption {
description = "Templates for LXD";
type = types.attrsOf (types.submodule (templateSubmodule));
default = {};
example = literalExample ''
{
# create /etc/hostname on container creation
"hostname" = {
enable = true;
target = "/etc/hostname";
template = builtins.writeFile "hostname.tpl" "{{ container.name }}";
when = [ "create" ];
};
# create /etc/nixos/hostname.nix with a configuration for keeping the hostname applied
"hostname-nix" = {
enable = true;
target = "/etc/nixos/hostname.nix";
template = builtins.writeFile "hostname-nix.tpl" "{ ... }: { networking.hostName = "{{ container.name }}"; }";
# copy keeps the file updated when the container is changed
when = [ "create" "copy" ];
};
# copy allow the user to specify a custom configuration.nix
"configuration-nix" = {
enable = true;
target = "/etc/nixos/configuration.nix";
template = builtins.writeFile "configuration-nix" "{{ config_get(\"user.user-data\", properties.default) }}";
when = [ "create" ];
};
};
'';
};
};
};
# Some more help text.
services.getty.helpLine =
''
config = {
boot.isContainer = true;
boot.postBootCommands =
''
# After booting, register the contents of the Nix store in the Nix
# database.
if [ -f /nix-path-registration ]; then
${config.nix.package.out}/bin/nix-store --load-db < /nix-path-registration &&
rm /nix-path-registration
fi
Log in as "root" with an empty password.
# nixos-rebuild also requires a "system" profile
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
'';
system.build.metadata = pkgs.callPackage ../../lib/make-system-tarball.nix {
contents = [
{
source = toYAML "metadata.yaml" {
architecture = builtins.elemAt (builtins.match "^([a-z0-9_]+).+" (toString pkgs.system)) 0;
creation_date = 1;
properties = {
description = "NixOS ${config.system.nixos.codeName} ${config.system.nixos.label} ${pkgs.system}";
os = "nixos";
release = "${config.system.nixos.codeName}";
};
templates = templates.properties;
};
target = "/metadata.yaml";
}
] ++ templates.files;
};
# TODO: build rootfs as squashfs for faster unpack
system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
extraArgs = "--owner=0";
storeContents = [
{
object = config.system.build.toplevel;
symlink = "none";
}
];
contents = [
{
source = config.system.build.toplevel + "/init";
target = "/sbin/init";
}
];
extraCommands = "mkdir -p proc sys dev";
};
# Add the overrides from lxd distrobuilder
systemd.extraConfig = ''
[Service]
ProtectProc=default
ProtectControlGroups=no
ProtectKernelTunables=no
'';
# Containers should be light-weight, so start sshd on demand.
services.openssh.enable = mkDefault true;
services.openssh.startWhenNeeded = mkDefault true;
# Allow the user to login as root without password.
users.users.root.initialHashedPassword = mkOverride 150 "";
# Allow ssh connections
networking.firewall.allowedTCPPorts = [ 22 ];
system.activationScripts.installInitScript = mkForce ''
ln -fs $systemConfig/init /sbin/init
'';
# Some more help text.
services.getty.helpLine =
''
Log in as "root" with an empty password.
'';
# Containers should be light-weight, so start sshd on demand.
services.openssh.enable = mkDefault true;
services.openssh.startWhenNeeded = mkDefault true;
};
}

View file

@ -251,6 +251,37 @@ in rec {
);
# An image that can be imported into lxd and used for container creation
lxdImage = 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-image.nix
];
}).config.system.build.tarball)
);
# Metadata for the lxd image
lxdMeta = 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-image.nix
];
}).config.system.build.metadata)
);
# Ensure that all packages used by the minimal NixOS config end up in the channel.
dummy = forAllSystems (system: pkgs.runCommand "dummy"

View file

@ -236,6 +236,7 @@ in
login = handleTest ./login.nix {};
loki = handleTest ./loki.nix {};
lxd = handleTest ./lxd.nix {};
lxd-image = handleTest ./lxd-image.nix {};
lxd-nftables = handleTest ./lxd-nftables.nix {};
#logstash = handleTest ./logstash.nix {};
lorri = handleTest ./lorri/default.nix {};

91
nixos/tests/lxd-image.nix Normal file
View file

@ -0,0 +1,91 @@
# This test ensures that the nixOS lxd images builds and functions properly
# It has been extracted from `lxd.nix` to seperate failures of just the image and the lxd software
import ./make-test-python.nix ({ pkgs, ...} : let
release = import ../release.nix {
/* configuration = {
environment.systemPackages = with pkgs; [ stdenv ]; # inject stdenv so rebuild test works
}; */
};
metadata = release.lxdMeta.${pkgs.system};
image = release.lxdImage.${pkgs.system};
lxd-config = pkgs.writeText "config.yaml" ''
storage_pools:
- name: default
driver: dir
config:
source: /var/lxd-pool
networks:
- name: lxdbr0
type: bridge
config:
ipv4.address: auto
ipv6.address: none
profiles:
- name: default
devices:
eth0:
name: eth0
network: lxdbr0
type: nic
root:
path: /
pool: default
type: disk
'';
in {
name = "lxd-image";
meta = with pkgs.lib.maintainers; {
maintainers = [ mkg20001 ];
};
machine = { lib, ... }: {
virtualisation = {
# OOMs otherwise
memorySize = 1024;
# disk full otherwise
diskSize = 2048;
lxc.lxcfs.enable = true;
lxd.enable = true;
};
};
testScript = ''
machine.wait_for_unit("sockets.target")
machine.wait_for_unit("lxd.service")
machine.wait_for_file("/var/lib/lxd/unix.socket")
# It takes additional second for lxd to settle
machine.sleep(1)
# lxd expects the pool's directory to already exist
machine.succeed("mkdir /var/lxd-pool")
machine.succeed(
"cat ${lxd-config} | lxd init --preseed"
)
# TODO: test custom built container aswell
with subtest("importing container works"):
machine.succeed("lxc image import ${metadata}/*/*.tar.xz ${image}/*/*.tar.xz --alias nixos")
with subtest("launching container works"):
machine.succeed("lxc launch nixos machine -c security.nesting=true")
# make sure machine boots up properly
machine.sleep(5)
with subtest("container shell works"):
machine.succeed("echo true | lxc exec machine /run/current-system/sw/bin/bash -")
machine.succeed("lxc exec machine /run/current-system/sw/bin/true")
# with subtest("rebuilding works"):
# machine.succeed("lxc exec machine /run/current-system/sw/bin/nixos-rebuild switch")
'';
})