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