Creating a Windows Box with Vagrant 1.6

The latest Vagrant release added out-of-the box support for Windows VMs.  Below are my notes on creating a new vagrant box, and then using WinRM and RDP to connect to a Windows 2008 Server VM.

Pre-requisites:

  • VirtualBox 4.3 or above Installed
    Add installation path (“C:\Program Files\Oracle\VirtualBox”) to your PATH environment variable
  • Windows ISO file
  • Vagrant 1.6.3 or above Installed

Create a VirtualBox Windows VM

The instructions use the command line interface. You are welcome to use the VirtualBox GUI as there’s really no difference in the end result.  You can also skip this if you already have an operational Windows VM in VirtualBox.  See this post on “Create/Manage VirtualBox VMs from the Command Line” and VirtualBox VBoxManage documentation.

Alternatively you could also get a base box from packer-windows (it only configures SSH currently, but they are working on adding WinRM support).

  1. Create/Register the VM
    C:\>VBoxManage createvm --name "w2k8_r2_base" --ostype Windows2008_64 --basefolder C:\VMs\ --register

    Use VBoxManage list ostypes In order to get the possible OS types you can use.  Also note that 64bit OS may not show up on this list if Virtualization Technology (Intel VT-x, AMD-V, etc) is not enabled in the BIOS.

  2. Configure VM according to your needs
    C:\>VBoxManage modifyvm "w2k8_r2_base" --memory 2048 --cpus 2 --vram 128 --acpi on --boot1 dvd --nic1 nat

    Vagrant requires the first network interface to be a NAT adapter

  3. Configure Hard Drive
    C:\>cd VMs\w2k8_r2_base
    C:\VMs\w2k8_r2_base>VBoxManage createhd --filename ./w2k8_r2_base.vdi --size 30000
    C:\VMs\w2k8_r2_base>VBoxManage storagectl "w2k8_r2_base" --name "SATA" --add sata
    C:\VMs\w2k8_r2_base>VBoxManage storageattach "w2k8_r2_base" --storagectl "SATA" --port 0 --device 0 --type hdd --medium ./w2k8_r2_base.vdi
    
  4. Configure DVD Drive and point to your installation ISO file
    C:\VMs\w2k8_r2_base>VBoxManage storagectl "w2k8_r2_base" --name "IDE" --add ide
    C:\VMs\w2k8_r2_base>VBoxManage storageattach "w2k8_r2_base" --storagectl "IDE" --port 0 --device 0 --type dvddrive --medium C:\ISOs\Windows2008\W2K8_R2_64bit.iso
    
  5. Install Windows OS
    Using VirtualBox GUI start the newly created VM and install/setup Windows according to your needs.
  6. Detach the Installation ISO file
    C:\VMs\w2k8_r2_base>VBoxManage storageattach "w2k8_r2_base" --storagectl "IDE" --port 0 --device 0 --type dvddrive --medium none
  7. Install Guest Additions
    C:\VMs\w2k8_r2_base>VBoxManage storageattach "w2k8_r2_base" --storagectl "IDE" --port 0 --device 0 --type dvddrive --medium "C:\Program Files\Oracle\VirtualBox\VBoxGuestAdditions.iso"

    Using VirtualBox GUI, open the DVD drive on the Guest VM and install VirtualBox Guest Additions. After you’re finished detach the ISO using the command on the previous step.

Configure WinRM & RDP

  1. Setup WinRM for remote management on Guest VM
    By default WinRM might not be configure for remote management on your newly created Windows VM, the following command enables it.

    C:\>winrm quickconfig -q
  2. Update WinRM config on Guest VM
    I used the following settings (documented on the knife windows chef plugin)

    C:\>winrm set winrm/config/winrs @{MaxMemoryPerShellMB="300"}
    C:\>winrm set winrm/config @{MaxTimeoutms="1800000"}
    C:\>winrm set winrm/config/service @{AllowUnencrypted="true"}
    C:\>winrm set winrm/config/service/auth @{Basic="true"}
    
  3. Enable Remote Desktop
    On Guest VM, Remote desktop can be enabled by going to “My computer” properties, click on “Remote Settings”, and select “Allow connections from computers running any versions for Remote Desktop”
  4. Ensure Windows Firewall Allows WinRM/RDP traffic
    On Guest VM, open “Windows Firewall with Advance Security” and make sure that the Inbound Rules for “Windows Remote Management (HTTP-In)” and “Remote Desktop (TCP-in)” are enabled.

Create a Vagrant Box

  1. Shutdown the Guest Windows VM
  2. Package the Windows Box
    C:\>cd VMs\VagrantBoxes
    C:\VMs\VagrantBoxes>vagrant package --base w2k8_r2_base --output w2k8_r2_base.box
  3. Add the box to Vagrant
    C:\>vagrant box add w2k8_r2_base C:\VMs\VagrantBoxes\w2k8_r2_base.box

Vagrant Up

  1. Initialize Box
    C:\>cd VMs\VagrantVMs\w2k8_r2_vm
    C:\VMs\VagrantVMs\w2k8_r2_vm>vagrant init w2k8_r2_base
  2. Edit Vagrantfile
    By default winrm is not setup (ssh is the default); you need to explicitly set it.  In addition, I didn’t use the default vagrant user/password, so I set those as well.  Lastly make sure to forward the RDP port.

    # -*- mode: ruby -*-
    # vi: set ft=ruby :
    
    VAGRANTFILE_API_VERSION = "2"
    
    Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
     config.vm.box = "w2k8_r2_base"
     config.vm.communicator = "winrm"
     config.winrm.username = "Administrator"
     config.winrm.password = "yourpassword"
     config.vm.network "forwarded_port", host: 33389, guest: 3389
    end
  3. Vagrant Up!
    C:\VMs\VagrantVMs\w2k8_r2_vm>vagrant up
  4. Remote-in to your new Vagrant-managed VM
    C:\VMs\VagrantVMs\w2k8_r2_vm>vagrant rdp

    * In Vagrant version 1.6.3 there was a regression introduced around the rdp command (See issue #3973).  I used my regular Remote Desktop client manually and all worked fine.

At this point you should have a Windows Box all set with Vagrant.  In a future post, I intend to discuss provisioning software with Chef.  If you ran into any issues following these instructions, please add those as comments below.  Thanks for reading!

Advertisements

28 thoughts on “Creating a Windows Box with Vagrant 1.6

  1. Hi Denny,
    I’ve done eveything you said, works fine with a win2k12 server but it isn’t working with a w2k8. When I “Vagrant Up”, it blocks at “waiting for machine to boot..” and then tells me thar i’ve got a networking problem. Any Idea ? Thanks a lot for the Tutorial btw 🙂

    • Hi Clement, would suggest to verify you can manage your guest vm with winrm outside of vagrant. One way to do this is to install chef’s knife utility and execute the following command:

      knife winrm ‘node1.domain.com’ ‘dir’ -m -x domain\\administrator -P ‘super_secret_password’ –p 5986

      This is documented on the knife windows site:
      http://docs.opscode.com/plugin_knife_windows.html

      I ran into similar problems when using w2k8 since it doesn’t have winrm configured by default and also had to allow the traffic through the firewall (see steps 1-4 on the “Configure WinRM & RDP” section above)

  2. I think I missed something when I read the tutorial for the first time because now it’s perfectly working. Thank you ! Have you made attempts to use External Script provisionning ? The script I created in order to install software on the guest machine starts in background mode. I wonder if there is a configuration in WinRM to change.

    • this nice and dandy but what about running a sysprep on windows where you can assign IPs; define DNS server; gateway; activate windows product with different licences

      such as if you multiple template of windows server OS and each template has its own customization when you install it

  3. Hey Denny. Thanks for this. I had run into that RDP regression issue you mentioned, even reported it to them when I found it. I’m curious if you have blogged more about the provisioning side of things yet. I didn’t see anything when I did a quick glance around your site.

    While Chef would be interesting, I’m hoping that just using PowerShell will be sufficient. Trying to reduce the learning curve for other developers.

      • Glad to hear that. I made some pretty good progress with PS provisioning last week. Have a base box that now runs scripts to install .NET 4.5, Remote Debugging and added the Web Server Role. Currently working on/testing installation of SQL 2008 R2 Express. Looking forward to your post.

    • Hi Kyle, I finally got a chance to wrap up my article on DSC. Take a look 🙂

      Also I did have to udpate the xSqlServerInstall DSC Resource in order to make it work with SQL Server 2008 (I think they only officially support 2012).

      Basically added a Version DSC resource parameter and the following code to the psm1 file:

      # Do nothing if UpdateEnable is not passed (is not supported by 2008 R2 Standard)
      if (($UpdateEnabled -eq $true) -and (!($Version.Contains(“2008″)))){
      $cmd += ” /updateEnabled=true ”
      } elseif (($UpdateEnabled -eq $false) -and (!($Version.Contains(“2008″)))) {
      $cmd += ” /updateEnabled=false ”
      }

      # SQL Server log folder
      $LogPath = $null
      if ($Version.Contains(“2008”)) {
      $LogPath = Join-Path $env:ProgramFiles “Microsoft SQL Server\100\Setup Bootstrap\Log”
      } else {
      $LogPath = Join-Path $env:ProgramFiles “Microsoft SQL Server\110\Setup Bootstrap\Log”
      }

      Hopefully MS will add official support to their DSC resource soon.

      • Thanks Denny! I’ll have to read that other article. I had made decent progress getting through multiple installations via PS (including SQL Express 2008 R2) but was pulled onto other tasks and haven’t had a chance to get back to playing with this. I hope that changes soon, have some big ideas that I want to get working.

    • HI Venkat, looks like you’ve got an answer from stackoverflow already. I’d recommend to update Vagrant to 1.6.5 if you’re still running into issues with RDP. On another note you can add this to your Vagrantfile to disable headless mode and get a GUI when you execute vagrant up

      # Start Virtual Box VM in GUI mode
      config.vm.provider “virtualbox” do |v|
      v.gui = true
      end

      • Hi Denny,
        I did get answers but they didn’t seem to help me out completely. I upgraded to Vagrant 1.7.1 and followed all your steps until vagrant up where I got an error. My vagrantFile is as follows:
        Vagrant.configure(2) do |config|
        config.vm.box = “serverbasebox”
        config.vm.communicator = “winrm”
        config.vm.username = “Administrator”
        config.vm.password = “password123”
        config.vm.network “forwarded_port”, guest: 33389, host: 3389
        end

        I get the following error:
        Bringing machine ‘default’ up with ‘virtualbox’ provider…
        There are errors in the configuration of this machine. Please fix
        the following errors and try again:

        vm:
        * The following settings shouldn’t exist: password, username

        Any suggestions as to what I can do about this?

    • Hi Venkat,

      Looks like there’s a bad double quote character at the end of the password. Try using an ASCII editor (notepad maybe), and re-type the double quote characters.

      Hope this helps.

      • I don’t know if Venkat is still having the problem, but the Vagrantfile should have

        config.winrm.username = “…”
        config.winrm.password = “…”

        Note the config.winrm rather than config.vm. But only on those two lines.

      • Hi Denny, thanks for your speedy and detailed reply.I have worked around the issue by configurating the RDP and SSH like described in the blog article here: http://www.hyper-world.de/en/2014/07/26/windows8-1-vagrant-box/

        Interestingly, then I had the “Forwarded port ‘xxxx’ (host port) is declared multiple times” error. Despite this is not the case in my Vagrantfile, several port forwardings seem to be hardcoded in the source of Vagrant that under uncertain circumstances take effect. But I worked around that using labels as mentioned in the comments to this bug report: https://github.com/mitchellh/vagrant/issues/1541#issuecomment-17315713

        Now that worked it out. Now I just have port conflicts with the host network to resolve but that’s no explicit Vagrant issue and I should be able to work that out eventually 🙂

      • Update: I have found by googling that there was a Change in newer RDP Client of Windows that ports 3389 and 3390 shall no longer be used but port 3388 worked.
        The only issue I have now is that after “vagrant up” the vagrant procces hangs at “Waiting for machine to boot.This may take a few mins…” Any idea why that happens and how to avoid it? It’s not a biggie, as I can cancel it with CTRL and C and then run vagrant Provision but would be cool to have it working 100%. I have put my vagrantfile up at for you to loook at:https://mega.co.nz/#!pgJHVRRb!XV3oTIiJPkZD-8_PuZONBQWdcumkHHP6NQ7ngTte9jk

        Thanks in advance!

    • Great to hear that Joerg 🙂 Would you mind posting your solution? I did get a brief chance to look at your Vagrantfile but didn’t really spot any issues there. Thought that the issue might be with the configuration on the base VM.

  4. hi Denny, I have posted some more details in the comment before the above, but it’s pending moderation from your side:

    Joerg Droege December 3, 2014 at 5:17 AM · ·
    Your comment is awaiting moderation.

    And I have asked my boss, I have got the permission to post my solution on my blog, so I will do it soon at one of these days!

  5. Hi Denny,

    I followed all your steps on setting up WinRM my Windows 7 VM and I edited my Vagrantfile as follows:

    config.vm.box = “win7_v4”
    config.vm.communicator = “winrm”
    config.winrm.username = “Administrator”
    config.winrm.password = “mypassword”
    config.vm.network :forwarded_port, guest: 33389, host: 3389, id: “rdp”, auto_correct:true
    config.vm.network :forwarded_port, guest: 5985, host: 5985, id: “winrm”, auto_correct:true
    config.windows.set_work_network = true

    However, when I run vagrant up, it hangs and eventually times out on this:

    ==> default: Waiting for machine to boot. This may take a few minutes…

    Even though the machine boots up fine. There seems to be an issue with connecting to it.

    I end up getting this message:
    Timed out while waiting for the machine to boot. This means that
    Vagrant was unable to communicate with the guest machine within
    the configured (“config.vm.boot_timeout” value) time period.

    If you look above, you should be able to see the error(s) that
    Vagrant had when attempting to connect to the machine. These errors
    are usually good hints as to what may be wrong.

    If you’re using a custom box, make sure that networking is properly
    working and you’re able to connect to the machine. It is a common
    problem that networking isn’t setup properly in these boxes.
    Verify that authentication configurations are also setup properly,
    as well.

    If the box appears to be booting properly, you may want to increase
    the timeout (“config.vm.boot_timeout”) value.

    Any ideas what might be wrong?

  6. With new version of vagrant dont use config.vm.network “forwarded_port”, host: 33389, guest: 3389. Use config.winrm.port = “33389”
    config.winrm.guest_port = “3389” instead

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s