1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8with lib;
9let
10 cfg = config.virtualisation.azureImage;
11in
12{
13 imports = [
14 ./azure-common.nix
15 ./disk-size-option.nix
16 ../image/file-options.nix
17 (lib.mkRenamedOptionModuleWith {
18 sinceRelease = 2411;
19 from = [
20 "virtualisation"
21 "azureImage"
22 "diskSize"
23 ];
24 to = [
25 "virtualisation"
26 "diskSize"
27 ];
28 })
29 ];
30
31 options.virtualisation.azureImage = {
32 bootSize = mkOption {
33 type = types.int;
34 default = 256;
35 description = ''
36 ESP partition size. Unit is MB.
37 Only effective when vmGeneration is `v2`.
38 '';
39 };
40
41 contents = mkOption {
42 type = with types; listOf attrs;
43 default = [ ];
44 description = ''
45 Extra contents to add to the image.
46 '';
47 };
48
49 label = mkOption {
50 type = types.str;
51 default = "nixos";
52 description = ''
53 NixOS partition label.
54 '';
55 };
56
57 vmGeneration = mkOption {
58 type =
59 with types;
60 enum [
61 "v1"
62 "v2"
63 ];
64 default = "v1";
65 description = ''
66 VM Generation to use.
67 For v2, secure boot needs to be turned off during creation.
68 '';
69 };
70 };
71
72 config = {
73 image.extension = "vhd";
74 system.nixos.tags = [ "azure" ];
75 system.build.image = config.system.build.azureImage;
76 system.build.azureImage = import ../../lib/make-disk-image.nix {
77 name = "azure-image";
78 inherit (config.image) baseName;
79
80 # Azure expects vhd format with fixed size,
81 # generating raw format and convert with subformat args afterwards
82 format = "raw";
83 postVM = ''
84 ${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -o subformat=fixed,force_size -O vpc $diskImage $out/${config.image.fileName}
85 rm $diskImage
86 '';
87 configFile = ./azure-config-user.nix;
88
89 bootSize = "${toString cfg.bootSize}M";
90 partitionTableType = if (cfg.vmGeneration == "v2") then "efi" else "legacy";
91
92 inherit (cfg) contents label;
93 inherit (config.virtualisation) diskSize;
94 inherit config lib pkgs;
95 };
96
97 boot.growPartition = true;
98 boot.loader.grub = rec {
99 efiSupport = (cfg.vmGeneration == "v2");
100 device = if efiSupport then "nodev" else "/dev/sda";
101 efiInstallAsRemovable = efiSupport;
102 # Force grub to run in text mode and output to console
103 # by disabling font and splash image
104 font = null;
105 splashImage = null;
106 # For Gen 1 VM, configurate grub output to serial_com0.
107 # Not needed for Gen 2 VM wbere serial_com0 does not exist,
108 # and outputing to console is enough to make Azure Serial Console working
109 extraConfig = lib.mkIf (!efiSupport) ''
110 serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
111 terminal_input --append serial
112 terminal_output --append serial
113 '';
114 };
115
116 fileSystems = {
117 "/" = {
118 device = "/dev/disk/by-label/${cfg.label}";
119 inherit (cfg) label;
120 fsType = "ext4";
121 autoResize = true;
122 };
123
124 "/boot" = lib.mkIf (cfg.vmGeneration == "v2") {
125 device = "/dev/disk/by-label/ESP";
126 fsType = "vfat";
127 };
128 };
129 };
130}