| name | vagrant |
| description | Comprehensive guide for developing with Vagrant, including Vagrantfile configuration, custom boxes, providers (VirtualBox, VMware, Hyper-V, libvirt, AWS), provisioners (Ansible, Chef, Puppet), multi-machine setups, networking, synced folders, plugins, and troubleshooting. |
| metadata | {"author":"mte90","version":"1.0.0","tags":["vagrant","virtualization","devops","development-environment","virtualbox","infrastructure","ansible"]} |
Vagrant Development
Complete guide for managing virtual machine environments with Vagrant.
Overview
Vagrant is a tool for building and managing virtual machine environments in a single, consistent workflow.
Key Characteristics:
- Reproducible environments
- Multiple providers (VirtualBox, VMware, Docker)
- Provisioners (Shell, Ansible, Chef, Puppet)
- Multi-machine support
- Portable boxes
Installation
Install Vagrant
brew install hashicorp/tap/hashicorp-vagrant
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install vagrant
choco install vagrant
Install Provider
vagrant plugin install vagrant-vmware-desktop
vagrant plugin install vagrant-libvirt
Basic Vagrantfile
Minimal Configuration
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.hostname = "myvm"
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
end
end
Complete Configuration
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.box_version = ">= 202310.0.0"
config.vm.hostname = "dev-environment"
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 443, host: 8443
config.vm.synced_folder "./app", "/var/www/html"
config.vm.synced_folder "./data", "/data", disabled: false
config.vm.provider "virtualbox" do |vb|
vb.memory = "4096"
vb.cpus = 2
vb.name = "my-dev-vm"
vb.gui = false
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--ioapic", "on"]
end
config.vm.provision "shell",
config.vm.provision ||
ansible.playbook =
ansible.become =
Common Commands
vagrant init ubuntu/focal64
vagrant up
vagrant ssh
vagrant halt
vagrant reload
vagrant destroy
vagrant suspend
vagrant resume
vagrant status
vagrant global-status
vagrant box list
vagrant box add ubuntu/focal64
vagrant box remove ubuntu/focal64
vagrant box update
vagrant box outdated
vagrant plugin list
vagrant plugin install vagrant-vbguest
vagrant plugin uninstall vagrant-vbguest
vagrant validate
vagrant ssh-config
vagrant package --output my-custom.box
Providers
VirtualBox Provider
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.provider "virtualbox" do |vb|
vb.name = "my-vm"
vb.gui = false
vb.memory = 4096
vb.cpus = 2
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
vb.customize ["modifyvm", :id, "--ioapic", "on"]
vb.customize ["modifyvm", :id, "--pae", "on"]
vb.customize ["modifyvm", :id, "--vram", "128"]
vb.customize ["modifyvm", :id, "--accelerate3d", "on"]
vb.customize ["storagectl", :id, "--name", "SATA Controller", "--ahci", "on"]
vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
vb.customize [, , , ]
vb.customize [, , , ]
VMware Provider
Vagrant.configure("2") do |config|
config.vm.box = "bento/ubuntu-22.04"
config.vm.provider "vmware_fusion" do |vmw|
vmw.vmx["memsize"] = "4096"
vmw.vmx["numvcpus"] = "4"
vmw.vmx["vhv.enable"] = "TRUE"
vmw.linked_clone = true
vmw.gui = false
end
config.vm.provider "vmware_workstation" do |vmw|
vmw.vmx["memsize"] = "4096"
vmw.vmx["numvcpus"] = "4"
end
end
Hyper-V Provider
Vagrant.configure("2") do |config|
config.vm.box = "microsoft/windows-server-2022"
config.vm.provider "hyperv" do |hv|
hv.memory = 4096
hv.maxmemory = 8192
hv.cpus = 2
hv.enable_virtualization_extensions = true
hv.enable_checkpoints = true
hv.vmname = "dev-vm"
hv.vlan_id = 100
hv.ip_address_timeout = 180
end
end
libvirt Provider
Vagrant.configure("2") do |config|
config.vm.box = "generic/ubuntu2204"
config.vm.provider :libvirt do |libvirt|
libvirt.cpus = 4
libvirt.memory = 4096
libvirt.driver = "kvm"
libvirt.cpu_mode = "host-passthrough"
libvirt.disk_bus = "virtio"
libvirt.disk_driver :cache => "none", :io => "native"
libvirt.video_type = "qxl"
libvirt.video_vram = "128"
libvirt.interface_type = "bridge"
libvirt.interface_source = "br0"
end
end
AWS Provider
Vagrant.configure("2") do |config|
config.vm.box = "aws"
config.vm.provider :aws do |aws, override|
override.ssh.username = "ec2-user"
override.ssh.private_key_path = "~/.ssh/my-key.pem"
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID']
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
aws.region = "us-east-1"
aws.ami = "ami-0c55b159cbfafe1f0"
aws.instance_type = "t3.medium"
aws.keypair_name = "my-key"
aws.security_groups = ["default"]
aws.tags = {
'Name' => 'vagrant-dev',
'Environment' => 'development'
}
aws.block_device_mappings = [{
device_name: '/dev/sda1',
ebs: {
volume_size: 50,
volume_type: 'gp3',
delete_on_termination: true
}
}]
end
end
DigitalOcean Provider
Vagrant.configure("2") do |config|
config.vm.box = "digitalocean"
config.vm.provider :digital_ocean do |provider|
provider.access_token = ENV['DIGITALOCEAN_ACCESS_TOKEN']
provider.ssh_key_id = "12345678"
provider.image = "ubuntu-22-04-x64"
provider.size = "s-2vcpu-4gb"
provider.region = "nyc3"
provider.ssh_username = "root"
provider.private_networking = true
provider.tags = ["vagrant", "development"]
end
end
Provisioning
Shell Provisioner
Vagrant.configure("2") do |config|
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y nginx
SHELL
config.vm.provision "shell", path: "scripts/setup.sh"
config.vm.provision "shell", path: "scripts/setup.sh",
args: ["--verbose", "--env", "development"]
config.vm.provision "shell", path: "scripts/setup.sh",
env: {
"APP_ENV" => "development",
"DB_HOST" => "localhost"
}
config.vm.provision "shell", path: "scripts/setup.sh",
privileged: false
config.vm.define "web" do |web|
web.vm.provision "shell", inline: "echo 'Web server'"
end
end
Ansible Provisioner
Vagrant.configure("2") do |config|
config.vm.provision "ansible" do |ansible|
ansible.playbook = "provisioning/playbook.yml"
ansible.inventory_path = "provisioning/inventory"
ansible.verbose = "v"
ansible.become = true
ansible.extra_vars = {
http_port: 80,
db_host: "localhost"
}
ansible.tags = ["web", "nginx"]
ansible.skip_tags = ["db"]
ansible.vault_password_file = "~/.vault_pass"
ansible.roles_path = "provisioning/roles"
ansible.galaxy_role_file = "provisioning/requirements.yml"
end
end
Ansible Local (runs on guest)
Vagrant.configure("2") do |config|
config.vm.provision "ansible_local" do |ansible|
ansible.playbook = "playbook.yml"
ansible.install_mode = "pip"
ansible.version = "2.14.0"
ansible.verbose = "v"
ansible.become = true
ansible.galaxy_file = "requirements.yml"
ansible.galaxy_roles_path = "roles"
end
end
Chef Provisioner
Vagrant.configure("2") do |config|
config.vm.provision "chef_solo" do |chef|
chef.cookbooks_path = "cookbooks"
chef.roles_path = "roles"
chef.add_recipe "webserver::default"
chef.add_recipe "database::default"
chef.json = {
webserver: {
port: 80,
docroot: "/var/www/html"
}
}
end
end
Puppet Provisioner
Vagrant.configure("2") do |config|
config.vm.provision "puppet_apply" do |puppet|
puppet.manifests_path = "manifests"
puppet.manifest_file = "site.pp"
puppet.module_path = "modules"
puppet.facter = {
"environment" => "development",
"server_role" => "web"
}
puppet.options = ["--verbose", "--debug"]
end
end
Docker Provisioner
Vagrant.configure("2") do |config|
config.vm.provision "docker" do |d|
d.pull_images "nginx:latest"
d.pull_images "postgres:14"
d.run "nginx",
image: "nginx:latest",
args: "-p 80:80 -v /vagrant/nginx.conf:/etc/nginx/nginx.conf"
d.run "postgres",
image: "postgres:14",
args: "-e POSTGRES_PASSWORD=secret -p 5432:5432"
end
end
Multi-Machine Setup
Basic Multi-Machine
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.define "web" do |web|
web.vm.hostname = "web"
web.vm.network "private_network", ip: "192.168.33.10"
web.vm.network "forwarded_port", guest: 80, host: 8080
web.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
end
web.vm.provision "shell", inline: "apt-get install -y nginx"
end
config.vm.define "db" do |db|
db.vm.hostname = "db"
db.vm.network "private_network", ip: "192.168.33.20"
db.vm.provider "virtualbox" do |vb|
vb.memory = "4096"
end
db.vm.provision "shell", inline: "apt-get install -y postgresql"
end
end
Complex Multi-Machine with Dependencies
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.define "loadbalancer", primary: true do |lb|
lb.vm.hostname = "lb"
lb.vm.network "private_network", ip: "192.168.33.10"
lb.vm.network "forwarded_port", guest: 80, host: 8080
lb.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
lb.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y haproxy
SHELL
end
(1..3).each do |i|
config.vm.define "web#{i}" do |web|
web.vm.hostname = "web#{i}"
web.vm.network "private_network", ip: "192.168.33.#{20 + i}"
web.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
end
web.vm.provision ,
web.vm.provision , ||
s.inline =
config.vm.define ||
db.vm.hostname =
db.vm.network ,
db.vm.provider ||
vb.memory =
db.vm.provision ,
Control Commands
vagrant up
vagrant up web
vagrant up web db
vagrant ssh web
vagrant provision web
vagrant reload web
vagrant destroy web
Networking
Private Networks
Vagrant.configure("2") do |config|
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.network "private_network",
ip: "192.168.33.10",
netmask: "255.255.255.0"
config.vm.network "private_network", type: "dhcp"
config.vm.network "private_network",
ip: "10.0.0.10",
virtualbox__intnet: "internal_network"
end
Public Networks (Bridged)
Vagrant.configure("2") do |config|
config.vm.network "public_network",
bridge: "en0: Wi-Fi (AirPort)"
config.vm.network "public_network",
bridge: "en0",
ip: "192.168.1.100"
config.vm.network "public_network"
end
Port Forwarding
Vagrant.configure("2") do |config|
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port",
guest: 80,
host: 8080,
auto_correct: true
config.vm.network "forwarded_port",
guest: 53,
host: 1053,
protocol: "udp"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 443, host: 8443
config.vm.network "forwarded_port", guest: 3306, host: 3306
end
Synced Folders
VirtualBox Shared Folders (Default)
Vagrant.configure("2") do |config|
config.vm.synced_folder "./app", "/var/www/html"
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.synced_folder "./app", "/var/www/html",
owner: "www-data",
group: "www-data",
mount_options: ["dmode=775", "fmode=664"]
end
NFS (Better Performance)
Vagrant.configure("2") do |config|
config.vm.synced_folder "./app", "/var/www/html",
type: "nfs",
nfs_udp: false,
mount_options: [
"nfsvers=3",
"tcp",
"rsize=32768",
"wsize=32768"
]
end
RSync
Vagrant.configure("2") do |config|
config.vm.synced_folder "./app", "/var/www/html",
type: "rsync",
rsync__auto: true,
rsync__exclude: [".git/", "node_modules/", "*.log"],
rsync__args: ["--verbose", "--archive", "--delete", "-z"]
end
SMB (Windows)
Vagrant.configure("2") do |config|
config.vm.synced_folder "./app", "/var/www/html",
type: "smb",
smb_host: "127.0.0.1",
smb_username: ENV['USER'],
smb_password: ENV['SMB_PASSWORD']
end
Custom Boxes
Packaging a Box
vagrant package --base my-configured-vm --output my-custom.box
vagrant package --base my-vm --output my.box --vagrantfile Vagrantfile.template
vagrant package --base my-vm --output my.box --include README.md,metadata.json
metadata.json
{
"name": "myorg/ubuntu-custom",
"description": "Custom Ubuntu 20.04 with pre-installed tools",
"versions": [
{
"version": "1.0.0",
"providers": [
{
"name": "virtualbox",
"url": "https://example.com/boxes/ubuntu-custom-1.0.0.box",
"checksum": "sha256:abc123...",
"checksum_type": "sha256"
}
]
}
]
}
Adding and Using Custom Boxes
vagrant box add myorg/ubuntu-custom ./my-custom.box
vagrant box add myorg/ubuntu-custom https://example.com/my-custom.box
vagrant box list
vagrant box update --box myorg/ubuntu-custom
vagrant box remove myorg/ubuntu-custom
Publishing to Vagrant Cloud
vagrant cloud auth login
vagrant cloud publish myorg/ubuntu-custom 1.0.0 \
--description "Custom Ubuntu with development tools" \
--provider virtualbox \
--file ./my-custom.box
Plugins
Installing Plugins
vagrant plugin install vagrant-vbguest
vagrant plugin install vagrant-vbguest --plugin-version 0.21.0
vagrant plugin list
vagrant plugin update vagrant-vbguest
vagrant plugin uninstall vagrant-vbguest
Useful Plugins
vagrant plugin install vagrant-vbguest
vagrant plugin install vagrant-hostmanager
vagrant plugin install vagrant-disksize
vagrant plugin install vagrant-snapshot
vagrant plugin install vagrant-cachier
Plugin Configuration
config.vbguest.auto_update = true
config.vbguest.no_remote = true
config.hostmanager.enabled = true
config.hostmanager.manage_host = true
config.hostmanager.manage_guest = true
config.disksize.size = '50GB'
Triggers
Basic Triggers
Vagrant.configure("2") do |config|
config.trigger.before :up do |trigger|
trigger.name = "Before Up"
trigger.info = "Starting VM..."
end
config.trigger.after :up do |trigger|
trigger.name = "After Up"
trigger.run = {inline: "echo 'VM is ready!'"}
end
config.trigger.before :destroy do |trigger|
trigger.name = "Confirm Destroy"
trigger.ask = "Are you sure you want to destroy?"
end
end
Advanced Triggers
Vagrant.configure("2") do |config|
config.trigger.after :up do |trigger|
trigger.run = {
inline: "echo 'VM IP:' && vagrant ssh -c 'ip addr show eth1'"
}
end
config.trigger.after :provision do |trigger|
trigger.run_remote = {
inline: "systemctl status nginx"
}
end
config.vm.define "web" do |web|
web.trigger.after :up do |trigger|
trigger.info = "Web server is up!"
end
end
end
Troubleshooting
Common Errors
SSH Timeout
Vagrant.configure("2") do |config|
config.ssh.timeout = 120
config.ssh.insert_key = false
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
end
end
Network Issues
vagrant ssh -c "ip addr show"
vagrant ssh -c "cat /etc/network/interfaces"
vagrant reload
VBoxManage list natnets
VBoxManage list hostonlyifs
Synced Folder Permission Denied
config.vm.synced_folder "./app", "/var/www/html",
owner: "vagrant",
group: "vagrant",
mount_options: ["dmode=775", "fmode=664"]
Box Download Issues
rm -rf ~/.vagrant.d/tmp/*
vagrant box add ubuntu/focal64 --box-version 202310.0.0
export VAGRANT_SERVER_URL="https://vagrantcloud.com"
Debug Mode
VAGRANT_LOG=debug vagrant up
VAGRANT_LOG=info vagrant up
VAGRANT_LOG=debug VAGRANT_DEFAULT_PROVIDER=virtualbox vagrant up
Reset Environment
vagrant destroy -f
vagrant box remove ubuntu/focal64
rm -rf .vagrant
rm -rf ~/.vagrant.d/data
vagrant up
Performance Optimization
VirtualBox Optimization
Vagrant.configure("2") do |config|
config.vm.provider "virtualbox" do |vb|
vb.memory = 4096
vb.cpus = 2
vb.pae = true
vb.customize ["storagectl", :id, "--name", "SATA Controller", "--ahci", "on"]
vb.customize ["storageattach", :id, "--storagectl", "SATA Controller",
"--type", "hdd", "--nonrotational", "on"]
vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
vb.customize ["modifyvm", :id, "--audio", "none"]
end
config.vm.synced_folder "./app", "/app", type: "nfs"
end
Parallel Operations
Vagrant.configure("2") do |config|
config.vm.define "web"
config.vm.define "db"
config.vm.provision "shell", inline: "apt-get update", run: "always"
end
Best Practices
- Version control your Vagrantfile
- Use specific box versions for reproducibility
- Use provisioners for repeatable setup
- Enable auto_correct for port forwarding
- Use triggers for automation hooks
- Document custom boxes with README
- Test multi-machine setups thoroughly
- Use NFS for better synced folder performance
- Keep Vagrant updated
- Clean up unused boxes regularly
Resources
Quick Reference
Common Vagrantfile Patterns
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.synced_folder ".", "/vagrant"
end
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.provision "shell", path: "setup.sh"
end
Vagrant.configure("2") do |config|
config.vm.define "web"
config.vm.define "db"
end
Common Commands
vagrant up
vagrant ssh
vagrant halt
vagrant destroy
vagrant reload
vagrant provision
vagrant status
vagrant global-status
vagrant box list
vagrant plugin list