8 cfg = config.services.cloud-init;
20 ++ lib.optional cfg.btrfs.enable btrfs-progs
21 ++ lib.optional cfg.ext4.enable e2fsprogs
22 ++ lib.optional cfg.xfs.enable xfsprogs
24 hasFs = fsName: lib.any (fs: fs.fsType == fsName) (lib.attrValues config.fileSystems);
25 settingsFormat = pkgs.formats.yaml { };
26 cfgfile = settingsFormat.generate "cloud.cfg" cfg.settings;
30 services.cloud-init = {
31 enable = lib.mkOption {
32 type = lib.types.bool;
35 Enable the cloud-init service. This services reads
36 configuration metadata in a cloud environment and configures
37 the machine according to this metadata.
39 This configuration is not completely compatible with the
40 NixOS way of doing configuration, as configuration done by
41 cloud-init might be overridden by a subsequent nixos-rebuild
42 call. However, some parts of cloud-init fall outside of
43 NixOS's responsibility, like filesystem resizing and ssh
44 public key provisioning, and cloud-init is useful for that
45 parts. Thus, be wary that using cloud-init in NixOS might
50 btrfs.enable = lib.mkOption {
51 type = lib.types.bool;
52 default = hasFs "btrfs";
53 defaultText = lib.literalExpression ''hasFs "btrfs"'';
55 Allow the cloud-init service to operate `btrfs` filesystem.
59 ext4.enable = lib.mkOption {
60 type = lib.types.bool;
61 default = hasFs "ext4";
62 defaultText = lib.literalExpression ''hasFs "ext4"'';
64 Allow the cloud-init service to operate `ext4` filesystem.
68 xfs.enable = lib.mkOption {
69 type = lib.types.bool;
70 default = hasFs "xfs";
71 defaultText = lib.literalExpression ''hasFs "xfs"'';
73 Allow the cloud-init service to operate `xfs` filesystem.
77 network.enable = lib.mkOption {
78 type = lib.types.bool;
81 Allow the cloud-init service to configure network interfaces
82 through systemd-networkd.
86 extraPackages = lib.mkOption {
87 type = lib.types.listOf lib.types.package;
90 List of additional packages to be available within cloud-init jobs.
94 settings = lib.mkOption {
96 Structured cloud-init configuration.
98 type = lib.types.submodule {
99 freeformType = settingsFormat.type;
104 config = lib.mkOption {
105 type = lib.types.str;
108 raw cloud-init configuration.
110 Takes precedence over the `settings` option if set.
118 config = lib.mkIf cfg.enable {
119 services.cloud-init.settings = {
120 system_info = lib.mkDefault {
123 renderers = [ "networkd" ];
127 users = lib.mkDefault [ "root" ];
128 disable_root = lib.mkDefault false;
129 preserve_hostname = lib.mkDefault false;
131 cloud_init_modules = lib.mkDefault [
145 cloud_config_modules = lib.mkDefault [
151 "disable-ec2-metadata"
156 cloud_final_modules = lib.mkDefault [
157 "rightscale_userdata"
161 "scripts-per-instance"
163 "ssh-authkey-fingerprints"
171 environment.etc."cloud/cloud.cfg" =
172 if cfg.config == "" then { source = cfgfile; } else { text = cfg.config; };
174 systemd.network.enable = lib.mkIf cfg.network.enable true;
176 systemd.services.cloud-init-local = {
177 description = "Initial cloud-init job (pre-networking)";
178 wantedBy = [ "multi-user.target" ];
179 # In certain environments (AWS for example), cloud-init-local will
180 # first configure an IP through DHCP, and later delete it.
181 # This can cause race conditions with anything else trying to set IP through DHCP.
183 "systemd-networkd.service"
189 ExecStart = "${pkgs.cloud-init}/bin/cloud-init init --local";
190 RemainAfterExit = "yes";
191 TimeoutSec = "infinity";
192 StandardOutput = "journal+console";
196 systemd.services.cloud-init = {
197 description = "Initial cloud-init job (metadata service crawler)";
198 wantedBy = [ "multi-user.target" ];
200 "network-online.target"
201 "cloud-init-local.service"
203 "sshd-keygen.service"
206 "network-online.target"
207 "cloud-init-local.service"
211 "sshd-keygen.service"
213 requires = [ "network.target" ];
217 ExecStart = "${pkgs.cloud-init}/bin/cloud-init init";
218 RemainAfterExit = "yes";
219 TimeoutSec = "infinity";
220 StandardOutput = "journal+console";
224 systemd.services.cloud-config = {
225 description = "Apply the settings specified in cloud-config";
226 wantedBy = [ "multi-user.target" ];
227 wants = [ "network-online.target" ];
229 "network-online.target"
230 "cloud-config.target"
236 ExecStart = "${pkgs.cloud-init}/bin/cloud-init modules --mode=config";
237 RemainAfterExit = "yes";
238 TimeoutSec = "infinity";
239 StandardOutput = "journal+console";
243 systemd.services.cloud-final = {
244 description = "Execute cloud user/final scripts";
245 wantedBy = [ "multi-user.target" ];
246 wants = [ "network-online.target" ];
248 "network-online.target"
249 "cloud-config.service"
252 requires = [ "cloud-config.target" ];
256 ExecStart = "${pkgs.cloud-init}/bin/cloud-init modules --mode=final";
257 RemainAfterExit = "yes";
258 TimeoutSec = "infinity";
259 StandardOutput = "journal+console";
263 systemd.targets.cloud-config = {
264 description = "Cloud-config availability";
266 "cloud-init-local.service"
272 meta.maintainers = [ lib.maintainers.zimbatm ];