This small guide aims to help all fellow windows users out there, who use VirtualBox on the windows-host-os but want to work with vagrant+ansible smoothly. This goal can be achived by leveraging the sharing-functionalities between the WSL2 and the windows host os.
In general, you have to perform the following steps which will be explained in detail down below:
- Setup and configure WSL2 on your Windows System
- Install a WSL2 distribution (I've used
ubuntu) - Install vagrant within the WSL2 distro (see Basics)
- Install and configure ansible in the WSL2 distro
- Configure networking (see Networking) between WSL2 and Host
- Use an ssh key with correct permissions set for ansible (see SSH Keys)
First of all it is recommended to take a quick look into this guide which explains how WSL2 can be used to run vagrant within the WSL2 distro while actually working with the windows host components. Follow the instructions in order to install Vagrant in your WSL2 distro accordingly.
To access windows resources outside the WSL2 distro, you have to set the following environment variable inside your WSL2 distro:
- Required:
export VAGRANT_WSL_ENABLE_WINDOWS_ACCESS="1"- ensures that vagrant within WSL can access the windows resources, like VirtualBox
- Required:
export PATH="$PATH:/mnt/c/Program Files/Oracle/VirtualBox"- adds the location of virtualbox within WSL2 to the path variable
- Optional: If the base folder is in another location than your home directory, set it accordingly in order to make stuff like
vagrant sshwork.export VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH="/mnt/c/TestDir"
There is well known issue related to networking when WSL2 is used. The problem is, that the network interface attached to WSL2 cannot see the localhost ip address which prevents vagrant ssh from working. You can either specify the correct addresses etc. manually, or just use the plugin virtualbox_WSL2 thankfully provided by Karandash8.
In your WSL2 distro, run: vagrant plugin install virtualbox_WSL2
This will automatically add the specific port-forwarding configuration to the corresponding VM(s).
Now you have to configure your local firewall accordingly. The ethernet adapter used by WSL2 is set by HyperV from Windows and mostly called something like vEthernet (WSL). To fetch the IP-Address and CIDR-Prefix, run the following powershell command:
Get-NetIPAddress | where {$_.InterfaceAlias -like "*WSL*"} | select InterfaceAlias,IPAddress,PrefixLengthThis will output the necessary information that you can use for a firewall rule.
InterfaceAlias IPAddress PrefixLength
-------------- --------- ------------
vEthernet (WSL) fe80::2c1f:abd5:d064:253%49 64
vEthernet (WSL) 172.21.240.1 20
In the example case, the ip range used by the WSL2 ethernet adaptor is 172.21.240.1/20. Use this information to add a firewall-rule.
NOTE: The following example will show you how to create a rule for the Windows-Firewall. If you are using a third-party firewall which does not also process the rules configured for windows-firewall, you have to create the rule manually in your tool! You can use the following settings as a guideline though.
In an administrative powershell session, run:
# Make sure to run the following command as administrator!
New-NetFirewallRule -Name "WSL2LocalHost" -DisplayName "WSL2 to Localhost-VBox Traffic" -Enabled True -Direction Inbound -Profile Any -Action Allow -Protocol TCP -LocalPort "2200-2222" -RemoteAddress "172.21.240.1/20"The output contains the details of the created rule:
Name : WSL2LocalHost
DisplayName : WSL2 to Localhost-VBox Traffic
Description :
DisplayGroup :
Group :
Enabled : True
Profile : Any
Platform : {}
Direction : Inbound
Action : Allow
EdgeTraversalPolicy : Block
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : Die Regel wurde erfolgreich vom Speicher aus analysiert. (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
If you have the need to add/set/remove ports configured in the rule, use the following command:
# make sure to run as administrator
# This will add the port "1234" to the accepted ports
Get-NetFirewallRule WSL2LocalHost | Set-NetFirewallRule -LocalPort ("2200-2222","1234")
# Verify
Get-NetFirewallRule WSL2LocalHost | Get-NetFirewallPortFilterProtocol : TCP
LocalPort : {2200-2222, 1234}
RemotePort : Any
IcmpType : Any
DynamicTarget : Any
Once the rule got applied, (ssh-)traffic from the WSL2 distro will not get blocked any longer.
The last problem that will occur is related to the SSH key used by vagrant. Vagrant uses a standard insecure_private_key file that ships with community-provided boxes. As this file will be mounted via the /mnt/{DRIVE}/Location/on/Windows paths, the permissions will not get set correctly and can't get changed though chmod. Thus the file will have the unix permissions 777 set and therefore be consided as insecure by ansbile. This will prevent the provisioning accordingly.
To address this issue, you need to have an ssh-keypair located within the native WSL2 distro and use this for the provisioning instead of the insecure_private_key file.
What to do (inside your WSL2 distro):
-
create a new ssh key
ssh-keygen- specify the path like:
/home/myuser/.ssh/myFile - Leave the password blank!
- specify the path like:
- Verify that the file and its corresponding
.pubfile were created:ls -la ~/.ssh
-
Use the new key in
Vagrantfile
# Declare a variable that stores the path to your ssh private key file
SECURE_SSH_PRIVATE_KEY = "~/.ssh/devOps"
# Copy the public key to each VM and add it to known_hosts
Vagrant.configure("2") do |config|
config.ssh.insert_key = false
# Insert own ssh key to the machines.
# Taken from: https://stackoverflow.com/questions/30075461/how-do-i-add-my-own-public-key-to-vagrant-vm
vagrant_home_path = ENV["VAGRANT_HOME"] ||= "~/.vagrant.d"
config.ssh.private_key_path = ["#{vagrant_home_path}/insecure_private_key", "#{SECURE_SSH_PRIVATE_KEY}"]
config.vm.provision "file", source: "#{SECURE_SSH_PRIVATE_KEY}.pub", destination: "/home/vagrant/.ssh/SecureKey.pub"
config.vm.provision :shell, privileged: false do |shell_action|
shell_action.inline = <<-SHELL
cat /home/vagrant/.ssh/SecureKey.pub >> /home/vagrant/.ssh/authorized_keys
SHELL
end
# < Additional Vagrant stuff >
end
For a working example, take a look into my customized vagrant-file used for a kubernetes cluster deployment (forked from itwonderlab/ansible-vbox-vagrant-kubernetes. You have to uncomment the respective lines that will inject a secure ssh key into the VMs.
With all of those prerequisites met, you are finally able to run vagrant+ansible from within your WSL2 distro while working with your windows host as operating system. :)
I suggest using VisualStudio code connected to your WSL2 distro. This enables you to easily edit your files mounted into WSL an execute the allmighty vagrant up command directly. :)
👏