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