nixos/lxd: add virtual-machine support, image and module
This commit is contained in:
parent
73982ef92a
commit
efd1605be6
15 changed files with 365 additions and 232 deletions
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
- Support for WiFi6 (IEEE 802.11ax) and WPA3-SAE-PK was enabled in the `hostapd` package, along with a significant rework of the hostapd module.
|
- Support for WiFi6 (IEEE 802.11ax) and WPA3-SAE-PK was enabled in the `hostapd` package, along with a significant rework of the hostapd module.
|
||||||
|
|
||||||
|
- LXD now supports virtual machine instances to complement the existing container support
|
||||||
|
|
||||||
## New Services {#sec-release-23.11-new-services}
|
## New Services {#sec-release-23.11-new-services}
|
||||||
|
|
||||||
- [MCHPRS](https://github.com/MCHPR/MCHPRS), a multithreaded Minecraft server built for redstone. Available as [services.mchprs](#opt-services.mchprs.enable).
|
- [MCHPRS](https://github.com/MCHPR/MCHPRS), a multithreaded Minecraft server built for redstone. Available as [services.mchprs](#opt-services.mchprs.enable).
|
||||||
|
|
20
nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix
Normal file
20
nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# 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, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports =
|
||||||
|
[
|
||||||
|
# Include the default lxd configuration.
|
||||||
|
../../../modules/virtualisation/lxc-container.nix
|
||||||
|
# Include the container-specific autogenerated configuration.
|
||||||
|
./lxd.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.interfaces.eth0.useDHCP = true;
|
||||||
|
|
||||||
|
system.stateVersion = "21.05"; # Did you read the comment?
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
{ lib, config, pkgs, ... }:
|
{ lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
@ -16,8 +16,8 @@
|
||||||
system.activationScripts.config = ''
|
system.activationScripts.config = ''
|
||||||
if [ ! -e /etc/nixos/configuration.nix ]; then
|
if [ ! -e /etc/nixos/configuration.nix ]; then
|
||||||
mkdir -p /etc/nixos
|
mkdir -p /etc/nixos
|
||||||
cat ${./lxd-image-inner.nix} > /etc/nixos/configuration.nix
|
cat ${./lxd-container-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
|
${lib.getExe pkgs.gnused} 's|../../../modules/virtualisation/lxc-container.nix|<nixpkgs/nixos/modules/virtualisation/lxc-container.nix>|g' -i /etc/nixos/configuration.nix
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
# 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, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
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.alice = {
|
|
||||||
# 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. It’s 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?
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# 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, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports =
|
||||||
|
[
|
||||||
|
# Include the default lxd configuration.
|
||||||
|
../../../modules/virtualisation/lxd-virtual-machine.nix
|
||||||
|
# Include the container-specific autogenerated configuration.
|
||||||
|
./lxd.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.interfaces.eth0.useDHCP = true;
|
||||||
|
|
||||||
|
system.stateVersion = "23.05"; # Did you read the comment?
|
||||||
|
}
|
27
nixos/maintainers/scripts/lxd/lxd-virtual-machine-image.nix
Normal file
27
nixos/maintainers/scripts/lxd/lxd-virtual-machine-image.nix
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{ lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
../../../modules/virtualisation/lxd-virtual-machine.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-virtual-machine-image-inner.nix} > /etc/nixos/configuration.nix
|
||||||
|
${lib.getExe pkgs.gnused} 's|../../../modules/virtualisation/lxd-virtual-machine.nix|<nixpkgs/nixos/modules/virtualisation/lxd-virtual-machine.nix>|g' -i /etc/nixos/configuration.nix
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Network
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.interfaces.enp5s0.useDHCP = true;
|
||||||
|
}
|
|
@ -1,96 +1,16 @@
|
||||||
{ lib, config, pkgs, ... }:
|
{ lib, config, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
let
|
||||||
templateSubmodule = { ... }: {
|
|
||||||
options = {
|
|
||||||
enable = mkEnableOption (lib.mdDoc "this template");
|
|
||||||
|
|
||||||
target = mkOption {
|
|
||||||
description = lib.mdDoc "Path in the container";
|
|
||||||
type = types.path;
|
|
||||||
};
|
|
||||||
template = mkOption {
|
|
||||||
description = lib.mdDoc ".tpl file for rendering the target";
|
|
||||||
type = types.path;
|
|
||||||
};
|
|
||||||
when = mkOption {
|
|
||||||
description = lib.mdDoc "Events which trigger a rewrite (create, copy)";
|
|
||||||
type = types.listOf (types.str);
|
|
||||||
};
|
|
||||||
properties = mkOption {
|
|
||||||
description = lib.mdDoc "Additional properties";
|
|
||||||
type = types.attrs;
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
toYAML = name: data: pkgs.writeText name (generators.toYAML {} data);
|
|
||||||
|
|
||||||
cfg = config.virtualisation.lxc;
|
cfg = config.virtualisation.lxc;
|
||||||
templates = if cfg.templates != {} then let
|
in {
|
||||||
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 = [
|
imports = [
|
||||||
../installer/cd-dvd/channel.nix
|
./lxc-instance-common.nix
|
||||||
../profiles/clone-config.nix
|
|
||||||
../profiles/minimal.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
virtualisation.lxc = {
|
virtualisation.lxc = {
|
||||||
templates = mkOption {
|
privilegedContainer = lib.mkOption {
|
||||||
description = lib.mdDoc "Templates for LXD";
|
type = lib.types.bool;
|
||||||
type = types.attrsOf (types.submodule (templateSubmodule));
|
|
||||||
default = {};
|
|
||||||
example = literalExpression ''
|
|
||||||
{
|
|
||||||
# create /etc/hostname on container creation. also requires networking.hostName = "" to be set
|
|
||||||
"hostname" = {
|
|
||||||
enable = true;
|
|
||||||
target = "/etc/hostname";
|
|
||||||
template = builtins.toFile "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.toFile "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.toFile "configuration-nix" "{{ config_get(\"user.user-data\", properties.default) }}";
|
|
||||||
when = [ "create" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
privilegedContainer = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
default = false;
|
||||||
description = lib.mdDoc ''
|
description = lib.mdDoc ''
|
||||||
Whether this LXC container will be running as a privileged container or not. If set to `true` then
|
Whether this LXC container will be running as a privileged container or not. If set to `true` then
|
||||||
|
@ -116,24 +36,6 @@ in
|
||||||
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
|
${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 = "${config.system.nixos.distroName} ${config.system.nixos.codeName} ${config.system.nixos.label} ${pkgs.system}";
|
|
||||||
os = "${config.system.nixos.distroId}";
|
|
||||||
release = "${config.system.nixos.codeName}";
|
|
||||||
};
|
|
||||||
templates = templates.properties;
|
|
||||||
};
|
|
||||||
target = "/metadata.yaml";
|
|
||||||
}
|
|
||||||
] ++ templates.files;
|
|
||||||
};
|
|
||||||
|
|
||||||
# TODO: build rootfs as squashfs for faster unpack
|
# TODO: build rootfs as squashfs for faster unpack
|
||||||
system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
|
system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
|
||||||
extraArgs = "--owner=0";
|
extraArgs = "--owner=0";
|
||||||
|
@ -180,7 +82,7 @@ in
|
||||||
ProtectKernelTunables=no
|
ProtectKernelTunables=no
|
||||||
NoNewPrivileges=no
|
NoNewPrivileges=no
|
||||||
LoadCredential=
|
LoadCredential=
|
||||||
'' + optionalString cfg.privilegedContainer ''
|
'' + lib.optionalString cfg.privilegedContainer ''
|
||||||
# Additional settings for privileged containers
|
# Additional settings for privileged containers
|
||||||
ProtectHome=no
|
ProtectHome=no
|
||||||
ProtectSystem=no
|
ProtectSystem=no
|
||||||
|
@ -193,28 +95,8 @@ in
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
# Allow the user to login as root without password.
|
system.activationScripts.installInitScript = lib.mkForce ''
|
||||||
users.users.root.initialHashedPassword = mkOverride 150 "";
|
|
||||||
|
|
||||||
system.activationScripts.installInitScript = mkForce ''
|
|
||||||
ln -fs $systemConfig/init /sbin/init
|
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;
|
|
||||||
|
|
||||||
# As this is intended as a standalone image, undo some of the minimal profile stuff
|
|
||||||
environment.noXlibs = false;
|
|
||||||
documentation.enable = true;
|
|
||||||
documentation.nixos.enable = true;
|
|
||||||
services.logrotate.enable = true;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
104
nixos/modules/virtualisation/lxc-image-metadata.nix
Normal file
104
nixos/modules/virtualisation/lxc-image-metadata.nix
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
{ lib, config, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
templateSubmodule = {...}: {
|
||||||
|
options = {
|
||||||
|
enable = lib.mkEnableOption "this template";
|
||||||
|
|
||||||
|
target = lib.mkOption {
|
||||||
|
description = "Path in the container";
|
||||||
|
type = lib.types.path;
|
||||||
|
};
|
||||||
|
template = lib.mkOption {
|
||||||
|
description = ".tpl file for rendering the target";
|
||||||
|
type = lib.types.path;
|
||||||
|
};
|
||||||
|
when = lib.mkOption {
|
||||||
|
description = "Events which trigger a rewrite (create, copy)";
|
||||||
|
type = lib.types.listOf (lib.types.str);
|
||||||
|
};
|
||||||
|
properties = lib.mkOption {
|
||||||
|
description = "Additional properties";
|
||||||
|
type = lib.types.attrs;
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
toYAML = name: data: pkgs.writeText name (lib.generators.toYAML {} data);
|
||||||
|
|
||||||
|
cfg = config.virtualisation.lxc;
|
||||||
|
templates = if cfg.templates != {} then let
|
||||||
|
list = lib.mapAttrsToList (name: value: { inherit name; } // value)
|
||||||
|
(lib.filterAttrs (name: value: value.enable) cfg.templates);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
files = map (tpl: {
|
||||||
|
source = tpl.template;
|
||||||
|
target = "/templates/${tpl.name}.tpl";
|
||||||
|
}) list;
|
||||||
|
properties = lib.listToAttrs (map (tpl: lib.nameValuePair tpl.target {
|
||||||
|
when = tpl.when;
|
||||||
|
template = "${tpl.name}.tpl";
|
||||||
|
properties = tpl.properties;
|
||||||
|
}) list);
|
||||||
|
}
|
||||||
|
else { files = []; properties = {}; };
|
||||||
|
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
virtualisation.lxc = {
|
||||||
|
templates = lib.mkOption {
|
||||||
|
description = "Templates for LXD";
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule templateSubmodule);
|
||||||
|
default = {};
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
{
|
||||||
|
# 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" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
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 = "${config.system.nixos.distroName} ${config.system.nixos.codeName} ${config.system.nixos.label} ${pkgs.system}";
|
||||||
|
os = "${config.system.nixos.distroId}";
|
||||||
|
release = "${config.system.nixos.codeName}";
|
||||||
|
};
|
||||||
|
templates = templates.properties;
|
||||||
|
};
|
||||||
|
target = "/metadata.yaml";
|
||||||
|
}
|
||||||
|
] ++ templates.files;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
30
nixos/modules/virtualisation/lxc-instance-common.nix
Normal file
30
nixos/modules/virtualisation/lxc-instance-common.nix
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{lib, ...}:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./lxc-image-metadata.nix
|
||||||
|
|
||||||
|
../installer/cd-dvd/channel.nix
|
||||||
|
../profiles/clone-config.nix
|
||||||
|
../profiles/minimal.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
# Allow the user to login as root without password.
|
||||||
|
users.users.root.initialHashedPassword = lib.mkOverride 150 "";
|
||||||
|
|
||||||
|
# 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 = lib.mkDefault true;
|
||||||
|
services.openssh.startWhenNeeded = lib.mkDefault true;
|
||||||
|
|
||||||
|
# As this is intended as a standalone image, undo some of the minimal profile stuff
|
||||||
|
environment.noXlibs = false;
|
||||||
|
documentation.enable = true;
|
||||||
|
documentation.nixos.enable = true;
|
||||||
|
services.logrotate.enable = true;
|
||||||
|
}
|
46
nixos/modules/virtualisation/lxd-virtual-machine.nix
Normal file
46
nixos/modules/virtualisation/lxd-virtual-machine.nix
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
serialDevice =
|
||||||
|
if pkgs.stdenv.hostPlatform.isx86
|
||||||
|
then "ttyS0"
|
||||||
|
else "ttyAMA0"; # aarch64
|
||||||
|
in {
|
||||||
|
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}"];
|
||||||
|
|
||||||
|
virtualisation.lxd.agent.enable = lib.mkDefault true;
|
||||||
|
};
|
||||||
|
}
|
|
@ -196,7 +196,7 @@ in {
|
||||||
"kernel.keys.maxkeys" = 2000;
|
"kernel.keys.maxkeys" = 2000;
|
||||||
};
|
};
|
||||||
|
|
||||||
boot.kernelModules = [ "veth" "xt_comment" "xt_CHECKSUM" "xt_MASQUERADE" ]
|
boot.kernelModules = [ "veth" "xt_comment" "xt_CHECKSUM" "xt_MASQUERADE" "vhost_vsock" ]
|
||||||
++ optionals (!config.networking.nftables.enable) [ "iptable_mangle" ];
|
++ optionals (!config.networking.nftables.enable) [ "iptable_mangle" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,7 +310,7 @@ in rec {
|
||||||
);
|
);
|
||||||
|
|
||||||
# An image that can be imported into lxd and used for container creation
|
# An image that can be imported into lxd and used for container creation
|
||||||
lxdImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
|
lxdContainerImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
|
||||||
|
|
||||||
with import ./.. { inherit system; };
|
with import ./.. { inherit system; };
|
||||||
|
|
||||||
|
@ -319,14 +319,14 @@ in rec {
|
||||||
modules =
|
modules =
|
||||||
[ configuration
|
[ configuration
|
||||||
versionModule
|
versionModule
|
||||||
./maintainers/scripts/lxd/lxd-image.nix
|
./maintainers/scripts/lxd/lxd-container-image.nix
|
||||||
];
|
];
|
||||||
}).config.system.build.tarball)
|
}).config.system.build.tarball)
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
# Metadata for the lxd image
|
# Metadata for the lxd image
|
||||||
lxdMeta = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
|
lxdContainerMeta = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
|
||||||
|
|
||||||
with import ./.. { inherit system; };
|
with import ./.. { inherit system; };
|
||||||
|
|
||||||
|
@ -335,7 +335,39 @@ in rec {
|
||||||
modules =
|
modules =
|
||||||
[ configuration
|
[ configuration
|
||||||
versionModule
|
versionModule
|
||||||
./maintainers/scripts/lxd/lxd-image.nix
|
./maintainers/scripts/lxd/lxd-container-image.nix
|
||||||
|
];
|
||||||
|
}).config.system.build.metadata)
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
# An image that can be imported into lxd and used for container creation
|
||||||
|
lxdVirtualMachineImage = 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-virtual-machine-image.nix
|
||||||
|
];
|
||||||
|
}).config.system.build.qemuImage)
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
# Metadata for the lxd image
|
||||||
|
lxdVirtualMachineImageMeta = 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-virtual-machine-image.nix
|
||||||
];
|
];
|
||||||
}).config.system.build.metadata)
|
}).config.system.build.metadata)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import ../make-test-python.nix ({ pkgs, lib, ... } :
|
import ../make-test-python.nix ({ pkgs, lib, ... } :
|
||||||
|
|
||||||
let
|
let
|
||||||
lxd-image = import ../../release.nix {
|
releases = import ../../release.nix {
|
||||||
configuration = {
|
configuration = {
|
||||||
# Building documentation makes the test unnecessarily take a longer time:
|
# Building documentation makes the test unnecessarily take a longer time:
|
||||||
documentation.enable = lib.mkForce false;
|
documentation.enable = lib.mkForce false;
|
||||||
|
@ -11,14 +11,14 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
lxd-image-metadata = lxd-image.lxdMeta.${pkgs.stdenv.hostPlatform.system};
|
lxd-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system};
|
||||||
lxd-image-rootfs = lxd-image.lxdImage.${pkgs.stdenv.hostPlatform.system};
|
lxd-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system};
|
||||||
|
|
||||||
in {
|
in {
|
||||||
name = "lxd";
|
name = "lxd-container";
|
||||||
|
|
||||||
meta = with pkgs.lib.maintainers; {
|
meta = with pkgs.lib.maintainers; {
|
||||||
maintainers = [ patryk27 ];
|
maintainers = [ patryk27 adamcstephens ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes.machine = { lib, ... }: {
|
nodes.machine = { lib, ... }: {
|
||||||
|
|
|
@ -6,4 +6,5 @@
|
||||||
container = import ./container.nix {inherit system pkgs;};
|
container = import ./container.nix {inherit system pkgs;};
|
||||||
nftables = import ./nftables.nix {inherit system pkgs;};
|
nftables = import ./nftables.nix {inherit system pkgs;};
|
||||||
ui = import ./ui.nix {inherit system pkgs;};
|
ui = import ./ui.nix {inherit system pkgs;};
|
||||||
|
virtual-machine = import ./virtual-machine.nix { inherit system pkgs; };
|
||||||
}
|
}
|
||||||
|
|
64
nixos/tests/lxd/virtual-machine.nix
Normal file
64
nixos/tests/lxd/virtual-machine.nix
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import ../make-test-python.nix ({ pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
releases = import ../../release.nix {
|
||||||
|
configuration = {
|
||||||
|
# Building documentation makes the test unnecessarily take a longer time:
|
||||||
|
documentation.enable = lib.mkForce false;
|
||||||
|
|
||||||
|
# Our tests require `grep` & friends:
|
||||||
|
environment.systemPackages = with pkgs; [busybox];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
lxd-image-metadata = releases.lxdVirtualMachineImageMeta.${pkgs.stdenv.hostPlatform.system};
|
||||||
|
lxd-image-disk = releases.lxdVirtualMachineImage.${pkgs.stdenv.hostPlatform.system};
|
||||||
|
|
||||||
|
instance-name = "instance1";
|
||||||
|
in {
|
||||||
|
name = "lxd-virtual-machine";
|
||||||
|
|
||||||
|
meta = with pkgs.lib.maintainers; {
|
||||||
|
maintainers = [adamcstephens];
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.machine = {lib, ...}: {
|
||||||
|
virtualisation = {
|
||||||
|
diskSize = 4096;
|
||||||
|
|
||||||
|
cores = 2;
|
||||||
|
|
||||||
|
# Ensure we have enough memory for the nested virtual machine
|
||||||
|
memorySize = 1024;
|
||||||
|
|
||||||
|
lxc.lxcfs.enable = true;
|
||||||
|
lxd.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = ''
|
||||||
|
def instance_is_up(_) -> bool:
|
||||||
|
status, _ = machine.execute("lxc exec ${instance-name} --disable-stdin --force-interactive /run/current-system/sw/bin/true")
|
||||||
|
return status == 0
|
||||||
|
|
||||||
|
machine.wait_for_unit("sockets.target")
|
||||||
|
machine.wait_for_unit("lxd.service")
|
||||||
|
machine.wait_for_file("/var/lib/lxd/unix.socket")
|
||||||
|
|
||||||
|
# Wait for lxd to settle
|
||||||
|
machine.succeed("lxd waitready")
|
||||||
|
|
||||||
|
machine.succeed("lxd init --minimal")
|
||||||
|
|
||||||
|
with subtest("virtual-machine image can be imported"):
|
||||||
|
machine.succeed("lxc image import ${lxd-image-metadata}/*/*.tar.xz ${lxd-image-disk}/nixos.qcow2 --alias nixos")
|
||||||
|
|
||||||
|
with subtest("virtual-machine can be launched and become available"):
|
||||||
|
machine.succeed("lxc launch nixos ${instance-name} --vm --config limits.memory=512MB --config security.secureboot=false")
|
||||||
|
with machine.nested("Waiting for instance to start and be usable"):
|
||||||
|
retry(instance_is_up)
|
||||||
|
|
||||||
|
with subtest("lxd-agent is started"):
|
||||||
|
machine.succeed("lxc exec ${instance-name} systemctl is-active lxd-agent")
|
||||||
|
'';
|
||||||
|
})
|
Loading…
Reference in a new issue