1 { config, lib, pkgs, ... }:
4 cfg = config.virtualbox;
10 baseImageSize = lib.mkOption {
11 type = with lib.types; either (enum [ "auto" ]) int;
15 The size of the VirtualBox base image in MiB.
18 baseImageFreeSpace = lib.mkOption {
19 type = with lib.types; int;
22 Free space in the VirtualBox base image in MiB.
25 memorySize = lib.mkOption {
29 The amount of RAM the VirtualBox appliance can use in MiB.
32 vmDerivationName = lib.mkOption {
34 default = "nixos-ova-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}";
36 The name of the derivation for the VirtualBox appliance.
39 vmName = lib.mkOption {
41 default = "${config.system.nixos.distroName} ${config.system.nixos.label} (${pkgs.stdenv.hostPlatform.system})";
43 The name of the VirtualBox appliance.
46 vmFileName = lib.mkOption {
48 default = "nixos-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.ova";
50 The file name of the VirtualBox appliance.
53 params = lib.mkOption {
54 type = with lib.types; attrsOf (oneOf [ str int bool (listOf str) ]);
61 Parameters passed to the Virtualbox appliance.
63 Run `VBoxManage modifyvm --help` to see more options.
66 exportParams = lib.mkOption {
67 type = with lib.types; listOf (oneOf [ str int bool (listOf str) ]);
69 "--vsys" "0" "--vendor" "ACME Inc."
73 Parameters passed to the Virtualbox export command.
75 Run `VBoxManage export --help` to see more options.
78 extraDisk = lib.mkOption {
80 Optional extra disk/hdd configuration.
81 The disk will be an 'ext4' partition on a separate file.
86 mountPoint = "/home/demo/storage";
89 type = lib.types.nullOr (lib.types.submodule {
93 description = "Size in MiB";
95 label = lib.mkOption {
97 default = "vm-extra-storage";
98 description = "Label for the disk partition";
100 mountPoint = lib.mkOption {
101 type = lib.types.str;
102 description = "Path where to mount this disk.";
107 postExportCommands = lib.mkOption {
108 type = lib.types.lines;
111 ${pkgs.cot}/bin/cot edit-hardware "$fn" \
114 --nic-types VMXNET3 \
115 --nic-names 'Nic name' \
116 --nic-networks 'Nic match' \
117 --network-descriptions 'Nic description' \
118 --scsi-subtypes VirtualSCSI
121 Extra commands to run after exporting the OVA to `$fn`.
124 storageController = lib.mkOption {
125 type = with lib.types; attrsOf (oneOf [ str int bool (listOf str) ]);
141 Parameters passed to the VirtualBox appliance. Must have at least
144 Run `VBoxManage storagectl --help` to see more options.
152 virtualbox.params = lib.mkMerge [
153 (lib.mapAttrs (name: lib.mkDefault) {
158 audiocontroller = "ac97";
161 graphicscontroller = "vmsvga";
167 (lib.mkIf (pkgs.stdenv.hostPlatform.system == "i686-linux") { pae = "on"; })
170 system.build.virtualBoxOVA = import ../../lib/make-disk-image.nix {
171 name = cfg.vmDerivationName;
173 inherit pkgs lib config;
174 partitionTableType = "legacy";
175 diskSize = cfg.baseImageSize;
176 additionalSpace = "${toString cfg.baseImageFreeSpace}M";
181 export PATH=${pkgs.virtualbox}/bin:$PATH
183 echo "converting image to VirtualBox format..."
184 VBoxManage convertfromraw $diskImage disk.vdi
186 ${lib.optionalString (cfg.extraDisk != null) ''
187 echo "creating extra disk: data-disk.raw"
188 dataDiskImage=data-disk.raw
189 truncate -s ${toString cfg.extraDisk.size}M $dataDiskImage
191 parted --script $dataDiskImage -- \
193 mkpart primary ext4 1MiB -1
194 eval $(partx $dataDiskImage -o START,SECTORS --nr 1 --pairs)
195 mkfs.ext4 -F -L ${cfg.extraDisk.label} $dataDiskImage -E offset=$(sectorsToBytes $START) $(sectorsToKilobytes $SECTORS)K
196 echo "creating extra disk: data-disk.vdi"
197 VBoxManage convertfromraw $dataDiskImage data-disk.vdi
200 echo "creating VirtualBox VM..."
201 vmName="${cfg.vmName}";
202 VBoxManage createvm --name "$vmName" --register \
203 --ostype ${if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then "Linux26_64" else "Linux26"}
204 VBoxManage modifyvm "$vmName" \
205 --memory ${toString cfg.memorySize} \
206 ${lib.cli.toGNUCommandLineShell { } cfg.params}
207 VBoxManage storagectl "$vmName" ${lib.cli.toGNUCommandLineShell { } cfg.storageController}
208 VBoxManage storageattach "$vmName" --storagectl ${cfg.storageController.name} --port 0 --device 0 --type hdd \
210 ${lib.optionalString (cfg.extraDisk != null) ''
211 VBoxManage storageattach "$vmName" --storagectl ${cfg.storageController.name} --port 1 --device 0 --type hdd \
212 --medium data-disk.vdi
215 echo "exporting VirtualBox VM..."
217 fn="$out/${cfg.vmFileName}"
218 VBoxManage export "$vmName" --output "$fn" --options manifest ${lib.escapeShellArgs cfg.exportParams}
219 ${cfg.postExportCommands}
223 mkdir -p $out/nix-support
224 echo "file ova $fn" >> $out/nix-support/hydra-build-products
230 device = "/dev/disk/by-label/nixos";
234 } // (lib.optionalAttrs (cfg.extraDisk != null) {
235 ${cfg.extraDisk.mountPoint} = {
236 device = "/dev/disk/by-label/" + cfg.extraDisk.label;
242 boot.growPartition = true;
243 boot.loader.grub.device = "/dev/sda";
246 device = "/var/swap";
250 virtualisation.virtualbox.guest.enable = true;