@@ -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}