Difference between revisions of "HashiCorp/Vagrant"
(36 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
Vagrant is configured on a per project basis. Each of these projects has its own Vagran file. The Vagrant file is a text file in which vagrant reads that sets up our environment. There is a description of what OS, how much RAM, and what software to be installed etc. You can version control this file. | Vagrant is configured on a per project basis. Each of these projects has its own Vagran file. The Vagrant file is a text file in which vagrant reads that sets up our environment. There is a description of what OS, how much RAM, and what software to be installed etc. You can version control this file. | ||
= | = Install | [https://github.com/hashicorp/vagrant/blob/v2.2.10/CHANGELOG.md Changelog] = | ||
Download or upgrade | |||
<source lang=bash> | |||
# Install using Ubuntu package manager (2024) | |||
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg | |||
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list | |||
apt-cache policy vagrant | |||
sudo apt update && sudo apt install vagrant | |||
# Install downloading a package from sources (2022) | |||
LATEST=$(curl -s GET https://api.github.com/repos/hashicorp/vagrant/tags | jq -r '.[].name' | head -n1 | tr -d v); echo $LATEST | |||
VERSION=${LATEST:=2.2.18}; | |||
wget https://releases.hashicorp.com/vagrant/${VERSION}/vagrant_${VERSION}_linux_amd64.zip | |||
sudo install /usr/bin/vagrant | |||
#sudo dpkg -i vagrant_${VERSION}_x86_64.deb | |||
#sudo apt-get update && sudo apt-get install -f # resolve missing dependencies | |||
# Fix plugins if needed | |||
vagrant plugin update | |||
vagrant plugin repair | |||
vagrant plugin expunge --reinstall | |||
</source> | |||
Install ruby is recommended as configuration within '''Vagrant''' file is written in Ruby language. | |||
<source lang=bash> | |||
sudo apt-get install ruby | |||
sudo gem install bundler | |||
sudo gem update bundler # if update needed | |||
</source> | |||
Repair plugins after the upgrade | |||
<source lang=bash> | |||
vagrant plugin repair # use first | |||
vagrant plugin expunge --reinstall | |||
vagrant plugin update # then update broken plugin | |||
</source> | |||
= Images aka <code>box</code> management = | = Images aka <code>box</code> management = | ||
Line 52: | Line 61: | ||
vagrant box add --force ubuntu/14.04-i386 https://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-i386-vagrant-disk1.box | vagrant box add --force ubuntu/14.04-i386 https://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-i386-vagrant-disk1.box | ||
</source> | </source> | ||
Windows images | |||
* devopsgroup-io/windows_server-2012r2-standard-amd64-nocm | |||
* peru/windows-server-2016-standard-x64-eval | |||
* scotch/box | |||
Line 105: | Line 120: | ||
vagrant init peru/windows-server-2016-standard-x64-eval #Windows 2016, halt works | vagrant init peru/windows-server-2016-standard-x64-eval #Windows 2016, halt works | ||
vagrant init gusztavvargadr/windows-server #Windows 2019, full integration | vagrant init gusztavvargadr/windows-server #Windows 2019, full integration | ||
</source> | |||
;Power up your Vagrant box | ;Power up your Vagrant box | ||
<source lang="bash"> | <source lang="bash"> | ||
vagrant up | vagrant up | ||
</source> | |||
;Ssh to the box. Below example of nested virtualisation 64bit VM(host) runs 32bit (guest vm) | |||
<source lang="bash"> | |||
piotr@vm-ubuntu64:~/git/vagrant$ vagrant ssh #default password is "vagrant" | |||
... | vagrant@vagrant-ubuntu-precise-32:~$ w | ||
13:08:35 up 15 min, 1 user, load average: 0.06, 0.31, 0.54 | |||
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT | |||
vagrant pts/0 10.0.2.2 13:02 1.00s 4.63s 0.09s w | |||
</source> | </source> | ||
;Shared directory between Vagrant VM and an hypervisor provider | ;Shared directory between Vagrant VM and an hypervisor provider | ||
Line 137: | Line 149: | ||
= Troubleshooting = | = Troubleshooting = | ||
<source> | <source> | ||
vagrant --debug up | |||
</source> | </source> | ||
== Nesting VMs == | |||
The error below is due to Virtualbox cannot run nested 64bit virtualbox VM. Spinning up a 64bit VM stops with an error that no 64bit CPU could be found. Update [https://forums.virtualbox.org/viewtopic.php?f=1&t=90831 VirtualBox 6.x Nested virtualization, VT-x/AMD-V in the guest]. | |||
<pre> | |||
Error: | |||
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. | |||
</pre> | |||
= Manage power states = | = Manage power states = | ||
Line 462: | Line 482: | ||
|--metadata.json | |--metadata.json | ||
==Create box from current project (package box) == | == [https://www.vagrantup.com/docs/virtualbox/boxes.html Create box] from current project (package a box) == | ||
This allows to create a reusable box that contains all changes to the software we made | This allows to create a reusable box that contains all changes to the software we made, VirtualBox or Hyper-V supported only. | ||
[https://www.vagrantup.com/docs/cli/package.html Command basics] | |||
<source lang=bash> | |||
vagrant package [options] [name|id] | |||
# --base NAME - instead of packaging a VirtualBox machine that Vagrant manages, | |||
# this will package a VirtualBox machine that VirtualBox manages | |||
# --output NAME - default is package.box | |||
# --include x,y,z - additional files will be packaged with the box | |||
</source> | |||
Package | |||
<source lang=bash> | |||
$ vagrant version # -> Installed Version: 2.2.9 | |||
# Optional '--vagrantfile NAME' can be included, that automatically restores '--include' files | |||
# learn more at https://www.vagrantup.com/docs/vagrantfile#load-order | |||
$ time vagrant package --output u18cli-1.box --include data,git-host,git-host3rd,sync.sh,cleanup.sh | |||
==> default: Clearing any previously set forwarded ports... | |||
==> default: Exporting VM... | |||
==> default: Compressing package to: /home/piotr/vms-vagrant/u18cli-1/2020-05-23-u18cli-1.box | |||
==> default: Packaging additional file: data # <- dir | |||
==> default: Packaging additional file: git-host # <- dir | |||
==> default: Packaging additional file: git-host3rd # <- dir | |||
==> default: Packaging additional file: cleanup.sh # <- file | |||
real 15m27.324s user 8m23.550s sys 0m16.827s | |||
</source> | |||
Re-ristribute the <tt>.box</tt> file then restore it. | |||
<source lang=bash> | |||
# Add the packaged box to local system box repository | |||
# _____box-name________ __box-file_____ | |||
$ vagrant box add --name box-packages/u18cli-1 u18cli-1-v1.box | |||
==> box: Box file was not detected as metadata. Adding it directly... | |||
==> box: Adding box 'u18cli-1-v1.box' (v0) for provider: | |||
box: Unpacking necessary files from: file:///home/piotr/vms-vagrant/test-box-restore/u18cli-1-v1.box | |||
==> box: Successfully added box 'box-packages/u18cli-1' (v0) for 'virtualbox'! | |||
# List boxes | |||
$ vagrant box list | |||
box-packages/u18cli-1 (virtualbox, 0) | |||
$ ls -l ~/.vagrant.d/boxes | |||
total 16 | |||
drwxrwxr-x 3 piotr piotr 4096 Jul 16 17:44 box-packages-VAGRANTSLASH-u18cli-1 | |||
</source> | |||
Restore. Create/re-use Vagrantfile using box you added to your local box repository | |||
<source lang=bash> | |||
# vi Vagrantfile | |||
config.vm.box = "box-packages/u18cli-1.box" | |||
vagrant up | |||
# restore '--include' files coping them from | |||
# 'ls -l ~/.vagrant.d/boxes/box-packages-VAGRANTSLASH-u18cli-1/0/virtualbox/include/*' | |||
</source> | |||
= [https://tuhrig.de/resizing-vagrant-box-disk-space/ Resizing Vagrant box disk] = | |||
* [https://www.vagrantup.com/docs/disks/usage Resizing primary disk] native way | |||
= Enable Vagrant to use proxy server for VMs = | = Enable Vagrant to use proxy server for VMs = | ||
Line 488: | Line 559: | ||
= Virtualbox Guest Additions = | = Virtualbox Guest Additions = | ||
== Sync using vagrant-vbguest plugin == | == Sync using vagrant-vbguest plugin == | ||
Plugin install | |||
<source lang=bash> | <source lang=bash> | ||
vagrant plugin install vagrant-vbguest | |||
vagrant plugin install vagrant-vbguest | |||
#Verify current version, running on a host(hypervisor) | # Verify current version, running on a host(hypervisor) | ||
vagrant vbguest --status | vagrant vbguest --status | ||
#Add to your Vagrant file | # Add to your Vagrant file | ||
if Vagrant.has_plugin?("vagrant-vbguest") | if Vagrant.has_plugin?("vagrant-vbguest") | ||
host.vbguest.auto_update = true | host.vbguest.auto_update = true | ||
Line 504: | Line 574: | ||
;Manual install | |||
Download VBoxGuestAdditions from: | |||
* https://download.virtualbox.org/virtualbox | |||
<source lang=bash> | <source lang=bash> | ||
vagrant vbguest --do install | # Install a matching version to your host version onto the virtual machine. | ||
wget https://download.virtualbox.org/virtualbox/7.0.16/VBoxGuestAdditions_7.0.16.iso | |||
vagrant vbguest --do install --iso VBoxGuestAdditions_7.0.16.iso | |||
Usage: vagrant vbguest [vm-name] [--do start|rebuild|install] [--status] [-f|--force] [-b|--auto-reboot] [-R|--no-remote] [--iso VBoxGuestAdditions.iso] [--no-cleanup] | |||
vagrant vbguest [vm-name] [--do start|rebuild|install] [--status] [-f|--force] | |||
</source> | </source> | ||
More you will find at [https://github.com/dotless-de/vagrant-vbguest vagrant-vbguest] plugin project. | More you will find at [https://github.com/dotless-de/vagrant-vbguest vagrant-vbguest] plugin project. | ||
Line 552: | Line 627: | ||
</source> | </source> | ||
= HAProxy cluster, multi-node Vagrant config = | = Vagrant file = | ||
;Ruby gotchas | |||
Vagrant configuration file is written in Ruby specification, therefore you need to remember | |||
*don't use dashes in object names, '''don't''': <tt>jenkins-minion_config.vm.box = "ubuntu/xenial64"</tt> | |||
*don't use symbols (here underscore) in variable names, '''don't''': <tt>(1..2).each do |minion_number|</tt> | |||
== HAProxy cluster, multi-node Vagrant config == | |||
<source lang="bash"> | <source lang="bash"> | ||
git clone https://github.com/jweissig/episode-45 | git clone https://github.com/jweissig/episode-45 | ||
Line 669: | Line 751: | ||
sudo apt-get install apache2-utils | sudo apt-get install apache2-utils | ||
ansible localhost -m apt -a "pkg=apache2-utils state=present" --become | ansible localhost -m apt -a "pkg=apache2-utils state=present" --become | ||
ab -n 1000 -c 1 http://10.0.2.15:80/ | ab -n 1000 -c 1 http://10.0.2.15:80/ # Apache replaced 'ab' with 'hey' | ||
</source> | </source> | ||
= | = Vagrant DNS = | ||
By default | == Multi-machine mDNS discovery == | ||
Multi-machine setup requires 3 ingredients* : | |||
* each machine to have different hostname | |||
* a way of getting the IP address for a hostname (eg. mDNS) | |||
* connect the VMs through a private network | |||
In multi-machine configuration we need a way of getting the IP address for a hostname. We use <code>mDNS</code> for this. By default <codemDNS</code> only resolves host names ending with the <code>.local</code> top-level domain (TLD). This can cause problems if that domain includes hosts which do not implement mDNS but which can be found via a conventional unicast DNS server. Resolving such conflicts requires network-configuration changes that violate the zero-configuration goal. Install <code>avahi</code> system on all machines to facilitate service discovery on a local network via the <code>mDNS/DNS-SD</code> protocol suite. | |||
<source lang=bash> | <source lang=bash> | ||
config.vm.provision "shell", inline: <<- | config.vm.provision "shell", inline: <<-SCRIPT | ||
apt-get install -y avahi-daemon libnss-mdns | apt-get install -y avahi-daemon libnss-mdns | ||
SCRIPT | |||
</source> | </source> | ||
;References | ;References | ||
*[https://github.com/lathiat/nss-mdns nss-mdns] system which allows hostname lookup of *.local hostnames via mDNS in all system programs using nsswitch | *[https://github.com/lathiat/nss-mdns nss-mdns] system which allows hostname lookup of *.local hostnames via mDNS in all system programs using nsswitch | ||
*[https://www.avahi.org/ avahi.org] | *[https://www.avahi.org/ avahi.org] | ||
= | == Set host system DNS server resolver == | ||
<source lang=ruby> | <source lang=ruby> | ||
config.vm.provider :virtualbox do |vb| | config.vm.provider :virtualbox do |vb| | ||
Line 865: | Line 956: | ||
*[https://cloud-images.ubuntu.com/vagrant/ Vagrant Ubuntu VMs images] Virtualbox | *[https://cloud-images.ubuntu.com/vagrant/ Vagrant Ubuntu VMs images] Virtualbox | ||
*[https://www.vagrantup.com/docs/provisioning/ansible_intro.html Vagrant and Ansible provisioner] Vagrant docs | *[https://www.vagrantup.com/docs/provisioning/ansible_intro.html Vagrant and Ansible provisioner] Vagrant docs | ||
*[https://manski.net/2016/09/vagrant-multi-machine-tutorial/#multi-machine.3A-the-naive-way Vagrant Tutorial – From Nothing To Multi-Machine] Tutorial |
Latest revision as of 20:05, 5 June 2024
Introduction
Vagrant is configured on a per project basis. Each of these projects has its own Vagran file. The Vagrant file is a text file in which vagrant reads that sets up our environment. There is a description of what OS, how much RAM, and what software to be installed etc. You can version control this file.
Install | Changelog
Download or upgrade
# Install using Ubuntu package manager (2024) wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list apt-cache policy vagrant sudo apt update && sudo apt install vagrant # Install downloading a package from sources (2022) LATEST=$(curl -s GET https://api.github.com/repos/hashicorp/vagrant/tags | jq -r '.[].name' | head -n1 | tr -d v); echo $LATEST VERSION=${LATEST:=2.2.18}; wget https://releases.hashicorp.com/vagrant/${VERSION}/vagrant_${VERSION}_linux_amd64.zip sudo install /usr/bin/vagrant #sudo dpkg -i vagrant_${VERSION}_x86_64.deb #sudo apt-get update && sudo apt-get install -f # resolve missing dependencies # Fix plugins if needed vagrant plugin update vagrant plugin repair vagrant plugin expunge --reinstall
Install ruby is recommended as configuration within Vagrant file is written in Ruby language.
sudo apt-get install ruby sudo gem install bundler sudo gem update bundler # if update needed
Repair plugins after the upgrade
vagrant plugin repair # use first vagrant plugin expunge --reinstall vagrant plugin update # then update broken plugin
Images aka box
management
Vagrant comes with a preconfigured image repositories.
- Manage boxes
vagrant box [list | add | remove] [--help]
- Add a box (image) into local repository
These are standard VMs from providers in Virtualbox, VMware or Hyper-V format taken from a given repository
vagrant box add hashicorp/precise64 #user: hashicorp boximage: precise64, this is preconfigured repository vagrant box add ubuntu/xenial64 vagrant box add ubuntu/xenial64 --box-version 20170618.0.0 --provider virtualbox vagrant box add bento/ubuntu-18.04 --box-version 201812.27.0 --provider hyperv # Box can be specified via URLs or local file paths, Virtualbox can only nest 32bit machines vagrant box add --force ubuntu/14.04 https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box vagrant box add --force ubuntu/14.04-i386 https://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-i386-vagrant-disk1.box
Windows images
- devopsgroup-io/windows_server-2012r2-standard-amd64-nocm
- peru/windows-server-2016-standard-x64-eval
- scotch/box
- Update a box to the latest version
$> vagrant box list ubuntu/bionic64 (virtualbox, 20190411.0.0) ubuntu/bionic64 (virtualbox, 20190718.0.0) $> vagrant box update --box ubuntu/bionic64 Checking for updates to 'ubuntu/bionic64' Latest installed version: 20190718.0.0 Version constraints: > 20190718.0.0 Provider: virtualbox Updating 'ubuntu/bionic64' with provider 'virtualbox' from version '20190718.0.0' to '20200124.0.0'... Loading metadata for box 'https://vagrantcloud.com/ubuntu/bionic64' Adding box 'ubuntu/bionic64' (v20200124.0.0) for provider: virtualbox Downloading: https://vagrantcloud.com/ubuntu/boxes/bionic64/versions/20200124.0.0/providers/virtualbox.box Download redirected to host: cloud-images.ubuntu.com $> vagrant box list ubuntu/bionic64 (virtualbox, 20190411.0.0) ubuntu/bionic64 (virtualbox, 20190718.0.0) ubuntu/bionic64 (virtualbox, 20200124.0.0) # <- new downloaded
- Delete all images (aka boxes)
vagrant box prune
vagrant init - your first project
- Configure Vagrantfile to use the box as your base system
Vagrant.configure("2") do |config| config.vm.box = "ubuntu/bionic64" config.vm.hostname = "ubuntu" #hostname, requires reload end
- Create Vagrant project, by creating Vagrantfile in your current directory
vagrant init #initialises an project vagrant init ubuntu/xenial64 # initialises official Ubuntu 16.04 LTS (Xenial Xerus) Daily Build vagrant init ubuntu/bionic64 #supports only VirtualBox provider vagrant init bento/ubuntu-18.04 #supports variety of providers #Windows vagrant init devopsgroup-io/windows_server-2012r2-standard-amd64-nocm #Windows 2012r2, VirtualBox only; cannot ssh vagrant init peru/windows-server-2016-standard-x64-eval #Windows 2016, halt works vagrant init gusztavvargadr/windows-server #Windows 2019, full integration
- Power up your Vagrant box
vagrant up
- Ssh to the box. Below example of nested virtualisation 64bit VM(host) runs 32bit (guest vm)
piotr@vm-ubuntu64:~/git/vagrant$ vagrant ssh #default password is "vagrant" vagrant@vagrant-ubuntu-precise-32:~$ w 13:08:35 up 15 min, 1 user, load average: 0.06, 0.31, 0.54 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT vagrant pts/0 10.0.2.2 13:02 1.00s 4.63s 0.09s w
- Shared directory between Vagrant VM and an hypervisor provider
Vagrant VM shares a directory mounted at /vagrant with the directory on the host containing your Vagrantfile. This can be manually mounted from within VM as long the shared directory is setup in GUI.
Eg. vm_name > Settings > Shared Folders > Name: vagrant | Path: /home/piotr/vm_name
sudo mount -t vboxsf -o uid=1000 vagrant /vagrant #firts arg 'vagrant' refers to GUI setiing
Troubleshooting
vagrant --debug up
Nesting VMs
The error below is due to Virtualbox cannot run nested 64bit virtualbox VM. Spinning up a 64bit VM stops with an error that no 64bit CPU could be found. Update VirtualBox 6.x Nested virtualization, VT-x/AMD-V in the guest.
Error: 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.
Manage power states
vagrant suspend
- saves the current running state of the machine and stop itvagrant halt
- gracefully shuts down the guest operating system and power down the guest machinevagrant destroy
- removes all traces of the guest machine from your system. It'll stop the guest machine, power it down, and remove all of the guest hard disks
Snapshots
You can easily save snapshots.
# Get status $ vagrant status Current machine states: default poweroff (virtualbox) # <- 'default' it's machine name # in multi-vm Vagrant config file The VM is powered off. To restart the VM, simply run `vagrant up` # List vagrant snapshot list ==> default: 11_b4-upgradeVbox-stopped 12_Dec01_stopped # Save <nameOfvm> <snapshot-name> vagrant snapshot save default 13_Dec30_external-eks_stopped # Restore vagrant snapshot restore default 13_Dec30_external-eks_stopped
Lookup path precedence for Vagrant project file
When you run any vagrant command, Vagrant climbs your directory tree starting first in the current directory you are in. Example:
/home/peter/projects/la/Vagrant /home/peter/projects/Vagrant /home/peter/Vagrant /home/Vagrant /Vagrant
Configuration
Networking
Private network is network that is not accessible from Internet. Networking stanza is a part of the main |config| loop.
DHCP IP address assigned
config.vm.network "private_network", type: "dhcp"
Static IP assigment
config.vm.network "private_network", ip: "192.168.80.5" auto_config: false #optional to disable auto-configure
Public network These networks can be accessible from outside of the host machine including Internet, are usually Bridged Networks.
Examples of dhcp and static IP assignment
config.vm.network "public_network", type: "dhcp" config.vm.network "public_network", ip: "192.168.80.5"
Default interface. The name need to match your system name otherwise Vagrant will prompt you to choose from available interfaces during vagrant up process.
config.vm.network "public_network", bridge: 'eth1'
Port forwarding
Vagrant can forward any host(hypervisor) TCP port to guest vm specyfing in ~/git/vargant/Vagrant file
config.vm.network :forwarded_port, guest: 80, host: 4567
Reload virtual machine vagrant reload
and run from hypervisor web browser http://127.0.0.1:4567 to test it.
Sync folders
Vagrant v2 renamed Shared folders into Sync folders. This feature mounts HostOS directory into GuestOS. allowing workflow of editing files with IDE installed on a host machine but access them within GuestOS. The files sync both directions (as mount on GuestOS), Remember, taking vagrant snapshot save ubuntu-snap1
will NOT save the Sync folder content as it's just mounted directory.
When configuring, 1st argument is a path existing on a host machine. If relative then it's relative to the root-project folder (where Vagrantfile exists) and 2nd arg is a full path to the mounted dir on guest-os.
- Enabling Sync folders and Symlinks
This can be done at any time, it's applied during vagrant up | reload
. In general symlinks are disabled by VirtualBox as insecure.
Vagrant.configure("2") do |config| # path on the host mount on the guestOS \ / config.vm.sync_folder "git-host/", "/git", disabled: false end config.vm.provider "virtualbox" do |vb| vb.name = File.basename(Dir.pwd) + "_vagrant" ... vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate//git", "1"] # vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate//vagrant", "1"] # symlinks should be active in root of vm by default # vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"] end
Disabling
Vagrant.configure("2") do |config| config.vm.sync_folder "../data/", "/vagrant-data", disabled: true end
Modifying the Owner/Group
config.vm.sync_folder "../data/", "/vagrant-data", disabled: true, owner: "root", group: "root"
References
- synced-folders Hashicorp docs
Vagrant providers
Vagrant can work with a wide variety of backend providers, such as VMware, AWS, and more without changing Vagrantfile. It's enough to specify the provider and Vagrant will do the rest:
vagrant up --provider=vmware_fusion vagrant up --provider=aws
Hyper-V
- Enable Hyper-V
- if you running Docker for Windows make sure is disabled as only one application can bound to Internal NAT vswitch, if you are using it
- WSL and Windows Vagrant versions must match
- the terminal you run WSL or PowerShell runs with elevated privileges
When running in WSL, make sure you have export VAGRANT_WSL_ENABLE_WINDOWS_ACCESS="1"
,
- you are in native Bash.exe not eg. ConEmu terminal with as it was proven not working at the time. You can change default provider by
export VAGRANT_DEFAULT_PROVIDER=hyperv
Optional: Set the user-level environment variable in PowerShell:
[Environment]::SetEnvironmentVariable("VAGRANT_DEFAULT_PROVIDER", "hyperv", "User")
- Workarounds
Copy insecure private key from https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant to WSL ~/.vagr
ant_key/private_key
because Microsoft filesystem does not support Unix style file permissions, until WSL2 is released.
$ wget https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant -O ~/.vagrant_key/private_key # then set in Vagrantfile config.ssh.private_key_path = "~/.vagrant_key/private_key"
When running on HyperV you need to choose a vswitch you will use. Vagrant will prompt you, select "Default Switch", w
hich is eqvivalent of NAT Network. You need to creat your own vswitch if you want access to Internet.
Go to Hyper-V Manager, open Virtual Switch Manager..., create External switch, name: vagrant-external, press OK. Then
run.
vagrant up --provider hyperv default: Please choose a switch to attach to your Hyper-V instance. default: If none of these are appropriate, please open the Hyper-V manager default: to create a new virtual switch. default: default: 1) DockerNAT default: 2) Default Switch default: 3) vagrant-external default: default: What switch would you like to use?3 #<-- select 3
Read more https://www.vagrantup.com/docs/hyperv/limitations.html
Run Vagrant file
vagrant up --provider=hyperv
References
- Create vSwitch in Hyper-V to run Vagrant
- Copying Files into a Hyper-V VM with Vagrant
- Vagrant and Hyper-V -- Tips and Tricks techcommunity.microsoft.com
Provisioners
Shell provisioner
Vagrant can run from shared location script or from inline: Vagrant file shell provisioning commands.
Create provisioning script
vi ~/git/vagrant/bootstrap.sh #!/usr/bin/env bash export http_proxy=<nowiki>http://username:password@proxyserver.local:8080</nowiki> export https_proxy=$http_proxy apt-get update apt-get install -y apache2 if ! [ -L /var/www ]; then rm -rf /var/www ln -sf /vagrant /var/www # sets Vagrant shared dir to Apache DocumentRoot fi
Configure Vagrant to run this shell script above when setting up our machine
vi ~/git/vagrant/Vagrantfile Vagrant.configure("2") do |config| config.vm.box = ubuntu/14.04-i386 config.vm.provision: shell, path: "bootstrap.sh" end
Another example of using shell provisioner, separating a script out
$script = <<SCRIPT echo " touch /home/vagrant/test_\\`date +%s\\`.txt " > /home/vagrant/newfile chmod +x /home/vagrant/newfile echo "* * * * * /home/vagrant/newfile" > mycron crontab mycron SCRIPT Vagrant.configure("2") do |config| config.vm.box = "ubuntu/xenial64" config.vm.provision "shell", inline: $script , privileged: false end
Bring the environment up
vagrant up #runs provisioning only once vagrant reload --provision #reloads VM skipping import and runs provisioning vagrant ssh #ssh to VM wget -qO- 127.0.0.1 #test Apache is running on VM
- Provisioners - shell, ansible, ansible_local and more
This section is about using Ansible with Vagrant,
*ansible
, where Ansible is executed on the Vagrant host *ansible_local
, where Ansible is executed on the Vagrant guest
Ansible provisioner
Specify Ansible as a provisioner in Vagrant file
# Run Ansible from the Vagrant Host config.vm.provision "ansible" do |ansible| ansible.playbook = "playbook.yml" end
Chef_solo provisioner
Create recipe, the following dirctory structure is required, eg. recipe name is: vagrant_la
├── cookbooks │ └── vagrant_la │ └── recipes │ └── default.rb Vagrant
Recipe
vi cookbooks/vagrant_la/recipes/default.rb execute "apt-get update" package "apache2" execute "rm -rf /var/www" link "var/www" do to "/vagrant" end
In Vagrant file add following
config.vm.provision "chef_solo" do |chef| chef.add_recipe "vagrant_la" end
Run vagrant up
Puppet manifest
Create Vagrant provisioning stanza
config.vm.define "web" do |web| web.vm.hostname = "web" web.vm.box = "apache" web.vm.network "private_network", type: "dhcp" web.vm.network "forwarded_port", guest: 80, host: 8080 web.vm.provision "puppet" do |puppet| puppet.manifests_path = "manifests" puppet.manifest_file = "default.pp" end end
Create a required folder structure for puppet manifests
├── manifests │ └── default.pp └── Vagrantfile
Puppet manifest file
vi manifests/default.pp exec { "apt-get update": command => "/usr/bin/apt-get update", } package { "apache2": require => Exec["apt-get update"], } file { "/var/www": ensure => link, target => "/vagrant", force => true, }
Box images advanced
vagrant box list #list all downloaded boxes
Default path of boxes image, it can be specified by environment variable VAGRANT_HOME
C:\Users\%username%\.vagrant.d\boxes #Windows ~/.vagrant.d/boxes #Linux
Change default path via environment variable
export VAGRANT_HOME=my/new/path/goes/here/
Box format
When you un-tar the .box file it contains 4 files:
|--Vagrantfile |--box-disk1.vmdk #compressed virtual disk |--box.ovf #description of virtual hardware |--metadata.json
Create box from current project (package a box)
This allows to create a reusable box that contains all changes to the software we made, VirtualBox or Hyper-V supported only.
vagrant package [options] [name|id] # --base NAME - instead of packaging a VirtualBox machine that Vagrant manages, # this will package a VirtualBox machine that VirtualBox manages # --output NAME - default is package.box # --include x,y,z - additional files will be packaged with the box
Package
$ vagrant version # -> Installed Version: 2.2.9 # Optional '--vagrantfile NAME' can be included, that automatically restores '--include' files # learn more at https://www.vagrantup.com/docs/vagrantfile#load-order $ time vagrant package --output u18cli-1.box --include data,git-host,git-host3rd,sync.sh,cleanup.sh ==> default: Clearing any previously set forwarded ports... ==> default: Exporting VM... ==> default: Compressing package to: /home/piotr/vms-vagrant/u18cli-1/2020-05-23-u18cli-1.box ==> default: Packaging additional file: data # <- dir ==> default: Packaging additional file: git-host # <- dir ==> default: Packaging additional file: git-host3rd # <- dir ==> default: Packaging additional file: cleanup.sh # <- file real 15m27.324s user 8m23.550s sys 0m16.827s
Re-ristribute the .box file then restore it.
# Add the packaged box to local system box repository # _____box-name________ __box-file_____ $ vagrant box add --name box-packages/u18cli-1 u18cli-1-v1.box ==> box: Box file was not detected as metadata. Adding it directly... ==> box: Adding box 'u18cli-1-v1.box' (v0) for provider: box: Unpacking necessary files from: file:///home/piotr/vms-vagrant/test-box-restore/u18cli-1-v1.box ==> box: Successfully added box 'box-packages/u18cli-1' (v0) for 'virtualbox'! # List boxes $ vagrant box list box-packages/u18cli-1 (virtualbox, 0) $ ls -l ~/.vagrant.d/boxes total 16 drwxrwxr-x 3 piotr piotr 4096 Jul 16 17:44 box-packages-VAGRANTSLASH-u18cli-1
Restore. Create/re-use Vagrantfile using box you added to your local box repository
# vi Vagrantfile config.vm.box = "box-packages/u18cli-1.box" vagrant up # restore '--include' files coping them from # 'ls -l ~/.vagrant.d/boxes/box-packages-VAGRANTSLASH-u18cli-1/0/virtualbox/include/*'
Resizing Vagrant box disk
- Resizing primary disk native way
Enable Vagrant to use proxy server for VMs
Install proxyconf plugin or use vagrant plugin list
to verify if installed
vagrant plugin install vagrant-proxyconf
Configure your Vagrantfile, here particularly host 10.0.0.1:3128 runs CNTLM proxy
Vagrant.configure("2") do |config| config.proxy.http = "http://10.0.0.1:3128" config.proxy.https = "http://10.0.0.1:3128" config.proxy.no_proxy = "localhost,127.0.0.1"
Virtualbox Guest Additions
Sync using vagrant-vbguest plugin
Plugin install
vagrant plugin install vagrant-vbguest # Verify current version, running on a host(hypervisor) vagrant vbguest --status # Add to your Vagrant file if Vagrant.has_plugin?("vagrant-vbguest") host.vbguest.auto_update = true host.vbguest.no_remote = true end
- Manual install
Download VBoxGuestAdditions from:
# Install a matching version to your host version onto the virtual machine. wget https://download.virtualbox.org/virtualbox/7.0.16/VBoxGuestAdditions_7.0.16.iso vagrant vbguest --do install --iso VBoxGuestAdditions_7.0.16.iso Usage: vagrant vbguest [vm-name] [--do start|rebuild|install] [--status] [-f|--force] [-b|--auto-reboot] [-R|--no-remote] [--iso VBoxGuestAdditions.iso] [--no-cleanup]
More you will find at vagrant-vbguest plugin project.
Manual upgrade
Find out what version you are running, execute on a guest VM
vagrant@ubuntu:~$ modinfo vboxguest | grep ^version version: 6.0.10 r132072 vagrant@ubuntu:~$ lsmod | grep -io vboxguest | xargs modinfo | grep -iw version version: 6.0.10 r132072 vagrant@u18cli-3:~$ sudo /usr/sbin/VBoxService --version 6.0.10r132072
Download the extension, you can explore here
wget http://download.virtualbox.org/virtualbox/5.0.32/VBoxGuestAdditions_5.0.32.iso #you need to get it mounted or extracted the content and run inside the VM.
References
List all Virtualbox SSH redirections
vboxmanage list vms | cut -d ' ' -f 2 > /tmp/vms.out && for vm in $(cat /tmp/vms.out); do vboxmanage showvminfo "$vm" | grep ssh; done vboxmanage list vms | cut -d ' ' -f 1 | sed 's/"//g' > /tmp/vms.out && for vm in $(cat /tmp/vms.out); do echo $vm; vboxmanage showvminfo "$vm" | grep ssh; done vboxmanage list vms \ | cut -d ' ' -f 1 \ | sed 's/"//g' > /tmp/vms.out \ && for vm in $(cat /tmp/vms.out); do vboxmanage showvminfo "$vm" \ | grep ssh \ | tr --delete '\n'; echo " $vm"; done sed 's/"//g' #removes double quotes from whole string tr --delete '\n' #deletes EOL, so the next command output is appended to the previous line
Vagrant file
- Ruby gotchas
Vagrant configuration file is written in Ruby specification, therefore you need to remember
- don't use dashes in object names, don't: jenkins-minion_config.vm.box = "ubuntu/xenial64"
- don't use symbols (here underscore) in variable names, don't: (1..2).each do |minion_number|
HAProxy cluster, multi-node Vagrant config
git clone https://github.com/jweissig/episode-45
This creates Ansible mgmt server, Load Balancer and Web nodes [1..2]. HAProxy will be configured via Ansible code.
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| # create mgmt node config.vm.define :mgmt do |mgmt_config| mgmt_config.vm.box = "ubuntu/trusty64" mgmt_config.vm.hostname = "mgmt" mgmt_config.vm.network :private_network, ip: "10.0.15.10" mgmt_config.vm.provider "virtualbox" do |vb| vb.memory = "256" end mgmt_config.vm.provision :shell, path: "bootstrap-mgmt.sh" end # create load balancer config.vm.define :lb do |lb_config| lb_config.vm.box = "ubuntu/trusty64" lb_config.vm.hostname = "lb" lb_config.vm.network :private_network, ip: "10.0.15.11" lb_config.vm.network "forwarded_port", guest: 80, host: 8080 lb_config.vm.provider "virtualbox" do |vb| vb.memory = "256" end end # create some web servers # https://docs.vagrantup.com/v2/vagrantfile/tips.html (1..2).each do |i| config.vm.define "web#{i}" do |node| node.vm.box = "ubuntu/trusty64" node.vm.hostname = "web#{i}" node.vm.network :private_network, ip: "10.0.15.2#{i}" node.vm.network "forwarded_port", guest: 80, host: "808#{i}" node.vm.provider "virtualbox" do |vb| vb.memory = "256" end end end end
Boot strap script bootstrap-mgmt.sh
#!/usr/bin/env bash # install ansible (http://docs.ansible.com/intro_installation.html) apt-get -y install software-properties-common apt-add-repository -y ppa:ansible/ansible apt-get update apt-get -y install ansible # copy examples into /home/vagrant (from inside the mgmt node) cp -a /vagrant/examples/* /home/vagrant chown -R vagrant:vagrant /home/vagrant # configure hosts file for our internal network defined by Vagrantfile cat >> /etc/hosts <<EOL # vagrant environment nodes 10.0.15.10 mgmt 10.0.15.11 lb 10.0.15.21 web1 10.0.15.22 web2 10.0.15.23 web3 10.0.15.24 web4 10.0.15.25 web5 10.0.15.26 web6 10.0.15.27 web7 10.0.15.28 web8 10.0.15.29 web9 EOL
Gitbash path - /c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe
Set bootstrap script for Proxy or No-proxy specific system
Vagrant status Vagrant up Vagrant ssh mgmt ansible all --list-hosts ssh-keyscan web1 web2 lb > ~/.ssh/known_hosts ansible-playbook ssh-addkey.yml -u vagrant --ask-pass ansible-playbook site.yml
Once set it up you can navigate on your laptop to:
http://localhost:8080/ #Website test http://localhost:8080/haproxy?stats #HAProxy stats
Use to verify end server
curl -I http://localhost:8080
Generate web traffic
vagrant ssh lb sudo apt-get install apache2-utils ansible localhost -m apt -a "pkg=apache2-utils state=present" --become ab -n 1000 -c 1 http://10.0.2.15:80/ # Apache replaced 'ab' with 'hey'
Vagrant DNS
Multi-machine mDNS discovery
Multi-machine setup requires 3 ingredients* :
- each machine to have different hostname
- a way of getting the IP address for a hostname (eg. mDNS)
- connect the VMs through a private network
In multi-machine configuration we need a way of getting the IP address for a hostname. We use mDNS
for this. By default <codemDNS only resolves host names ending with the .local
top-level domain (TLD). This can cause problems if that domain includes hosts which do not implement mDNS but which can be found via a conventional unicast DNS server. Resolving such conflicts requires network-configuration changes that violate the zero-configuration goal. Install avahi
system on all machines to facilitate service discovery on a local network via the mDNS/DNS-SD
protocol suite.
config.vm.provision "shell", inline: <<-SCRIPT apt-get install -y avahi-daemon libnss-mdns SCRIPT
- References
- nss-mdns system which allows hostname lookup of *.local hostnames via mDNS in all system programs using nsswitch
- avahi.org
Set host system DNS server resolver
config.vm.provider :virtualbox do |vb| vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] end
Ubuntu with GUI
This article is going to describe to setup Vagrant Virtualbox VM with GUI, setting up xserver with xfce4 as desktop environment.
Locales
This is not working
locale-gen en_GB.utf8 #en_GB.UTF-8 update-locale LANG=en_GB.UTF-8 locale-gen --purge "en_GB.UTF-8" dpkg-reconfigure --frontend=noninteractive locales dpkg-reconfigure --frontend=noninteractive keyboard-configuration localedef -i en_GB -c -f UTF-8 en_GB.utf8 sudo update-locale LANG=en_GB.UTF-8 locale-gen --purge "en_GB.UTF-8"
Troubleshooting
locale -a #shows which locales are available on your system sudo less /usr/share/i18n/SUPPORTED cat /etc/default/locale #Set system wide locales (does not work for users) localectl set-locale LANG=en_GB.UTF-8 LANGUAGE=en_GB:en localectl set-keymap gb localectl set-x11-keymap gb #Quick kb change apt-get install -yq x11-xkb-utils; setxkbmap gb
Gnome3
This setup installs Ubuntu desktop and may require a restart to apply changes to like a taskbar with shortcuts.
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "ubuntu/bionic64" #bento/ubuntu-18.04, ubuntu/xenial64 machineName = File.basename(Dir.pwd) #name as a current working dir # machineName = 'u18gui-1' config.vm.hostname = machineName # Manually check for updates `vagrant box outdated` config.vm.box_check_update = false # Vbguest plugin if Vagrant.has_plugin?("vagrant-vbguest") config.vbguest.auto_update = false config.vbguest.no_remote = true end # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" # Public network, which generally matched to bridged network. # config.vm.network "public_network" # config.vm.synced_folder "hostDir", "/InVagrantMount/path" # config.vm.synced_folder "../data", "/vagrant_data" config.vm.provider "virtualbox" do |vb| vb.gui = true vb.memory = "3072" vb.name = machineName + "_vagrant" end config.vm.provision "shell", inline: <<-SHELL export DEBIAN_FRONTEND=noninteractive setxkbmap gb apt-get update && apt-get upgrade -yq apt-get install -yq ubuntu-desktop --no-install-recommends apt-get install -yq terminator tmux #only U16 xenial to fix Unity #apt-get install -yq unity-lens-files unity-lens-applications indicator-session --no-install-recommends SHELL end
Running up
vagrant plugin install vagrant-vbguest vagrant up && vagrant vbguest --do install && vagrant reload
Xface
Get a basic Ubuntu image working, boot it up and vagrant ssh. Next, enable the VirtualBox display, which is off by default. Halt the VM and uncomment these lines in Vagrantfile:
config.vm.provider :virtualbox do |vb| vb.gui = true end
Boot the VM and observe the new display window. Now you just need to install and start xfce4. Use vagrant ssh and:
sudo apt-get install -y xfce4 virtualbox-guest-dkms virtualbox-guest-utils virtualbox-guest-x11 #guest additions are already installed on most of the Vagrant boxes
Don't start the GUI as root because you really want to stay the vagrant user. To do this you need to permit anyone to start the GUI:
sudo vim /etc/X11/Xwrapper.config and edit it to allowed_users=anybody sudo startxfce4& sudo VBoxClient-all #optional
You should be landed in a xfce4 session.
(Optional) If VBoxClient-all script isn't installed or anything is missing, you can replace with the equivalent:
sudo VBoxClient --clipboard sudo VBoxClient --draganddrop sudo VBoxClient --display sudo VBoxClient --checkhostversion sudo VBoxClient --seamless
References
- Vagrant GUI vms stackoverflow
Windows
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "gusztavvargadr/windows-server" config.vm.box_check_update = false config.vm.provider "virtualbox" do |vb| vb.gui = true # Display the VirtualBox GUI when booting the machine vb.memory = "3072" # Customize the amount of memory on the VM: end # Plugins config.vbguest.auto_update = false config.vbguest.no_remote = true end
Shared location
- enable Network Sharing
- Vagrant path is mapped to
\\VBOXSVR\vagrant
WIP DevOps workstation
This to contain:
- bashrc with git branch in ps1
- bash autocomplete (...samename)
- bash colored symlinks
- bash_logout and .profile to eval ssh-agent and kill on exit
- git install
- ansible 1.9.4
- java Oracle
- clone tfenv and install terraform
- vim install
- vundle install
- [done] python 2.7 OOB in 16.04
- [done]python pip: awscli, boto, boto3, etc..
Challenges:
- Ubuntu 16.04 official box does not come with a default vagrant user but instead comes with ubuntu user. This causes a number of incompatibilities.
- Read more at launchpad vagrant xenial box is not provided with vagrant/vagrant username and password
- Solutions
- on W10 host both users: ubuntu & vagrant exist. Only vagrant has insecure_pub installed OOB. I am coping vagrant user pub key into ubuntu user authorized_keys
- on U16.05 host the official image does not seem to come with vagrant user but Ubuntu user works OOB
- Read more at SO
- [Vagrant's Ubuntu 16.04 vagrantfile default password https://stackoverflow.com/questions/41337802/vagrants-ubuntu-16-04-vagrantfile-default-password]
- How do I add my own public key to Vagrant VM?
- Running a Shell Script Once Only in vagrant
References
- Vagrant Start up documentation
- Vagrant Hashicorp VMs repository Virtualbox
- Vagrant Ubuntu VMs images Virtualbox
- Vagrant and Ansible provisioner Vagrant docs
- Vagrant Tutorial – From Nothing To Multi-Machine Tutorial