1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 cfg = config.virtualisation.azure;
10 mlxDrivers = [
11 "mlx4_en"
12 "mlx4_core"
13 "mlx5_core"
14 ];
15in
16{
17 options.virtualisation.azure = {
18 acceleratedNetworking = lib.mkOption {
19 default = false;
20 description = "Whether the machine's network interface has enabled accelerated networking.";
21 };
22 };
23
24 config = {
25 services.waagent.enable = true;
26
27 # Enable cloud-init by default for waagent.
28 # Otherwise waagent would try manage networking using ifupdown,
29 # which is currently not availeble in nixpkgs.
30 services.cloud-init.enable = true;
31 services.cloud-init.network.enable = true;
32 systemd.services.cloud-config.serviceConfig.Restart = "on-failure";
33
34 # cloud-init.network.enable also enables systemd-networkd
35 networking.useNetworkd = true;
36
37 # Ensure kernel outputs to ttyS0 (Azure Serial Console),
38 # and reboot machine upon fatal boot issues
39 boot.kernelParams = [
40 "console=ttyS0"
41 "earlyprintk=ttyS0"
42 "rootdelay=300"
43 "panic=1"
44 "boot.panic_on_fail"
45 ];
46
47 # Load Hyper-V kernel modules
48 boot.initrd.kernelModules = [
49 "hv_vmbus"
50 "hv_netvsc"
51 "hv_utils"
52 "hv_storvsc"
53 ];
54
55 # Accelerated networking, configured following:
56 # https://learn.microsoft.com/en-us/azure/virtual-network/accelerated-networking-overview
57 boot.initrd.availableKernelModules = lib.optionals cfg.acceleratedNetworking mlxDrivers;
58 systemd.network.networks."99-azure-unmanaged-devices.network" = lib.mkIf cfg.acceleratedNetworking {
59 matchConfig.Driver = mlxDrivers;
60 linkConfig.Unmanaged = "yes";
61 };
62 networking.networkmanager.unmanaged = lib.mkIf cfg.acceleratedNetworking (
63 builtins.map (drv: "driver:${drv}") mlxDrivers
64 );
65
66 # Allow root logins only using the SSH key that the user specified
67 # at instance creation time, ping client connections to avoid timeouts
68 services.openssh.enable = true;
69 services.openssh.settings.PermitRootLogin = "prohibit-password";
70 services.openssh.settings.ClientAliveInterval = 180;
71
72 # Force getting the hostname from Azure
73 networking.hostName = lib.mkDefault "";
74
75 # Always include cryptsetup so that NixOps can use it.
76 # sg_scan is needed to finalize disk removal on older kernels
77 environment.systemPackages = [
78 pkgs.cryptsetup
79 pkgs.sg3_utils
80 ];
81
82 networking.usePredictableInterfaceNames = false;
83
84 services.udev.extraRules = lib.concatMapStrings (i: ''
85 ENV{DEVTYPE}=="disk", KERNEL!="sda" SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNELS=="?:0:0:${toString i}", ATTR{removable}=="0", SYMLINK+="disk/by-lun/${toString i}"
86 '') (lib.range 1 15);
87 };
88}