diff --git a/.gitignore b/.gitignore
index bfbe3225c773a086d68ea17089bafc59c1cc2c1c..181ec64cb67a268c331e2148b14eafe1550505cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,8 @@ testsdefinitions.txt
 /.testoutput/
 /.cover/
 
+/.vagrant/
+
 codeclimate.json
 
 # Ignore Visual Studio Code internals
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 595edd0548184149941aa3e3ec370ca7cc37847f..31f999e34e9436842fd57727bf141b645f469a6a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -248,10 +248,8 @@ integration windows:
   - cmd /c mklink /D $target_path $current_path
   - cd $GODIR\gitlab-runner
   script:
-  - $packages = (go list ./... | findstr -v "\/vendor\/" | Out-String | %{$_ -replace "\r\n"," "})
-  - $testCommand = "go test $packages"
-  - Invoke-Expression $testCommand
-  - if ( $LASTEXITCODE -ne 0 ) { exit $LASTEXITCODE }
+  - $script = Join-Path -Path "ci" -ChildPath "test_windows.ps1"
+  - Invoke-Expression $script
   allow_failure: true
   only:
   - /.*/@gitlab-org/gitlab-runner
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000000000000000000000000000000000000..298960a8b41087015ed80942e01a3ac60676ee72
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,20 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure('2') do |config|
+  config.vm.define 'win10' do |cfg|
+    cfg.vm.box = 'StefanScherer/windows_10'
+    cfg.vm.communicator = 'winrm'
+
+    cfg.vm.synced_folder '.', 'C:\Go\src\gitlab.com\gitlab-org\gitlab-runner'
+
+    cfg.vm.provision 'shell', path: 'ci/vagrant.ps1'
+  end
+
+  config.vm.provider 'virtualbox' do |vb|
+    vb.gui = false
+    vb.memory = '2048'
+    vb.cpus = 1
+    vb.linked_clone = true
+  end
+end
diff --git a/ci/test_windows.ps1 b/ci/test_windows.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..28113be81ac536364ce48808a05c75868f7a8cc4
--- /dev/null
+++ b/ci/test_windows.ps1
@@ -0,0 +1,16 @@
+param([string]$testOpts = "")
+
+$failed = @()
+go list ./... | Select-String -Pattern "gitlab.com/gitlab-org/gitlab-runner/vendor/" -NotMatch | ForEach-Object {
+    $pkg = %{$_ -replace "\r\n", "" }
+    $testCmd = "go test $testOpts $pkg"
+    Invoke-Expression $testCmd
+    if ( $LASTEXITCODE -ne 0 ) { $failed += $pkg }
+}
+
+if ($failed.count -ne 0) {
+    Write-Host "Failed packages"
+    $failed | Out-String | Write-Host
+
+    exit 1
+}
diff --git a/ci/vagrant.ps1 b/ci/vagrant.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..8e5a1666521f5099cdb75267ec93b23e430f3cd4
--- /dev/null
+++ b/ci/vagrant.ps1
@@ -0,0 +1,111 @@
+$goVersion = "1.8"
+$gitVersion = "2.18.0"
+$srcFolder = "C:\Go\src\gitlab.com\gitlab-org\gitlab-runner"
+
+function Main
+{
+    [environment]::SetEnvironmentVariable("RUNNER_SRC", $srcFolder, "Machine")
+    Install-Go($goVersion)
+    Install-Git($gitVersion)
+    Install-SSH
+}
+
+function Install-Go([string]$version)
+{
+    $file = 'go' + $version +'.windows-amd64.msi'
+    $url = 'https://storage.googleapis.com/golang/' + $file
+    $dest = Download -Url $url
+
+
+    Write-Host "installing go $version..."
+    $logFile = Log-File -App 'go'
+    $MSIArguments = @(
+        "/i"
+        ('"{0}"' -f $dest)
+        "/qn"
+        "/norestart"
+        "/L*v"
+        $logFile
+    )
+    Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow
+
+    Write-Host "done"
+    Remove-Item $dest
+}
+
+function Install-Git([string]$version)
+{
+    $releaseVersion = 'v' + $version + '.windows.1'
+    $file = 'Git-' + $version +'-64-bit.exe'
+    $url = GitHubRelease -Project 'git-for-windows/git' -Version $releaseVersion -File $file
+    $dest = Download -Url $url
+
+    Write-Host "installing git $version..."
+    $logFile = Log-File -App 'git'
+    $InstallArguments = @(
+        "/VERYSILENT"
+        ('/LOG="{0}"' -f $logFile)
+    )
+    Start-Process $dest -ArgumentList $InstallArguments -Wait -NoNewWindow
+
+    Write-Host "done"
+    Remove-Item $dest
+}
+
+function Install-SSH
+{
+    Write-Host "Enable Developer Mode"
+    # Create AppModelUnlock if it doesn't exist, required for enabling Developer Mode
+    $RegistryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
+    if (-not(Test-Path -Path $RegistryKeyPath)) {
+        New-Item -Path $RegistryKeyPath -ItemType Directory -Force
+    }
+
+    # Add registry value to enable Developer Mode
+    New-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -PropertyType DWORD -Value 1
+
+    $cap = Get-WindowsCapability -Online | ? Name -like "OpenSSH.Server*"
+    if (($cap.count -ne 0) -and ($cap[0].State -ne "Installed")) {
+        Write-Host "Install OpenSSH Server"
+        # Install the OpenSSH Server
+        Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
+        # Install the OpenSSHUtils helper module, which is needed to fix the ACL for ths host keys.
+        # Install-Module -Force OpenSSHUtils
+
+        Write-Host "Enable OpenSSH Server"
+        Start-Service sshd
+
+        Write-Host "Open OpenSSH Server port on firewall"
+        # Open firewall port
+        New-NetFirewallRule -Protocol TCP -LocalPort 22 -Direction Inbound -Action Allow -DisplayName SSH
+    }
+}
+
+function GitHubRelease([string]$Project, [string]$Version = 'latest', [string]$File) {
+    'https://github.com/' + $Project + '/releases/download/' + $Version + '/' + $File
+}
+
+function Download([string]$Url) {
+    $dest = [System.IO.Path]::GetTempFileName()
+    [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11"
+    Write-Host "downloading $Url"
+
+    # Create client, set its info, and download
+    $wc = New-Object System.Net.WebClient
+    $wc.UseDefaultCredentials = $true
+    $wc.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
+    $wc.DownloadFile($Url, $dest)
+
+    Write-Host "$url downloaded as $dest"
+    $dest
+}
+
+function Log-File($App)
+{
+    $timestamp = get-date -Format yyyyMMddTHHmmss
+    $logFile = '{0}-{1}.log' -f $App,$timestamp
+    $vagrantFolder = Join-Path -Path $srcFolder -ChildPath ".vagrant"
+    Join-Path -Path $vagrantFolder -ChildPath $logFile
+}
+
+Main