···30303131- [agorakit](https://github.com/agorakit/agorakit), an organization tool for citizens' collectives. Available with [services.agorakit](options.html#opt-services.agorakit.enable).
32323333+- [waagent](https://github.com/Azure/WALinuxAgent), the Microsoft Azure Linux Agent (waagent) manages Linux provisioning and VM interaction with the Azure Fabric Controller. Available with [services.waagent](options.html#opt-services.waagent.enable).
3434+3335- [mqtt-exporter](https://github.com/kpetremann/mqtt-exporter/), a Prometheus exporter for exposing messages from MQTT. Available as [services.prometheus.exporters.mqtt](#opt-services.prometheus.exporters.mqtt.enable).
34363537- [Buffyboard](https://gitlab.postmarketos.org/postmarketOS/buffybox/-/tree/master/buffyboard), a framebuffer on-screen keyboard. Available as [services.buffyboard](option.html#opt-services.buffyboard).
···103105- `gkraken` software and `hardware.gkraken.enable` option have been removed, use `coolercontrol` via `programs.coolercontrol.enable` option instead.
104106105107- `nodePackages.ganache` has been removed, as the package has been deprecated by upstream.
108108+109109+- `virtualisation.azure.agent` option provided by `azure-agent.nix` is replaced by `services.waagent`, and will be removed in a future release.
106110107111- `containerd` has been updated to v2, which contains breaking changes. See the [containerd
108112 2.0](https://github.com/containerd/containerd/blob/main/docs/containerd-2.0.md) documentation for more
···11-{ config, lib, pkgs, ... }:
11+{ lib, ... }:
2233with lib;
44-let
55-66- cfg = config.virtualisation.azure.agent;
77-88- provisionedHook = pkgs.writeScript "provisioned-hook" ''
99- #!${pkgs.runtimeShell}
1010- /run/current-system/systemd/bin/systemctl start provisioned.target
1111- '';
1212-1313-in
1414-{
44+warn
55+ ''
66+ `virtualisation.azure.agent` provided by `azure-agent.nix` module has been replaced
77+ by `services.waagent` options, and will be removed in a future release.
88+ ''
99+ {
15101616- ###### interface
1717-1818- options.virtualisation.azure.agent = {
1919- enable = mkOption {
2020- default = false;
2121- description = "Whether to enable the Windows Azure Linux Agent.";
2222- };
2323- verboseLogging = mkOption {
2424- default = false;
2525- description = "Whether to enable verbose logging.";
2626- };
2727- mountResourceDisk = mkOption {
2828- default = true;
2929- description = "Whether the agent should format (ext4) and mount the resource disk to /mnt/resource.";
3030- };
3131- };
3232-3333- ###### implementation
3434-3535- config = lib.mkIf cfg.enable {
3636- assertions = [{
3737- assertion = config.networking.networkmanager.enable == false;
3838- message = "Windows Azure Linux Agent is not compatible with NetworkManager";
3939- }];
4040-4141- boot.initrd.kernelModules = [ "ata_piix" ];
4242- networking.firewall.allowedUDPPorts = [ 68 ];
4343-4444-4545- environment.etc."waagent.conf".text = ''
4646- #
4747- # Microsoft Azure Linux Agent Configuration
4848- #
4949-5050- # Enable extension handling. Do not disable this unless you do not need password reset,
5151- # backup, monitoring, or any extension handling whatsoever.
5252- Extensions.Enabled=y
5353-5454- # How often (in seconds) to poll for new goal states
5555- Extensions.GoalStatePeriod=6
5656-5757- # Which provisioning agent to use. Supported values are "auto" (default), "waagent",
5858- # "cloud-init", or "disabled".
5959- Provisioning.Agent=auto
6060-6161- # Password authentication for root account will be unavailable.
6262- Provisioning.DeleteRootPassword=n
6363-6464- # Generate fresh host key pair.
6565- Provisioning.RegenerateSshHostKeyPair=n
6666-6767- # Supported values are "rsa", "dsa", "ecdsa", "ed25519", and "auto".
6868- # The "auto" option is supported on OpenSSH 5.9 (2011) and later.
6969- Provisioning.SshHostKeyPairType=ed25519
7070-7171- # Monitor host name changes and publish changes via DHCP requests.
7272- Provisioning.MonitorHostName=y
7373-7474- # How often (in seconds) to monitor host name changes.
7575- Provisioning.MonitorHostNamePeriod=30
7676-7777- # Decode CustomData from Base64.
7878- Provisioning.DecodeCustomData=n
7979-8080- # Execute CustomData after provisioning.
8181- Provisioning.ExecuteCustomData=n
8282-8383- # Algorithm used by crypt when generating password hash.
8484- #Provisioning.PasswordCryptId=6
8585-8686- # Length of random salt used when generating password hash.
8787- #Provisioning.PasswordCryptSaltLength=10
8888-8989- # Allow reset password of sys user
9090- Provisioning.AllowResetSysUser=n
9191-9292- # Format if unformatted. If 'n', resource disk will not be mounted.
9393- ResourceDisk.Format=${if cfg.mountResourceDisk then "y" else "n"}
9494-9595- # File system on the resource disk
9696- # Typically ext3 or ext4. FreeBSD images should use 'ufs2' here.
9797- ResourceDisk.Filesystem=ext4
9898-9999- # Mount point for the resource disk
100100- ResourceDisk.MountPoint=/mnt/resource
101101-102102- # Create and use swapfile on resource disk.
103103- ResourceDisk.EnableSwap=n
104104-105105- # Size of the swapfile.
106106- ResourceDisk.SwapSizeMB=0
107107-108108- # Comma-separated list of mount options. See mount(8) for valid options.
109109- ResourceDisk.MountOptions=None
110110-111111- # Enable verbose logging (y|n)
112112- Logs.Verbose=${if cfg.verboseLogging then "y" else "n"}
113113-114114- # Enable Console logging, default is y
115115- # Logs.Console=y
116116-117117- # Enable periodic log collection, default is n
118118- Logs.Collect=n
119119-120120- # How frequently to collect logs, default is each hour
121121- Logs.CollectPeriod=3600
122122-123123- # Is FIPS enabled
124124- OS.EnableFIPS=n
125125-126126- # Root device timeout in seconds.
127127- OS.RootDeviceScsiTimeout=300
128128-129129- # How often (in seconds) to set the root device timeout.
130130- OS.RootDeviceScsiTimeoutPeriod=30
131131-132132- # If "None", the system default version is used.
133133- OS.OpensslPath=${pkgs.openssl_3.bin}/bin/openssl
134134-135135- # Set the SSH ClientAliveInterval
136136- # OS.SshClientAliveInterval=180
137137-138138- # Set the path to SSH keys and configuration files
139139- OS.SshDir=/etc/ssh
140140-141141- # If set, agent will use proxy server to access internet
142142- #HttpProxy.Host=None
143143- #HttpProxy.Port=None
144144-145145- # Detect Scvmm environment, default is n
146146- # DetectScvmmEnv=n
147147-148148- #
149149- # Lib.Dir=/var/lib/waagent
150150-151151- #
152152- # DVD.MountPoint=/mnt/cdrom/secure
153153-154154- #
155155- # Pid.File=/var/run/waagent.pid
156156-157157- #
158158- # Extension.LogDir=/var/log/azure
159159-160160- #
161161- # Home.Dir=/home
162162-163163- # Enable RDMA management and set up, should only be used in HPC images
164164- OS.EnableRDMA=n
165165-166166- # Enable checking RDMA driver version and update
167167- # OS.CheckRdmaDriver=y
168168-169169- # Enable or disable goal state processing auto-update, default is enabled
170170- AutoUpdate.Enabled=n
171171-172172- # Determine the update family, this should not be changed
173173- # AutoUpdate.GAFamily=Prod
174174-175175- # Determine if the overprovisioning feature is enabled. If yes, hold extension
176176- # handling until inVMArtifactsProfile.OnHold is false.
177177- # Default is enabled
178178- EnableOverProvisioning=n
179179-180180- # Allow fallback to HTTP if HTTPS is unavailable
181181- # Note: Allowing HTTP (vs. HTTPS) may cause security risks
182182- # OS.AllowHTTP=n
183183-184184- # Add firewall rules to protect access to Azure host node services
185185- OS.EnableFirewall=n
186186-187187- # How often (in seconds) to check the firewall rules
188188- OS.EnableFirewallPeriod=30
189189-190190- # How often (in seconds) to remove the udev rules for persistent network interface
191191- # names (75-persistent-net-generator.rules and /etc/udev/rules.d/70-persistent-net.rules)
192192- OS.RemovePersistentNetRulesPeriod=30
193193-194194- # How often (in seconds) to monitor for DHCP client restarts
195195- OS.MonitorDhcpClientRestartPeriod=30
196196- '';
197197-198198- services.udev.packages = [ pkgs.waagent ];
199199-200200- # Provide waagent-shipped udev rules in initrd too.
201201- boot.initrd.services.udev.packages = [ pkgs.waagent ];
202202- # udev rules shell out to chmod, cut and readlink, which are all
203203- # provided by pkgs.coreutils, which is in services.udev.path, but not
204204- # boot.initrd.services.udev.binPackages.
205205- boot.initrd.services.udev.binPackages = [ pkgs.coreutils ];
206206-207207- networking.dhcpcd.persistent = true;
208208-209209- services.logrotate = {
210210- enable = true;
211211- settings."/var/log/waagent.log" = {
212212- compress = true;
213213- frequency = "monthly";
214214- rotate = 6;
215215- };
216216- };
217217-218218- systemd.targets.provisioned = {
219219- description = "Services Requiring Azure VM provisioning to have finished";
220220- };
221221-222222- systemd.services.consume-hypervisor-entropy =
223223- {
224224- description = "Consume entropy in ACPI table provided by Hyper-V";
225225-226226- wantedBy = [ "sshd.service" "waagent.service" ];
227227- before = [ "sshd.service" "waagent.service" ];
228228-229229- path = [ pkgs.coreutils ];
230230- script =
231231- ''
232232- echo "Fetching entropy..."
233233- cat /sys/firmware/acpi/tables/OEM0 > /dev/random
234234- '';
235235- serviceConfig.Type = "oneshot";
236236- serviceConfig.RemainAfterExit = true;
237237- serviceConfig.StandardError = "journal+console";
238238- serviceConfig.StandardOutput = "journal+console";
239239- };
240240-241241- systemd.services.waagent = {
242242- wantedBy = [ "multi-user.target" ];
243243- after = [ "network-online.target" "sshd.service" ];
244244- wants = [ "network-online.target" ];
245245-246246- path = [
247247- pkgs.e2fsprogs
248248- pkgs.bash
249249-250250- pkgs.findutils
251251- pkgs.gnugrep
252252- pkgs.gnused
253253- pkgs.iproute2
254254- pkgs.iptables
255255-256256- # for hostname
257257- pkgs.nettools
258258-259259- pkgs.openssh
260260- pkgs.openssl
261261- pkgs.parted
262262-263263- # for pidof
264264- pkgs.procps
265265-266266- # for useradd, usermod
267267- pkgs.shadow
268268-269269- pkgs.util-linux # for (u)mount, fdisk, sfdisk, mkswap
270270-271271- # waagent's Microsoft.OSTCExtensions.VMAccessForLinux needs Python 3
272272- pkgs.python39
273273-274274- # waagent's Microsoft.CPlat.Core.RunCommandLinux needs lsof
275275- pkgs.lsof
276276- ];
277277- description = "Windows Azure Agent Service";
278278- unitConfig.ConditionPathExists = "/etc/waagent.conf";
279279- serviceConfig = {
280280- ExecStart = "${pkgs.waagent}/bin/waagent -daemon";
281281- Type = "simple";
282282- };
283283- };
284284-285285- # waagent will generate files under /etc/sudoers.d during provisioning
286286- security.sudo.extraConfig = ''
287287- #includedir /etc/sudoers.d
288288- '';
289289-290290- };
291291-}
1111+ imports = [
1212+ (mkRenamedOptionModule
1313+ [
1414+ "virtualisation"
1515+ "azure"
1616+ "agent"
1717+ "enable"
1818+ ]
1919+ [
2020+ "services"
2121+ "waagent"
2222+ "enable"
2323+ ]
2424+ )
2525+ (mkRenamedOptionModule
2626+ [
2727+ "virtualisation"
2828+ "azure"
2929+ "agent"
3030+ "verboseLogging"
3131+ ]
3232+ [
3333+ "services"
3434+ "waagent"
3535+ "settings"
3636+ "Logs"
3737+ "Verbose"
3838+ ]
3939+ )
4040+ (mkRenamedOptionModule
4141+ [
4242+ "virtualisation"
4343+ "azure"
4444+ "agent"
4545+ "mountResourceDisk"
4646+ ]
4747+ [
4848+ "services"
4949+ "waagent"
5050+ "settings"
5151+ "ResourceDisk"
5252+ "Format"
5353+ ]
5454+ )
5555+ ];
5656+ }
+364
nixos/modules/virtualisation/waagent.nix
···11+{
22+ config,
33+ lib,
44+ pkgs,
55+ ...
66+}:
77+88+with lib;
99+let
1010+ cfg = config.services.waagent;
1111+1212+ # Format for waagent.conf
1313+ settingsFormat = {
1414+ type =
1515+ with types;
1616+ let
1717+ singleAtom =
1818+ (nullOr (oneOf [
1919+ bool
2020+ str
2121+ int
2222+ float
2323+ ]))
2424+ // {
2525+ description = "atom (bool, string, int or float) or null";
2626+ };
2727+ atom = either singleAtom (listOf singleAtom) // {
2828+ description = singleAtom.description + " or a list of them";
2929+ };
3030+ in
3131+ attrsOf (
3232+ either atom (attrsOf atom)
3333+ // {
3434+ description = atom.description + "or an attribute set of them";
3535+ }
3636+ );
3737+ generate =
3838+ name: value:
3939+ let
4040+ # Transform non-attribute values
4141+ transform =
4242+ x:
4343+ # Transform bool to "y" or "n"
4444+ if (isBool x) then
4545+ (if x then "y" else "n")
4646+ # Concatenate list items with comma
4747+ else if (isList x) then
4848+ concatStringsSep "," (map transform x)
4949+ else
5050+ toString x;
5151+5252+ # Convert to format of waagent.conf
5353+ recurse =
5454+ path: value:
5555+ if builtins.isAttrs value then
5656+ pipe value [
5757+ (mapAttrsToList (k: v: recurse (path ++ [ k ]) v))
5858+ concatLists
5959+ ]
6060+ else
6161+ [
6262+ {
6363+ name = concatStringsSep "." path;
6464+ inherit value;
6565+ }
6666+ ];
6767+ convert =
6868+ attrs:
6969+ pipe (recurse [ ] attrs) [
7070+ # Filter out null values and emoty lists
7171+ (filter (kv: kv.value != null && kv.value != [ ]))
7272+ # Transform to Key=Value form, then concatenate
7373+ (map (kv: "${kv.name}=${transform kv.value}"))
7474+ (concatStringsSep "\n")
7575+ ];
7676+ in
7777+ pkgs.writeText name (convert value);
7878+ };
7979+8080+ settingsType = types.submodule {
8181+ freeformType = settingsFormat.type;
8282+ options = {
8383+ Provisioning = {
8484+ Enable = mkOption {
8585+ type = types.bool;
8686+ default = !config.services.cloud-init.enable;
8787+ defaultText = literalExpression "!config.services.cloud-init.enable";
8888+ description = ''
8989+ Whether to enable provisioning functionality in the agent.
9090+9191+ If provisioning is disabled, SSH host and user keys in the image are preserved
9292+ and configuration in the Azure provisioning API is ignored.
9393+9494+ Set to `false` if cloud-init is used for provisioning tasks.
9595+ '';
9696+ };
9797+9898+ Agent = mkOption {
9999+ type = types.enum [
100100+ "auto"
101101+ "waagent"
102102+ "cloud-init"
103103+ "disabled"
104104+ ];
105105+ default = "auto";
106106+ description = ''
107107+ Which provisioning agent to use.
108108+ '';
109109+ };
110110+ };
111111+112112+ ResourceDisk = {
113113+ Format = mkEnableOption ''
114114+ If set to `true`, waagent formats and mounts the resource disk that the platform provides,
115115+ unless the file system type in `ResourceDisk.FileSystem` is set to `ntfs`.
116116+ The agent makes a single Linux partition (ID 83) available on the disk.
117117+ This partition isn't formatted if it can be successfully mounted.
118118+119119+ This configuration has no effect if resource disk is managed by cloud-init.
120120+ '';
121121+122122+ FileSystem = mkOption {
123123+ type = types.str;
124124+ default = "ext4";
125125+ description = ''
126126+ The file system type for the resource disk.
127127+ If the string is `X`, then `mkfs.X` should be present in the environment.
128128+ You can add additional filesystem packages using `services.waagent.extraPackages`.
129129+130130+ This configuration has no effect if resource disk is managed by cloud-init.
131131+ '';
132132+ };
133133+134134+ MountPoint = mkOption {
135135+ type = types.str;
136136+ default = "/mnt/resource";
137137+ description = ''
138138+ This option specifies the path at which the resource disk is mounted.
139139+ The resource disk is a temporary disk and might be emptied when the VM is deprovisioned.
140140+141141+ This configuration has no effect if resource disk is managed by cloud-init.
142142+ '';
143143+ };
144144+145145+ MountOptions = mkOption {
146146+ type = with types; listOf str;
147147+ default = [ ];
148148+ example = [
149149+ "nodev"
150150+ "nosuid"
151151+ ];
152152+ description = ''
153153+ This option specifies disk mount options to be passed to the `mount -o` command.
154154+ For more information, see the `mount(8)` manual page.
155155+ '';
156156+ };
157157+158158+ EnableSwap = mkEnableOption ''
159159+ If enabled, the agent creates a swap file (`/swapfile`) on the resource disk
160160+ and adds it to the system swap space.
161161+162162+ This configuration has no effect if resource disk is managed by cloud-init.
163163+ '';
164164+165165+ SwapSizeMB = mkOption {
166166+ type = types.int;
167167+ default = 0;
168168+ description = ''
169169+ Specifies the size of the swap file in megabytes.
170170+171171+ This configuration has no effect if resource disk is managed by cloud-init.
172172+ '';
173173+ };
174174+ };
175175+176176+ Logs.Verbose = lib.mkEnableOption ''
177177+ If you set this option, log verbosity is boosted.
178178+ Waagent logs to `/var/log/waagent.log` and uses the system logrotate functionality to rotate logs.
179179+ '';
180180+181181+ OS = {
182182+ EnableRDMA = lib.mkEnableOption ''
183183+ If enabled, the agent attempts to install and then load an RDMA kernel driver
184184+ that matches the version of the firmware on the underlying hardware.
185185+ '';
186186+187187+ RootDeviceScsiTimeout = lib.mkOption {
188188+ type = types.nullOr types.int;
189189+ default = 300;
190190+ description = ''
191191+ Configures the SCSI timeout in seconds on the OS disk and data drives.
192192+ If set to `null`, the system defaults are used.
193193+ '';
194194+ };
195195+ };
196196+197197+ HttpProxy = {
198198+ Host = lib.mkOption {
199199+ type = types.nullOr types.str;
200200+ default = null;
201201+ description = ''
202202+ If you set http proxy, waagent will use is proxy to access the Internet.
203203+ '';
204204+ };
205205+206206+ Port = lib.mkOption {
207207+ type = types.nullOr types.int;
208208+ default = null;
209209+ description = ''
210210+ If you set http proxy, waagent will use this proxy to access the Internet.
211211+ '';
212212+ };
213213+ };
214214+215215+ AutoUpdate.Enable = lib.mkEnableOption ''
216216+ Enable or disable autoupdate for goal state processing.
217217+ '';
218218+ };
219219+ };
220220+in
221221+{
222222+ options.services.waagent = {
223223+ enable = lib.mkEnableOption ''
224224+ Whether to enable the Windows Azure Linux Agent.
225225+ '';
226226+227227+ package = lib.mkPackageOption pkgs "waagent" { };
228228+229229+ extraPackages = lib.mkOption {
230230+ default = [ ];
231231+ description = ''
232232+ Additional packages to add to the waagent {env}`PATH`.
233233+ '';
234234+ example = lib.literalExpression "[ pkgs.powershell ]";
235235+ type = lib.types.listOf lib.types.package;
236236+ };
237237+238238+ settings = lib.mkOption {
239239+ type = settingsType;
240240+ default = { };
241241+ description = ''
242242+ The waagent.conf configuration, see https://learn.microsoft.com/en-us/azure/virtual-machines/extensions/agent-linux for documentation.
243243+ '';
244244+ };
245245+ };
246246+247247+ config = lib.mkIf cfg.enable {
248248+ assertions = [
249249+ {
250250+ assertion = (cfg.settings.HttpProxy.Host != null) -> (cfg.settings.HttpProxy.Port != null);
251251+ message = "Option services.waagent.settings.HttpProxy.Port must be set if services.waagent.settings.HttpProxy.Host is set.";
252252+ }
253253+ ];
254254+255255+ boot.initrd.kernelModules = [ "ata_piix" ];
256256+ networking.firewall.allowedUDPPorts = [ 68 ];
257257+258258+ services.udev.packages = with pkgs; [ waagent ];
259259+260260+ boot.initrd.services.udev = with pkgs; {
261261+ # Provide waagent-shipped udev rules in initrd too.
262262+ packages = [ waagent ];
263263+ # udev rules shell out to chmod, cut and readlink, which are all
264264+ # provided by pkgs.coreutils, which is in services.udev.path, but not
265265+ # boot.initrd.services.udev.binPackages.
266266+ binPackages = [ coreutils ];
267267+ };
268268+269269+ networking.dhcpcd.persistent = true;
270270+271271+ services.logrotate = {
272272+ enable = true;
273273+ settings."/var/log/waagent.log" = {
274274+ compress = true;
275275+ frequency = "monthly";
276276+ rotate = 6;
277277+ };
278278+ };
279279+280280+ # Write settings to /etc/waagent.conf
281281+ environment.etc."waagent.conf".source = settingsFormat.generate "waagent.conf" cfg.settings;
282282+283283+ systemd.targets.provisioned = {
284284+ description = "Services Requiring Azure VM provisioning to have finished";
285285+ };
286286+287287+ systemd.services.consume-hypervisor-entropy = {
288288+ description = "Consume entropy in ACPI table provided by Hyper-V";
289289+290290+ wantedBy = [
291291+ "sshd.service"
292292+ "waagent.service"
293293+ ];
294294+ before = [
295295+ "sshd.service"
296296+ "waagent.service"
297297+ ];
298298+299299+ path = [ pkgs.coreutils ];
300300+ script = ''
301301+ echo "Fetching entropy..."
302302+ cat /sys/firmware/acpi/tables/OEM0 > /dev/random
303303+ '';
304304+ serviceConfig.Type = "oneshot";
305305+ serviceConfig.RemainAfterExit = true;
306306+ serviceConfig.StandardError = "journal+console";
307307+ serviceConfig.StandardOutput = "journal+console";
308308+ };
309309+310310+ systemd.services.waagent = {
311311+ wantedBy = [ "multi-user.target" ];
312312+ after = [
313313+ "network-online.target"
314314+ ] ++ lib.optionals config.services.cloud-init.enable [ "cloud-init.service" ];
315315+ wants = [
316316+ "network-online.target"
317317+ "sshd.service"
318318+ "sshd-keygen.service"
319319+ ];
320320+321321+ path =
322322+ with pkgs;
323323+ [
324324+ e2fsprogs
325325+ bash
326326+ findutils
327327+ gnugrep
328328+ gnused
329329+ iproute2
330330+ iptables
331331+ openssh
332332+ openssl
333333+ parted
334334+335335+ # for hostname
336336+ nettools
337337+ # for pidof
338338+ procps
339339+ # for useradd, usermod
340340+ shadow
341341+342342+ util-linux # for (u)mount, fdisk, sfdisk, mkswap
343343+ # waagent's Microsoft.CPlat.Core.RunCommandLinux needs lsof
344344+ lsof
345345+ ]
346346+ ++ cfg.extraPackages;
347347+ description = "Windows Azure Agent Service";
348348+ unitConfig.ConditionPathExists = "/etc/waagent.conf";
349349+ serviceConfig = {
350350+ ExecStart = "${lib.getExe cfg.package} -daemon";
351351+ Type = "simple";
352352+ Restart = "always";
353353+ Slice = "azure.slice";
354354+ CPUAccounting = true;
355355+ MemoryAccounting = true;
356356+ };
357357+ };
358358+359359+ # waagent will generate files under /etc/sudoers.d during provisioning
360360+ security.sudo.extraConfig = ''
361361+ #includedir /etc/sudoers.d
362362+ '';
363363+ };
364364+}