Building a lab with ESXI and Vagrant

Lab design

ESXi 6.5 installed on a physical box, with multiple VMs on an isolated virtual network. A virtual firewall is the border for the internal network and supplies VPN access. VPN access will be set up to connect straight into the network, but no domain user provided.

Domain design

Nothing here yet

Server plan

Domain controller
Server 2012 R2
File server
Server 2008 R2
Web server
Server 2016 Tech Eval
W10 Enterprise
W7 Enterprise
Annoying Linux box
CentOS 7.4


Install all the software requirements and download the necessary ISOs. They can be acquired from the MS Evaluation Center (trial) or The-Eye (Volume Licensing (VL)).

Hardware requirements

  • ESXi 6.5 compatible hardware (can use 6.0 if incompatible)
  • Minimum 32 GB RAM
  • A drive for ESXi - rquires only 8 GB
  • A drive for the actual VMs - 500 GB+
  • A USB drive to install ESXi with - minimum 1 GB
  • A separate computer to do management from

Software requirements




  • Windows Server 2012 R2
  • Windows Server 2016
  • Windows 7 Enterprise Edition
  • Windows 10 Enterprise Edition
  • CentOS 7.4

Installing ESXI

Download ESXI 6.5 image
Use Rufusto make a bootable USB key from the ESXI image.
Boot the lab machine from USB and install ESXi on the small drive as per instruction.
After installation, reboot the server. ESXi should now provide a DHCP-leased IP-address you can access from a web panel.
It can be a good idea to set a static IP at this point to prevent the ESXi network adapter' IP to keep changing when you're doing things.


Troubleshooting write speeds with SSD: https://communities.vmware.com/thread/554004
ESXi 6.5 includes a new native driver (vmw_ahci) for SATA AHCI controllers, but that introduces performance problems with a lot of controllers and/or disks.
Try to disable the native driver and revert to the older sata-ahci driver by running
esxcli system moduleset--enabled=false--module=vmw_ahci

Enabling ESXi shell and SSH

The Vagrant ESXi plugin requires SSH to be anabled.
  1. 1.
    At the direct console of the ESXi host, press F2 and provide credentials when prompted.
  2. 2.
    Scroll to Troubleshooting Options and press Enter.
  3. 3.
    Choose Enable ESXi shell and Enable SSH and press Enter once on each of them
  4. 4.
    Press Esc until you return to the main direct console screen.

Setting static IP for the ESXi host

  1. 1.
    Press F2 on the ESXi console, provide credentials when prompted
  2. 2.
    Configure management network -> IPV4 Configuration
  3. 3.
    Press space on Set static ipv4 address
  4. 4.
    Press Esc until you return to the main direct console screen.

Adding a datastore to ESXi

Add the big drive, where the virtual machines will be stored as a datastore in ESXi.
  1. 1.
    In the ESXi web client press Storagein the left side pane.
  2. 2.
    Just follow the instructions after selecting New datastorefrom the menu,
  3. 3.
    Add a drive, give it a name like VMs and use the whole drive as one partition.

Adding a network configuration to ESXi

  1. 1.
    Select Networking on the left side pane
  2. 2.
    Click Add standard switch, name it vSwitch1
  3. 3.
    I forgot what step 3 was
  4. 4.
    Click port group, ADD port group.
  5. 5.
    Give it the name Lab Network, asign it to VLAN 0, assign it to vSwitch0which is the default virtual switch.

Installing Vagrant

Install Vagrant and the plugins
vagrant plugin install vagrant-vmware-esxi
vagrant plugin install vagrant-winrm-syncedfolders
vagrant plugin install vagrant-reload
vagrant plugin list
vagrant-reload (0.0.1)
vagrant-vmware-esxi (2.3.1)
vagrant-winrm-syncedfolders (1.0.1)

(NEW WAY) - Build VMs with Packer

Packer helps us automate the tiresome process of preparing images into VMs ready for deployment.

(OLD WAY) - Downloading operating systems in Vagrant

Using the following syntax download the required operating systems using Vagrant. Select vmware_desktop as provider when prompted. It is wise to choose boxes from the Vagrant cloud that doesn't have any configuration management built in; those are usually indicated by nocm.
vagrant box add opentable/win-2008r2-enterprise-amd64-nocm
vagrant box add opentable/win-2012r2-standard-amd64-nocm
vagrant box add StefanScherer/windows_2016
vagrant box add opentable/win-7-enterprise-amd64-nocm
vagrant box add StefanScherer/windows_10`

(OLD WAY) - Preparing base images for every OS

Deploying to Vagrant and applying things like powershell config during deployment will be a lot easier if the VMs are prepped. This process must be repeated for every VM, which is a drag, but it only has to be done once.
  • Make a new directory and call it PrepSever2016. Copy the entire directory of the VM .vagrant.d/boxes/repoNameOfVM to a new directory.
  • Before booting the VM in Workstation, set up a file share, because transfering files to the box is necessary.
  • If not possible, set up a network adapter so you can host the files on a local web server or on Github so you can download them to the box.
  • Proceed to boot the box in VMware workstation and prepare the following:

1. Fix accounts

Enable the local Administrator account and delete the Vagrant account by doing
  • Control panel -> User accounts -> Manage another account -> Administrator -> Set a password for the Administrator account -> Log out
  • Log in as Administrator using the new password, go into Control panel -> Users -> Remove User Acccounts -> Delete the Vagrant account -> Click delete files

2. Install VMware tools

Do it through the VMware workstation interface. Should be self explanatory.

3. Windows Update

  • Use this WU.ps1 script to download and install updates for the operating system.
  • Open powershell.exe as an Administrator and run Import-Module C:\Users\Administrator\Desktop\WU.ps1
  • This must potentially be performed numerous times with several reboots until there are no more updates to apply. Just keep running it until it says there are no more updates.

4. Installing .Net framework

4. Run Sysprep

Sysprep will be done through the XML file provided here: link
Perform sysprep with the following command. OOBE is Out Of Box Experience, the startup screen welcome bullshit. The script itself preps the system and enables WinRM.
C:\Windows\system32\sysprep\sysprep.exe /generalize /oobe /shutdown /unattend:c:\users\Administrator\Desktop\sysprep.xml

5. Verification

The VM should now be shut down and we want to verify that everything works as intended.
  • Go to VM -> Manage -> Clone -> Full clone and make a full clone of the VM. (Takes ages)
  • Boot the clone and verify that everything was set correctly.
  • Shut down and delete the clone or achive it as a Baseline image.
  • Make a copy of the VM you have fixed and put it in the boxes folder.
  • Rename the folder to Server2016 or whatever name you prefer.
  • If you are short on disk space, you can delete the original VMs downloaded from Vagrant cloud and/or clones, but note that they might be useful to have around for later in case something borks.
  • Snapshot?

Deploying VMs with Vagrant

Initialize repo

Initialize a repo. This, amongst other files creates the very important Vagrantfile which holds the deployment configuration.
vagrant init

Vagrantfile configuration

The documentation fro the vmware esxi plugin has examples and configurations.
https://www.vagrantup.com/docs/vagrantfile/machine_settings.html Each define tag is one box, so you can have multiple boxes, in fact your entire lab in just one Vagrantfile.
Set the name of the box and pointer to the box you downloaded in previous steps. The winrm parameters specify that WinRM (powershell remote controlling boxes) should be used for deployment. In relation to this, many powershell scripts can be added for tasks like adding a box to a domain, setting certain system parameters, in general preparing the OS so this does not become a manual job.
The esxi parameters are at the bottom. Hostname must point to the management network virtual switch interface and the password must of course be set.
Vagrant.configure("2") do |config|
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.define "WEB01" do |config|
config.vm.box = "Server2016"
config.vm.guest = :windows
config.vm.communicator = "winrm"
config.vm.synced_folder "C:\\Users\\chris\\Google Drive\\Hacking\\beelabs\\AD_Files", "C:\\windows\\temp", type: "winrm"
config.vm.boot_timeout = 100
config.vm.graceful_halt_timeout = 100
config.winrm.timeout = 120
config.winrm.username = "Administrator"
config.winrm.password = "PASSWORD"
config.winrm.transport = :plaintext
config.winrm.basic_auth_only = true
config.vm.provision "shell", inline: "Rename-Computer -NewName WEB01"
config.vm.provision :reload
config.vm.provider :vmware_esxi do |esxi|
esxi.esxi_hostname = ""
esxi.esxi_username = "root"
esxi.esxi_password = "PASSWORD"
esxi_virtual_network = "Lab Network"
esxi.esxi_disk_store = "VMs"
esxi.guest_memsize = "2048"
esxi.guest_numvcpus = "2"
esxi.mac_address = ["00:50:56:3f:01:01"]
After the configuration file has been verified run vagrant status and fix eventual errors then do deploy the machine run vagrant up This takes the Vagrantfile, applies it, and uses OVFtool to deploy it to the ESXi host using the aforementioned plugin.
If the box is shut down and booting it is necessary you want to up it without provisioning it, so specify the following
vagrant up BOX01 --no-provision
After the box has been deployed and provisioned it might be a good idea to shut it down and take a snapshot. This can also be done from vagrant using vagrant snapshot push to take a snapshot and vagrant snapshot pop to roll back. To show all snpashots do vagrant snapshot list