diff options
Diffstat (limited to 'nixos/modules/virtualisation/lxc-container.nix')
-rw-r--r-- | nixos/modules/virtualisation/lxc-container.nix | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/nixos/modules/virtualisation/lxc-container.nix b/nixos/modules/virtualisation/lxc-container.nix new file mode 100644 index 00000000000..9816cc2332f --- /dev/null +++ b/nixos/modules/virtualisation/lxc-container.nix @@ -0,0 +1,174 @@ +{ 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 = [ + ../installer/cd-dvd/channel.nix + ../profiles/minimal.nix + ../profiles/clone-config.nix + ]; + + options = { + virtualisation.lxc = { + templates = mkOption { + description = "Templates for LXD"; + type = types.attrsOf (types.submodule (templateSubmodule)); + default = {}; + example = 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 = { + 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 + + # 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 + ''; + + # Allow the user to login as root without password. + users.users.root.initialHashedPassword = mkOverride 150 ""; + + 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; + }; +} |