diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix
index 15afcc8f600018f2cd50fe7f8a0cf4383da27ead..f977876037c7a3769852f43cab0e5d3e59fce154 100644
--- a/morph/grid/local/grid.nix
+++ b/morph/grid/local/grid.nix
@@ -27,6 +27,8 @@ let
       ../../../nixos/modules/deployment.nix
       # Give it a good SSH configuration.
       ../../../nixos/modules/ssh.nix
+      # Configure things specific to the virtualisation environment.
+      gridlib.hardware-vagrant
     ];
     services.private-storage.sshUsers = ssh-users;
 
@@ -46,7 +48,7 @@ let
       # depend on the format we use.
       mode = "0666";
       text = ''
-        # Include the ssh-users config 
+        # Include the ssh-users config
         builtins.fromJSON (builtins.readFile ./ssh-users.json)
       '';
     };
@@ -68,42 +70,47 @@ let
   payments = {
     imports = [
       gridlib.issuer
-      (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.21"; }))
       (gridlib.customize-issuer (grid-config // {
           monitoringvpnIPv4 = "172.23.23.11";
       }))
       grid-module
     ];
+    config = {
+      grid.publicIPv4 = "192.168.67.21";
+    };
   };
 
   storage1 = {
     imports = [
       gridlib.storage
-      (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.22"; }))
       (gridlib.customize-storage (grid-config // {
         monitoringvpnIPv4 = "172.23.23.12";
         stateVersion = "19.09";
       }))
       grid-module
     ];
+    config = {
+      grid.publicIPv4 = "192.168.67.22";
+    };
   };
 
   storage2 = {
     imports = [
       gridlib.storage
-      (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.23"; }))
       (gridlib.customize-storage (grid-config // {
         monitoringvpnIPv4 = "172.23.23.13";
         stateVersion = "19.09";
       }))
       grid-module
     ];
+    config = {
+      grid.publicIPv4 = "192.168.67.23";
+    };
   };
 
   monitoring = {
     imports = [
       gridlib.monitoring
-      (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.24"; }))
       (gridlib.customize-monitoring {
         inherit hostsMap vpnClientIPs nodeExporterTargets paymentExporterTargets;
         inherit (grid-config) letsEncryptAdminEmail;
@@ -114,6 +121,9 @@ let
       })
       grid-module
     ];
+    config = {
+      grid.publicIPv4 = "192.168.67.24";
+    };
   };
 
   # TBD: derive these automatically:
diff --git a/morph/lib/default.nix b/morph/lib/default.nix
index 34f5e8b5171f211ededf38efb25440769113a8e4..78de2506382d023bc76b723eb866efc90f20ef7f 100644
--- a/morph/lib/default.nix
+++ b/morph/lib/default.nix
@@ -5,7 +5,7 @@
   base = import ./base.nix;
 
   hardware-aws = import ./issuer-aws.nix;
-  hardware-virtual = import ./hardware-virtual.nix;
+  hardware-vagrant = import ./hardware-vagrant.nix;
 
   issuer = import ./issuer.nix;
   customize-issuer = import ./customize-issuer.nix;
diff --git a/morph/lib/hardware-vagrant.nix b/morph/lib/hardware-vagrant.nix
new file mode 100644
index 0000000000000000000000000000000000000000..150944cd5b64b7a3eb620cd40ea39e00544779a7
--- /dev/null
+++ b/morph/lib/hardware-vagrant.nix
@@ -0,0 +1,43 @@
+{ config, lib, modulesPath, ... }:
+{
+  imports = [
+    # modulesPath points at the upstream nixos/modules directory.
+    "${modulesPath}/virtualisation/vagrant-guest.nix"
+  ];
+
+  options.grid = {
+    publicIPv4 = lib.mkOption {
+      type = lib.types.str;
+      description = ''
+        The primary IPv4 address of the virtual machine.
+      '';
+    };
+  };
+
+  config = {
+    virtualisation.virtualbox.guest.enable = true;
+
+    boot.loader.grub.device = "/dev/sda";
+
+    boot.initrd.availableKernelModules = [ "ata_piix" "sd_mod" "sr_mod" ];
+    boot.kernel.sysctl = { "vm.swappiness" = 0; };
+
+    # remove the fsck that runs at startup. It will always fail to run, stopping
+    # your boot until you press *.
+    boot.initrd.checkJournalingFS = false;
+
+    networking.interfaces.enp0s8.ipv4.addresses = [{
+      address = config.grid.publicIPv4;
+      prefixLength = 24;
+    }];
+
+    fileSystems."/storage" = { fsType = "tmpfs"; };
+    fileSystems."/" =
+      { device = "/dev/sda1";
+        fsType = "ext4";
+      };
+
+    # We want to push packages with morph without having to sign them
+    nix.trustedUsers = [ "@wheel" "root" "vagrant" ];
+  };
+}
diff --git a/morph/lib/hardware-virtual.nix b/morph/lib/hardware-virtual.nix
deleted file mode 100644
index cf1582792bff77c491210ee5e91f99bfbffbf9f3..0000000000000000000000000000000000000000
--- a/morph/lib/hardware-virtual.nix
+++ /dev/null
@@ -1,36 +0,0 @@
-{ publicIPv4, ... }:
-{
-  imports = [ ./vagrant-guest.nix ];
-
-  virtualisation.virtualbox.guest.enable = true;
-
-  # Use the GRUB 2 boot loader.
-  boot.loader.grub.enable = true;
-  boot.loader.grub.version = 2;
-  boot.loader.grub.device = "/dev/sda";
-
-  boot.initrd.availableKernelModules = [ "ata_piix" "sd_mod" "sr_mod" ];
-  boot.initrd.kernelModules = [ ];
-  boot.kernel.sysctl = { "vm.swappiness" = 0; };
-  boot.kernelModules = [ ];
-  boot.extraModulePackages = [ ];
-
-  # remove the fsck that runs at startup. It will always fail to run, stopping
-  # your boot until you press *.
-  boot.initrd.checkJournalingFS = false;
-
-  networking.interfaces.enp0s8.ipv4.addresses = [{
-    address = publicIPv4;
-    prefixLength = 24;
-  }];
-
-  fileSystems."/storage" = { fsType = "tmpfs"; };
-  fileSystems."/" =
-    { device = "/dev/sda1";
-      fsType = "ext4";
-    };
-  swapDevices = [ ];
-
-  # We want to push packages with morph without having to sign them
-  nix.trustedUsers = [ "@wheel" "root" "vagrant" ];
-}
diff --git a/morph/lib/vagrant-guest.nix b/morph/lib/vagrant-guest.nix
deleted file mode 100644
index 360671f5e8391571d37da6db37b2de8dc02b66bd..0000000000000000000000000000000000000000
--- a/morph/lib/vagrant-guest.nix
+++ /dev/null
@@ -1,91 +0,0 @@
-# Minimal configuration that vagrant depends on
-
-{ config, pkgs, lib, ... }:
-let
-  # Vagrant uses an insecure shared private key by default, but we
-  # don't use the authorizedKeys attribute under users because it should be
-  # removed on first boot and replaced with a random one. This script sets
-  # the correct permissions and installs the temporary key if no
-  # ~/.ssh/authorized_keys exists.
-  install-vagrant-ssh-key = pkgs.writeScriptBin "install-vagrant-ssh-key" ''
-    #!${pkgs.runtimeShell}
-    if [ ! -e ~/.ssh/authorized_keys ]; then
-      mkdir -m 0700 -p ~/.ssh
-      echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" >> ~/.ssh/authorized_keys
-      chmod 0600 ~/.ssh/authorized_keys
-    fi
-  '';
-in
-{
-  # Services to enable:
-
-  # Enable the OpenSSH daemon.
-  services.openssh.enable = true;
-
-  # Wireguard kernel module for Kernels < 5.6
-  boot = lib.mkIf (lib.versionOlder pkgs.linuxPackages.kernel.version "5.6") {
-    extraModulePackages = [ config.boot.kernelPackages.wireguard ] ;
-  };
-
-  # Enable DBus
-  services.dbus.enable    = true;
-
-  # Replace ntpd by timesyncd
-  services.timesyncd.enable = true;
-
-  # Packages for Vagrant
-  environment.systemPackages = with pkgs; [
-    findutils
-    gnumake
-    iputils
-    jq
-    nettools
-    netcat
-    nfs-utils
-    rsync
-  ];
-
-  users.users.root = { password = "vagrant"; };
-
-  # Creates a "vagrant" group & user with password-less sudo access
-  users.groups.vagrant = {
-    name = "vagrant";
-    members = [ "vagrant" ];
-  };
-  users.extraUsers.vagrant = {
-    isNormalUser    = true;
-    createHome      = true;
-    group           = "vagrant";
-    extraGroups     = [ "users" "wheel" ];
-    password        = "vagrant";
-    home            = "/home/vagrant";
-    useDefaultShell = true;
-  };
-
-  systemd.services.install-vagrant-ssh-key = {
-    description = "Vagrant SSH key install (if needed)";
-    after = [ "fs.target" ];
-    wants = [ "fs.target" ];
-    wantedBy = [ "multi-user.target" ];
-    serviceConfig = {
-      ExecStart = "${install-vagrant-ssh-key}/bin/install-vagrant-ssh-key";
-      User = "vagrant";
-      # So it won't be (needlessly) restarted:
-      RemainAfterExit = true;
-    };
-  };
-
-  security.sudo.wheelNeedsPassword = false;
-
-  security.sudo.extraConfig =
-    ''
-      Defaults:root,%wheel env_keep+=LOCALE_ARCHIVE
-      Defaults:root,%wheel env_keep+=NIX_PATH
-      Defaults:root,%wheel env_keep+=TERMINFO_DIRS
-      Defaults env_keep+=SSH_AUTH_SOCK
-      Defaults lecture = never
-      root   ALL=(ALL) SETENV: ALL
-      %wheel ALL=(ALL) NOPASSWD: ALL, SETENV: ALL
-    '';
-}
-