1{ config, lib, pkgs, ... }:
2
3with lib;
4let
5
6 cfg = config.virtualisation.azure.agent;
7
8 provisionedHook = pkgs.writeScript "provisioned-hook" ''
9 #!${pkgs.runtimeShell}
10 /run/current-system/systemd/bin/systemctl start provisioned.target
11 '';
12
13in
14
15{
16
17 ###### interface
18
19 options.virtualisation.azure.agent = {
20 enable = mkOption {
21 default = false;
22 description = "Whether to enable the Windows Azure Linux Agent.";
23 };
24 verboseLogging = mkOption {
25 default = false;
26 description = "Whether to enable verbose logging.";
27 };
28 mountResourceDisk = mkOption {
29 default = true;
30 description = "Whether the agent should format (ext4) and mount the resource disk to /mnt/resource.";
31 };
32 };
33
34 ###### implementation
35
36 config = lib.mkIf cfg.enable {
37 assertions = [{
38 assertion = pkgs.stdenv.hostPlatform.isx86;
39 message = "Azure not currently supported on ${pkgs.stdenv.hostPlatform.system}";
40 }
41 {
42 assertion = config.networking.networkmanager.enable == false;
43 message = "Windows Azure Linux Agent is not compatible with NetworkManager";
44 }];
45
46 boot.initrd.kernelModules = [ "ata_piix" ];
47 networking.firewall.allowedUDPPorts = [ 68 ];
48
49
50 environment.etc."waagent.conf".text = ''
51 #
52 # Microsoft Azure Linux Agent Configuration
53 #
54
55 # Enable extension handling. Do not disable this unless you do not need password reset,
56 # backup, monitoring, or any extension handling whatsoever.
57 Extensions.Enabled=y
58
59 # How often (in seconds) to poll for new goal states
60 Extensions.GoalStatePeriod=6
61
62 # Which provisioning agent to use. Supported values are "auto" (default), "waagent",
63 # "cloud-init", or "disabled".
64 Provisioning.Agent=auto
65
66 # Password authentication for root account will be unavailable.
67 Provisioning.DeleteRootPassword=n
68
69 # Generate fresh host key pair.
70 Provisioning.RegenerateSshHostKeyPair=n
71
72 # Supported values are "rsa", "dsa", "ecdsa", "ed25519", and "auto".
73 # The "auto" option is supported on OpenSSH 5.9 (2011) and later.
74 Provisioning.SshHostKeyPairType=ed25519
75
76 # Monitor host name changes and publish changes via DHCP requests.
77 Provisioning.MonitorHostName=y
78
79 # How often (in seconds) to monitor host name changes.
80 Provisioning.MonitorHostNamePeriod=30
81
82 # Decode CustomData from Base64.
83 Provisioning.DecodeCustomData=n
84
85 # Execute CustomData after provisioning.
86 Provisioning.ExecuteCustomData=n
87
88 # Algorithm used by crypt when generating password hash.
89 #Provisioning.PasswordCryptId=6
90
91 # Length of random salt used when generating password hash.
92 #Provisioning.PasswordCryptSaltLength=10
93
94 # Allow reset password of sys user
95 Provisioning.AllowResetSysUser=n
96
97 # Format if unformatted. If 'n', resource disk will not be mounted.
98 ResourceDisk.Format=${if cfg.mountResourceDisk then "y" else "n"}
99
100 # File system on the resource disk
101 # Typically ext3 or ext4. FreeBSD images should use 'ufs2' here.
102 ResourceDisk.Filesystem=ext4
103
104 # Mount point for the resource disk
105 ResourceDisk.MountPoint=/mnt/resource
106
107 # Create and use swapfile on resource disk.
108 ResourceDisk.EnableSwap=n
109
110 # Size of the swapfile.
111 ResourceDisk.SwapSizeMB=0
112
113 # Comma-separated list of mount options. See mount(8) for valid options.
114 ResourceDisk.MountOptions=None
115
116 # Enable verbose logging (y|n)
117 Logs.Verbose=${if cfg.verboseLogging then "y" else "n"}
118
119 # Enable Console logging, default is y
120 # Logs.Console=y
121
122 # Enable periodic log collection, default is n
123 Logs.Collect=n
124
125 # How frequently to collect logs, default is each hour
126 Logs.CollectPeriod=3600
127
128 # Is FIPS enabled
129 OS.EnableFIPS=n
130
131 # Root device timeout in seconds.
132 OS.RootDeviceScsiTimeout=300
133
134 # How often (in seconds) to set the root device timeout.
135 OS.RootDeviceScsiTimeoutPeriod=30
136
137 # If "None", the system default version is used.
138 OS.OpensslPath=${pkgs.openssl_3.bin}/bin/openssl
139
140 # Set the SSH ClientAliveInterval
141 # OS.SshClientAliveInterval=180
142
143 # Set the path to SSH keys and configuration files
144 OS.SshDir=/etc/ssh
145
146 # If set, agent will use proxy server to access internet
147 #HttpProxy.Host=None
148 #HttpProxy.Port=None
149
150 # Detect Scvmm environment, default is n
151 # DetectScvmmEnv=n
152
153 #
154 # Lib.Dir=/var/lib/waagent
155
156 #
157 # DVD.MountPoint=/mnt/cdrom/secure
158
159 #
160 # Pid.File=/var/run/waagent.pid
161
162 #
163 # Extension.LogDir=/var/log/azure
164
165 #
166 # Home.Dir=/home
167
168 # Enable RDMA management and set up, should only be used in HPC images
169 OS.EnableRDMA=n
170
171 # Enable checking RDMA driver version and update
172 # OS.CheckRdmaDriver=y
173
174 # Enable or disable goal state processing auto-update, default is enabled
175 AutoUpdate.Enabled=n
176
177 # Determine the update family, this should not be changed
178 # AutoUpdate.GAFamily=Prod
179
180 # Determine if the overprovisioning feature is enabled. If yes, hold extension
181 # handling until inVMArtifactsProfile.OnHold is false.
182 # Default is enabled
183 EnableOverProvisioning=n
184
185 # Allow fallback to HTTP if HTTPS is unavailable
186 # Note: Allowing HTTP (vs. HTTPS) may cause security risks
187 # OS.AllowHTTP=n
188
189 # Add firewall rules to protect access to Azure host node services
190 OS.EnableFirewall=n
191
192 # How often (in seconds) to check the firewall rules
193 OS.EnableFirewallPeriod=30
194
195 # How often (in seconds) to remove the udev rules for persistent network interface
196 # names (75-persistent-net-generator.rules and /etc/udev/rules.d/70-persistent-net.rules)
197 OS.RemovePersistentNetRulesPeriod=30
198
199 # How often (in seconds) to monitor for DHCP client restarts
200 OS.MonitorDhcpClientRestartPeriod=30
201 '';
202
203 services.udev.packages = [ pkgs.waagent ];
204
205 # Provide waagent-shipped udev rules in initrd too.
206 boot.initrd.services.udev.packages = [ pkgs.waagent ];
207 # udev rules shell out to chmod, cut and readlink, which are all
208 # provided by pkgs.coreutils, which is in services.udev.path, but not
209 # boot.initrd.services.udev.binPackages.
210 boot.initrd.services.udev.binPackages = [ pkgs.coreutils ];
211
212 networking.dhcpcd.persistent = true;
213
214 services.logrotate = {
215 enable = true;
216 settings."/var/log/waagent.log" = {
217 compress = true;
218 frequency = "monthly";
219 rotate = 6;
220 };
221 };
222
223 systemd.targets.provisioned = {
224 description = "Services Requiring Azure VM provisioning to have finished";
225 };
226
227 systemd.services.consume-hypervisor-entropy =
228 {
229 description = "Consume entropy in ACPI table provided by Hyper-V";
230
231 wantedBy = [ "sshd.service" "waagent.service" ];
232 before = [ "sshd.service" "waagent.service" ];
233
234 path = [ pkgs.coreutils ];
235 script =
236 ''
237 echo "Fetching entropy..."
238 cat /sys/firmware/acpi/tables/OEM0 > /dev/random
239 '';
240 serviceConfig.Type = "oneshot";
241 serviceConfig.RemainAfterExit = true;
242 serviceConfig.StandardError = "journal+console";
243 serviceConfig.StandardOutput = "journal+console";
244 };
245
246 systemd.services.waagent = {
247 wantedBy = [ "multi-user.target" ];
248 after = [ "network-online.target" "sshd.service" ];
249 wants = [ "network-online.target" ];
250
251 path = [
252 pkgs.e2fsprogs
253 pkgs.bash
254
255 pkgs.findutils
256 pkgs.gnugrep
257 pkgs.gnused
258 pkgs.iproute2
259 pkgs.iptables
260
261 # for hostname
262 pkgs.nettools
263
264 pkgs.openssh
265 pkgs.openssl
266 pkgs.parted
267
268 # for pidof
269 pkgs.procps
270
271 # for useradd, usermod
272 pkgs.shadow
273
274 pkgs.util-linux # for (u)mount, fdisk, sfdisk, mkswap
275
276 # waagent's Microsoft.OSTCExtensions.VMAccessForLinux needs Python 3
277 pkgs.python39
278
279 # waagent's Microsoft.CPlat.Core.RunCommandLinux needs lsof
280 pkgs.lsof
281 ];
282 description = "Windows Azure Agent Service";
283 unitConfig.ConditionPathExists = "/etc/waagent.conf";
284 serviceConfig = {
285 ExecStart = "${pkgs.waagent}/bin/waagent -daemon";
286 Type = "simple";
287 };
288 };
289
290 # waagent will generate files under /etc/sudoers.d during provisioning
291 security.sudo.extraConfig = ''
292 #includedir /etc/sudoers.d
293 '';
294
295 };
296}