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