/workstations

Vagrant virtual workstations and development environments with Visual Studio, Docker, IIS and SQL Server on Windows for .NET development

Primary LanguageRuby

Workstations

Quick links Vagrant boxes | Vagrant resources | Packer templates

This repository contains Windows-based virtual workstations for .NET, SQL and infrastructure development using Vagrant with Hyper-V and VirtualBox.

Contents Overview | Getting started | Usage | Contributing | Resources

Overview

This repository contains Windows-based virtual workstations for the following scenarios:

All of them support an easy, source-controlled way of installing and configuring the most common development tools for the related stacks, and the management of the source code of your projects, based on Vagrant with Hyper-V / VirtualBox and Chef:

  • Installing core features, packages and managing OS settings.
  • Using different versions of Visual Studio and SQL Server.
  • Managing Vagrant plugins and downloading boxes.
  • Pulling Docker images.
  • Configuring AWS profiles.
  • Working with Git and SVN repositories.
  • Managing NuGet sources.

This way you can easily create the same workstations anytime, anywhere, and instead of writing extensive documentation, you can simply share the ready to use environments with your teammates and contributors. Of course, you can extend the above options freely with any of your own configuration and provisioning steps.

Getting started

In this section Installing the tools | Creating your first workstation

Note This section assumes you are familiar with the basics of Vagrant. If that's not the case, it's recommended that you take a quick look at its getting started guide.

Note The workstations have been tested on Windows hosts only, but they are supposed to run on any other platform as well, given that the actual virtualization provider (e.g. VirtualBox) supports it. Let me know if you encounter any issues and I'm glad to help.

Installing the tools

In this section Using Hyper-V | Using VirtualBox

Follow the steps below to install the required tools:

  1. Install Vagrant.
  2. Install the Chef Development Kit.
  3. Install the following plugins:
    1. vagrant-reload.
    2. vagrant-berkshelf.
  4. Install the tools for the virtualization provider you want to use.

Using Hyper-V

Note Other virtualization providers that you might use will not work when Hyper-V is enabled. See Hanselman's post for switching between them easily.

  1. Enable Hyper-V. You will need Windows 10 or Windows Server 2016 version 1607 or later on the host.
    • Optionally, if you plan to use Hyper-V by default, add the environment variable VAGRANT_DEFAULT_PROVIDER with the value of hyperv to prevent specifying it every time a machine is booted.
    • Optionally, add the environment variable VAGRANT_LINKED_CLONE to save some disk space using differencing disks.
    • Optionally, add the environment variables VAGRANT_SMB_USERNAME and VAGRANT_SMB_PASSWORD with your credentials on the host to prevent Vagrant from asking it every time a machine is booted.
  2. Create a virtual switch to be used with Vagrant with access to the external network.
    • Optionally, add the environment variable VAGRANT_NETWORK_BRIDGE with the value of the name of the virtual switch you've created to prevent Vagrant from asking for it every time a machine is created.

Using VirtualBox

  1. Install VirtualBox. It is recommended to have VirtualBox version 5.2.22 or later on the host.
    • Optionally, if you plan to use VirtualBox by default, add the environment variable VAGRANT_DEFAULT_PROVIDER with the value of virtualbox to prevent specifying it every time a machine is booted.
    • Optionally, add the environment variable VAGRANT_LINKED_CLONE to save some disk space using linked clones.

Creating your first workstation

Note Booting a workstation for the first time can take a significant amount of time. If you have a slow connection, downloading the Vagrant boxes - usually several GBs for Windows guests - might require some patience and retries. Creating another machine from the same box later though will reuse the already downloaded one of course.

Note Configuring the core OS after Sysprep (to support actually unique virtual machines) and provisioning the workstations (e.g. installing the custom tools not included in the Packer templates) by default happens during the initial boot as well. However, starting the machines again later will not need these steps, so the process will be significantly faster.

Note The example in this section creates a workstation with a sample configuration by default, focusing on demonstrating the management of machines in general. You will see the details of how to customize it according to your preferences later.

You are now ready to create your workstations with Vagrant.

Clone this repository and navigate to the root directory of the clone using your shell. Then, enter the directory of your personal environment to list the available machines:

clone$ cd src/people/me
clone/src/people/me$ vagrant status

The output will be something similar to this:

work                      not_created (hyperv)
playground                not_created (hyperv)
private                   not_created (hyperv)

The list shows the three default workstations, work intended to support the projects you work on, playground for generic experiments, and private for anything else, like communication or generic office work. None of these exsit yet, so for example, to create the playground one, simply invoke vagrant up:

clone/src/people/me$ vagrant up playground

Now, it's time to be patient. The box - in this case, by default with Visual Studio 2017 Community including Windows Server 2016 Standard - will be downloaded and the machine will be provisioned before the first use to include all the components this repository supports. If this is not the configuration that you want, you can terminate the process anytime.

Once the machine is ready, you can connect to it with RDP or open a remote shell using the default credentials, vagrant for both the user name and password:

clone/src/people/me$ vagrant rdp playground
clone/src/people/me$ vagrant ssh playground

Later, you can check the status of your machines by typing vagrant status again in the same directory or vagrant global-status anywhere to list all the machines on your host.

clone/src/people/me$ vagrant status
work                      not_created (hyperv)
playground                running (hyperv)
private                   not_created (hyperv)
$ vagrant global-status
id  playground hyperv running    clone/src/people/me

When you've finished with your work, you can shut down the machine with vagrant halt. This will persist the machine's state, so next time when you invoke vagrant up, it will boot much more faster than for the first time, and your files and settings will be preserved.

clone/src/people/me$ vagrant halt playground

If you no longer need a machine, you can destroy it. As expected, this will wipe it completely from your system (on the next vagrant up, it will be provisioned again from scratch):

clone/src/people/me$ vagrant destroy playground

The box will remain on your system after destroying the machine as vagrant box list reports it, as other machines might still use it. You can use vagrant box remove to clean it up if you no longer need it.

Usage

In this section Basics | Components | Stacks | Projects | People

Note At this point you might want to fork this repository and create your own branch to save your changes and to compare your workstations easily with others.

Take a moment to realize that this might have been the last time you installed something for your workstations manually.

Basics

In this section Configuration | Provisioning

This repository uses custom Vagrant extensions to enable creating and reusing dynamic configurations based on YAML and ERB for the most common machine parameters and provisioning options.

Configuration

For example, you can define some reasonable defaults to be applied to every configuration:

# src/components/core/vagrant.yml
core:
  provider:
    memory: 8192
    cpus: 4

Source

This means that by default the machines will allocate 8 GB RAM and 4 virtual CPUs.

Also, you can define how components, like the core OS is being provisioned:

# src/components/os/vagrant.yml
core:
  chef:
    cookbooks:
      - gusztavvargadr_workstations_os
    json:
      gusztavvargadr_workstations_os:
        requirements:
          locales:
            system: en-US
            ui: en-US
            user: en-US
          datetime:
            timezone: UTC

Source

This shows that the custom OS cookbook will be used for provisioning, and the specified values, in this case, en-US for all the locales and UTC for the timezone will be set. The cookbooks provide complete samples for the scenarios they support so you can define only the options you need.

YAML files are processed as ERB-templates first, so for example you can dynamically set the host's timezone for the guest:

timezone: <%= `tzutil /g`.strip %>

This approach can be also used to e.g. pass secrets or other sensitive information to the guests without hard-coding them, retrieving the values for example from host environment variables dynamically.

You can also define further parameters for Vagrant, in this case, a base box specifying the Visual Studio version being used:

# src/components/vs/vagrant.yml
core:
  includes:
    - components/core/core

17c:
  includes:
    - components/vs/core
  box: w16s-dc-vs17c

Source

In this case the configuration named components/vs/17c will use the Visual Studio 2017 Community box including Windows Server 2016 Standard. This options is very useful for tools which take significant time to install, so instead of applying them on the first boot, they can be already included in the Vagrant boxes.

You can also see how the existing configuration is being reused. components/vs/17c includes components/vs/core, which in turn includes the above components/core/core (specifying the memory and the CPU settings). As the list notation suggests, you can include any number or other configurations. If you specify a single value (like the box) defined earlier, it will be overridden. Collections (for example, the list of cookbooks) will be merged, the new values being added after the existing ones.

Components like to appear in groups to form stacks, like using a dedicated .NET version and the related hosting options for local development. For example, for .NET Core you can define to use Docker with the usual images:

# src/stacks/dotnetcore/vagrant.yml
core:
  includes:
    - stacks/dotnet/core
    - stacks/infrastructure/dockere
  chef:
    json:
      gusztavvargadr_workstations_dockere:
        profiles:
          images:
            microsoft/dotnet:sdk-nanoserver:

library:
  includes:
    - stacks/dotnetcore/core
    - stacks/dotnet/library

web:
  includes:
    - stacks/dotnetcore/core
    - stacks/dotnet/web
  chef:
    json:
      gusztavvargadr_workstations_dockere:
        profiles:
          images:
            microsoft/aspnetcore-build:nanoserver:

Source

The referenced generic .NET configuration specifies the default Visual Studio version which you've seen before and includes NuGet as well:

# src/stacks/dotnet/vagrant.yml
core:
  includes:
    - components/vs/v17c
    - components/nuget/core

library:
  includes:
    - stacks/dotnet/core

web:
  includes:
    - stacks/dotnet/core

Source

Stacks aren't of course l'art pour l'art, but to be used in projects. For example, to define the core repositories of the one and only IdentityServer, you can use the following configuration:

# src/projects/identityserver/vagrant.yml
core:
  includes:
    - components/git/core
  chef:
    json:
      gusztavvargadr_workstations_git:
        profiles:
          workspaces:
            identityserver:
              address: https://github.com/identityserver
              directory: /Users/vagrant/Repos/identityserver

v4:
  includes:
    - projects/identityserver/core
    - stacks/dotnetcore/library
    - stacks/dotnetcore/web
  chef:
    json:
      gusztavvargadr_workstations_git:
        profiles:
          workspaces:
            identityserver:
              repositories:
                IdentityServer4:
                  directory: v4/core
                IdentityServer4.AccessTokenValidation:
                  directory: v4/accesstokenvalidation
                IdentityServer4.Samples:
                  directory: v4/samples

Source

This configuration, being referenced in your workstation will check out the mentioned repositories using Git, and install the tools and pull the images as you've seen above.

Finally, you can define your workstation to include projects like this:

# src/people/me/vagrant.yml
work:
  includes:
    - components/os/w16s
    - projects/identityserver/v4
  default: true

Source

And have your Vagrantfile reference the YAML configuration:

# src/people/me/Vagrantfile
directory = File.dirname(__FILE__)
require "#{directory}/../../Vagrantfile.core"

Vagrant.configure('2') do |config|
  gusztavvargadr_workstations_vm config, directory, 'work'
end

Source

This is a quick introduction of what happens behind the scenes when you invoke vagrant up.

Provisioning

Even if being run in a VM with Hyper-V or VirtualBox, Windows still loves to be restarted, and this is especially the case during provisioning, when e.g. Windows Features or specific tools get installed. To support those scenarios when provisioning would require the use of another component which just got installed, but it requires a restart, all the custom cookbooks support being executed in different stages, and the custom Vagrant extension will restart the machine between them.

In the requirements stage core settings like Windows Features and environment variables get installed and configured.

After those have been set up correctly, the tools stage is used to install e.g. Chocolatey packages or applications with native installers.

Finally, in the profiles stage all the tools can now be used properly, for example, to clone Git repositories or manage NuGet sources.

Components

In this section Core | OS | Visual Studio | SQL Server | Vagrant | Docker | AWS | Git | SVN | NuGet

See below the list of components with their features supported out of the box.

Core

  • Sets environment variables
  • Enables Windows Features
  • Installs Chocolatey packages
  • Installs native packages
  • Copies files to the host

Source
Samples

OS

Source
Samples

Visual Studio

Source
Samples

SQL Server

Source
Samples

Vagrant

  • Installs Vagrant
  • Installs plugins
  • Adds boxes

Source
Samples

Docker

Docker Community Edition
  • Installs Docker Community Edition (Edge) (requires Hyper-V host and Windows Server 2016 guest)
  • Pulls Docker images

Source
Samples

Docker Enterprise Edition
  • Installs Docker Enterprise Edition (requires Windows Server 2016 guest)
  • Pulls Docker images

Source
Samples

AWS

  • Installs the AWS command-line tools
  • Configures AWS profiles

Source
Samples

Git

  • Installs Git
  • Clones public or private repositories

Source
Samples

SVN

  • Installs SVN
  • Checks out public or private repositories

Source
Samples

NuGet

  • Installs NuGet
  • Adds sources

Source
Samples

Stacks

In this section .NET | SQL | Infrastructure

See below the list of stacks with their components configured out of the box.

.NET

  • Defines the base box for Visual Studio
  • Configures tools and settings for .NET class libraries
  • Configures tools and settings for .NET web applications

Source
Samples

.NET Core
  • Configures tools and settings for .NET Core class libraries including Docker
  • Configures tools and settings for .NET Core web applications including Docker

Source
Samples

.NET Framework
  • Configures tools and settings for .NET Framework class libraries
  • Configures tools and settings for .NET Framework web applications

Source
Samples

SQL

  • Defines the base box for SQL Server versions
  • Installs SQL Server Management Studio 17

Source
Samples

Infrastructure

  • Installs Vagrant with Chef, Packer and the related Vagrant plugins
  • Installs either:
    • Docker Community Edition
    • Docker Enterprise Edition
    • VirtualBox
    • AWS command-line tools

Source
Samples

Projects

Below is a list of a few sample projects to demonstrate the grouping of source code with the required development and deployment tools:

Using Git:

Using SVN:

  • Apache
    • projects/apache/log4net

People

Your actual workstations reference the above components, stacks and projects and now can ask Vagrant to create them.

clone$ cd src/people/me
clone/src/people/me$ vagrant up (work|playground|private)

The current samples contain only a single personal configuration, but this approach can be used to define baseline configurations for teams or organizations. Simple create a new folder within src/people for your entities, and include the projects and stacks you require as you've seen above. Then include the team or organizaton in your personal one according to your current membership or projects you want to work with.

Contributing

Any feedback, issues or pull requests are welcome and greatly appreciated. Chek out the milestones for the list of planned releases.

Resources

This repository could not exist without the following great tools: