vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / system / cloud-init.nix
blob7148d62b90842a21d16932f3482ecb44a4b7a2f3
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.cloud-init;
7   path = with pkgs; [
8     cloud-init
9     iproute2
10     nettools
11     openssh
12     shadow
13     util-linux
14     busybox
15   ]
16   ++ optional cfg.btrfs.enable btrfs-progs
17   ++ optional cfg.ext4.enable e2fsprogs
18   ++ optional cfg.xfs.enable xfsprogs
19   ++ cfg.extraPackages
20   ;
21   hasFs = fsName: lib.any (fs: fs.fsType == fsName) (lib.attrValues config.fileSystems);
22   settingsFormat = pkgs.formats.yaml { };
23   cfgfile = settingsFormat.generate "cloud.cfg" cfg.settings;
26   options = {
27     services.cloud-init = {
28       enable = mkOption {
29         type = types.bool;
30         default = false;
31         description = ''
32           Enable the cloud-init service. This services reads
33           configuration metadata in a cloud environment and configures
34           the machine according to this metadata.
36           This configuration is not completely compatible with the
37           NixOS way of doing configuration, as configuration done by
38           cloud-init might be overridden by a subsequent nixos-rebuild
39           call. However, some parts of cloud-init fall outside of
40           NixOS's responsibility, like filesystem resizing and ssh
41           public key provisioning, and cloud-init is useful for that
42           parts. Thus, be wary that using cloud-init in NixOS might
43           come as some cost.
44         '';
45       };
47       btrfs.enable = mkOption {
48         type = types.bool;
49         default = hasFs "btrfs";
50         defaultText = literalExpression ''hasFs "btrfs"'';
51         description = ''
52           Allow the cloud-init service to operate `btrfs` filesystem.
53         '';
54       };
56       ext4.enable = mkOption {
57         type = types.bool;
58         default = hasFs "ext4";
59         defaultText = literalExpression ''hasFs "ext4"'';
60         description = ''
61           Allow the cloud-init service to operate `ext4` filesystem.
62         '';
63       };
65       xfs.enable = mkOption {
66         type = types.bool;
67         default = hasFs "xfs";
68         defaultText = literalExpression ''hasFs "xfs"'';
69         description = ''
70           Allow the cloud-init service to operate `xfs` filesystem.
71         '';
72       };
74       network.enable = mkOption {
75         type = types.bool;
76         default = false;
77         description = ''
78           Allow the cloud-init service to configure network interfaces
79           through systemd-networkd.
80         '';
81       };
83       extraPackages = mkOption {
84         type = types.listOf types.package;
85         default = [ ];
86         description = ''
87           List of additional packages to be available within cloud-init jobs.
88         '';
89       };
91       settings = mkOption {
92         description = ''
93           Structured cloud-init configuration.
94         '';
95         type = types.submodule {
96           freeformType = settingsFormat.type;
97         };
98         default = { };
99       };
101       config = mkOption {
102         type = types.str;
103         default = "";
104         description = ''
105           raw cloud-init configuration.
107           Takes precedence over the `settings` option if set.
108         '';
109       };
111     };
113   };
115   config = mkIf cfg.enable {
116     services.cloud-init.settings = {
117       system_info = mkDefault {
118         distro = "nixos";
119         network = {
120           renderers = [ "networkd" ];
121         };
122       };
124       users = mkDefault [ "root" ];
125       disable_root = mkDefault false;
126       preserve_hostname = mkDefault false;
128       cloud_init_modules = mkDefault [
129         "migrator"
130         "seed_random"
131         "bootcmd"
132         "write-files"
133         "growpart"
134         "resizefs"
135         "update_hostname"
136         "resolv_conf"
137         "ca-certs"
138         "rsyslog"
139         "users-groups"
140       ];
142       cloud_config_modules = mkDefault [
143         "disk_setup"
144         "mounts"
145         "ssh-import-id"
146         "set-passwords"
147         "timezone"
148         "disable-ec2-metadata"
149         "runcmd"
150         "ssh"
151       ];
153       cloud_final_modules = mkDefault [
154         "rightscale_userdata"
155         "scripts-vendor"
156         "scripts-per-once"
157         "scripts-per-boot"
158         "scripts-per-instance"
159         "scripts-user"
160         "ssh-authkey-fingerprints"
161         "keys-to-console"
162         "phone-home"
163         "final-message"
164         "power-state-change"
165       ];
166     };
168     environment.etc."cloud/cloud.cfg" =
169       if cfg.config == "" then
170         { source = cfgfile; }
171       else
172         { text = cfg.config; }
173     ;
175     systemd.network.enable = mkIf cfg.network.enable true;
177     systemd.services.cloud-init-local = {
178       description = "Initial cloud-init job (pre-networking)";
179       wantedBy = [ "multi-user.target" ];
180       # In certain environments (AWS for example), cloud-init-local will
181       # first configure an IP through DHCP, and later delete it.
182       # This can cause race conditions with anything else trying to set IP through DHCP.
183       before = [ "systemd-networkd.service" "dhcpcd.service" ];
184       path = path;
185       serviceConfig = {
186         Type = "oneshot";
187         ExecStart = "${pkgs.cloud-init}/bin/cloud-init init --local";
188         RemainAfterExit = "yes";
189         TimeoutSec = "infinity";
190         StandardOutput = "journal+console";
191       };
192     };
194     systemd.services.cloud-init = {
195       description = "Initial cloud-init job (metadata service crawler)";
196       wantedBy = [ "multi-user.target" ];
197       wants = [
198         "network-online.target"
199         "cloud-init-local.service"
200         "sshd.service"
201         "sshd-keygen.service"
202       ];
203       after = [ "network-online.target" "cloud-init-local.service" ];
204       before = [ "sshd.service" "sshd-keygen.service" ];
205       requires = [ "network.target" ];
206       path = path;
207       serviceConfig = {
208         Type = "oneshot";
209         ExecStart = "${pkgs.cloud-init}/bin/cloud-init init";
210         RemainAfterExit = "yes";
211         TimeoutSec = "infinity";
212         StandardOutput = "journal+console";
213       };
214     };
216     systemd.services.cloud-config = {
217       description = "Apply the settings specified in cloud-config";
218       wantedBy = [ "multi-user.target" ];
219       wants = [ "network-online.target" ];
220       after = [ "network-online.target" "cloud-config.target" ];
222       path = path;
223       serviceConfig = {
224         Type = "oneshot";
225         ExecStart = "${pkgs.cloud-init}/bin/cloud-init modules --mode=config";
226         RemainAfterExit = "yes";
227         TimeoutSec = "infinity";
228         StandardOutput = "journal+console";
229       };
230     };
232     systemd.services.cloud-final = {
233       description = "Execute cloud user/final scripts";
234       wantedBy = [ "multi-user.target" ];
235       wants = [ "network-online.target" ];
236       after = [ "network-online.target" "cloud-config.service" "rc-local.service" ];
237       requires = [ "cloud-config.target" ];
238       path = path;
239       serviceConfig = {
240         Type = "oneshot";
241         ExecStart = "${pkgs.cloud-init}/bin/cloud-init modules --mode=final";
242         RemainAfterExit = "yes";
243         TimeoutSec = "infinity";
244         StandardOutput = "journal+console";
245       };
246     };
248     systemd.targets.cloud-config = {
249       description = "Cloud-config availability";
250       requires = [ "cloud-init-local.service" "cloud-init.service" ];
251     };
252   };
254   meta.maintainers = [ maintainers.zimbatm ];