1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let cfg = config.services.cloud-init;
6 path = with pkgs; [
7 cloud-init
8 iproute2
9 nettools
10 openssh
11 shadow
12 util-linux
13 ] ++ optional cfg.btrfs.enable btrfs-progs
14 ++ optional cfg.ext4.enable e2fsprogs
15 ;
16in
17{
18 options = {
19 services.cloud-init = {
20 enable = mkOption {
21 type = types.bool;
22 default = false;
23 description = ''
24 Enable the cloud-init service. This services reads
25 configuration metadata in a cloud environment and configures
26 the machine according to this metadata.
27
28 This configuration is not completely compatible with the
29 NixOS way of doing configuration, as configuration done by
30 cloud-init might be overriden by a subsequent nixos-rebuild
31 call. However, some parts of cloud-init fall outside of
32 NixOS's responsibility, like filesystem resizing and ssh
33 public key provisioning, and cloud-init is useful for that
34 parts. Thus, be wary that using cloud-init in NixOS might
35 come as some cost.
36 '';
37 };
38
39 btrfs.enable = mkOption {
40 type = types.bool;
41 default = false;
42 description = ''
43 Allow the cloud-init service to operate `btrfs` filesystem.
44 '';
45 };
46
47 ext4.enable = mkOption {
48 type = types.bool;
49 default = true;
50 description = ''
51 Allow the cloud-init service to operate `ext4` filesystem.
52 '';
53 };
54
55 config = mkOption {
56 type = types.str;
57 default = ''
58 system_info:
59 distro: nixos
60 users:
61 - root
62
63 disable_root: false
64 preserve_hostname: false
65
66 cloud_init_modules:
67 - migrator
68 - seed_random
69 - bootcmd
70 - write-files
71 - growpart
72 - resizefs
73 - update_etc_hosts
74 - ca-certs
75 - rsyslog
76 - users-groups
77
78 cloud_config_modules:
79 - disk_setup
80 - mounts
81 - ssh-import-id
82 - set-passwords
83 - timezone
84 - disable-ec2-metadata
85 - runcmd
86 - ssh
87
88 cloud_final_modules:
89 - rightscale_userdata
90 - scripts-vendor
91 - scripts-per-once
92 - scripts-per-boot
93 - scripts-per-instance
94 - scripts-user
95 - ssh-authkey-fingerprints
96 - keys-to-console
97 - phone-home
98 - final-message
99 - power-state-change
100 '';
101 description = "cloud-init configuration.";
102 };
103
104 };
105
106 };
107
108 config = mkIf cfg.enable {
109
110 environment.etc."cloud/cloud.cfg".text = cfg.config;
111
112 systemd.services.cloud-init-local =
113 { description = "Initial cloud-init job (pre-networking)";
114 wantedBy = [ "multi-user.target" ];
115 path = path;
116 serviceConfig =
117 { Type = "oneshot";
118 ExecStart = "${pkgs.cloud-init}/bin/cloud-init init --local";
119 RemainAfterExit = "yes";
120 TimeoutSec = "infinity";
121 StandardOutput = "journal+console";
122 };
123 };
124
125 systemd.services.cloud-init =
126 { description = "Initial cloud-init job (metadata service crawler)";
127 wantedBy = [ "multi-user.target" ];
128 wants = [ "network-online.target" "cloud-init-local.service"
129 "sshd.service" "sshd-keygen.service" ];
130 after = [ "network-online.target" "cloud-init-local.service" ];
131 before = [ "sshd.service" "sshd-keygen.service" ];
132 requires = [ "network.target "];
133 path = path;
134 serviceConfig =
135 { Type = "oneshot";
136 ExecStart = "${pkgs.cloud-init}/bin/cloud-init init";
137 RemainAfterExit = "yes";
138 TimeoutSec = "infinity";
139 StandardOutput = "journal+console";
140 };
141 };
142
143 systemd.services.cloud-config =
144 { description = "Apply the settings specified in cloud-config";
145 wantedBy = [ "multi-user.target" ];
146 wants = [ "network-online.target" ];
147 after = [ "network-online.target" "syslog.target" "cloud-config.target" ];
148
149 path = path;
150 serviceConfig =
151 { Type = "oneshot";
152 ExecStart = "${pkgs.cloud-init}/bin/cloud-init modules --mode=config";
153 RemainAfterExit = "yes";
154 TimeoutSec = "infinity";
155 StandardOutput = "journal+console";
156 };
157 };
158
159 systemd.services.cloud-final =
160 { description = "Execute cloud user/final scripts";
161 wantedBy = [ "multi-user.target" ];
162 wants = [ "network-online.target" ];
163 after = [ "network-online.target" "syslog.target" "cloud-config.service" "rc-local.service" ];
164 requires = [ "cloud-config.target" ];
165 path = path;
166 serviceConfig =
167 { Type = "oneshot";
168 ExecStart = "${pkgs.cloud-init}/bin/cloud-init modules --mode=final";
169 RemainAfterExit = "yes";
170 TimeoutSec = "infinity";
171 StandardOutput = "journal+console";
172 };
173 };
174
175 systemd.targets.cloud-config =
176 { description = "Cloud-config availability";
177 requires = [ "cloud-init-local.service" "cloud-init.service" ];
178 };
179 };
180}