Open-source tool for building and managing portable, reproducible virtual development environments using providers like VirtualBox, libvirt, and Hyper-V.
Addresses below are RFC 5737 documentation ranges or placeholders - swap in your own.
Table of Contents#
- Overview
- How Vagrant Works
- Installation
- Vagrantfile Configuration
- Multi-Machine Environments
- Provisioning
- Networking
- Synced Folders
- Box Management
- CLI Reference
- Troubleshooting
- See Also
- Sources
1. Overview#
Vagrant is an open-source tool by HashiCorp for building and managing virtualized development environments. It eliminates "it works on my machine" problems by providing consistent, reproducible environments defined as code.
Key features:
- Provider-agnostic - works with VirtualBox, libvirt/KVM, VMware, Hyper-V, Docker, and more
- Infrastructure as code - environments defined in a
Vagrantfile(Ruby DSL) - Provisioner support - shell scripts, Ansible, Puppet, Chef, Salt
- Multi-machine - define and orchestrate multiple VMs in a single Vagrantfile
- Box ecosystem - pre-built base images from Vagrant Cloud
2. How Vagrant Works#
Vagrant uses three core concepts:
- Boxes - base images (package format) used to create VMs. Each box is a pre-configured OS image.
- Vagrantfile - Ruby configuration file that defines the VM(s), including box, networking, provisioning, and provider-specific settings.
- Providers - the virtualization backend (VirtualBox, libvirt, etc.) that actually runs the VM.
Workflow: vagrant init creates a Vagrantfile, vagrant up builds and starts the VM(s), vagrant ssh connects to them.
3. Installation#
3.1 Installing Vagrant#
# Debian/Ubuntu
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
sudo apt update && sudo apt install vagrant
# Fedora/RHEL
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
sudo dnf install vagrant
# Arch Linux
sudo pacman -S vagrantAlso install a provider (e.g., VirtualBox, libvirt):
# libvirt provider (recommended for KVM users)
vagrant plugin install vagrant-libvirt3.2 Initializing a Project#
mkdir my-project && cd my-project
vagrant init ubuntu/jammy64
vagrant up4. Vagrantfile Configuration#
4.1 Basic Vagrantfile#
Vagrant.configure("2") do |config|
# Base box
config.vm.box = "ubuntu/jammy64"
# Hostname
config.vm.hostname = "dev-server"
# Provider-specific settings
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
vb.name = "dev-server"
end
# libvirt provider settings
config.vm.provider "libvirt" do |lv|
lv.memory = 2048
lv.cpus = 2
end
end4.2 Provider Selection#
# Use a specific provider
vagrant up --provider=libvirt
vagrant up --provider=virtualbox
# Set default provider via environment variable
export VAGRANT_DEFAULT_PROVIDER=libvirt5. Multi-Machine Environments#
Define multiple VMs in a single Vagrantfile for complex environments:
Vagrant.configure("2") do |config|
# Web server
config.vm.define "web" do |web|
web.vm.box = "ubuntu/jammy64"
web.vm.hostname = "web-server"
web.vm.network "private_network", ip: "192.0.2.10"
web.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
web.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y nginx
SHELL
end
# Database server
config.vm.define "db" do |db|
db.vm.box = "ubuntu/jammy64"
db.vm.hostname = "db-server"
db.vm.network "private_network", ip: "192.0.2.11"
db.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
end
db.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y postgresql
SHELL
end
endTarget specific machines:
vagrant up web # Start only the web VM
vagrant ssh db # SSH into the db VM
vagrant halt web # Stop only the web VM
vagrant destroy db -f # Destroy only the db VM6. Provisioning#
6.1 Shell Provisioner#
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
# Inline script
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y nginx
systemctl enable --now nginx
SHELL
# External script
config.vm.provision "shell", path: "scripts/setup.sh"
# Run as unprivileged user (not root)
config.vm.provision "shell", inline: "echo Hello", privileged: false
end6.2 Ansible Provisioner#
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
# Ansible runs from the HOST machine (requires Ansible installed on host)
config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
ansible.inventory_path = "inventory"
ansible.limit = "all"
ansible.verbose = "v"
# Extra variables
ansible.extra_vars = {
env: "development"
}
end
end6.3 Ansible Local Provisioner#
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
# Ansible runs INSIDE the guest VM (no Ansible needed on host)
config.vm.provision "ansible_local" do |ansible|
ansible.playbook = "playbook.yml"
ansible.install = true # Auto-install Ansible in the guest
end
end6.4 Puppet Provisioner#
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.provision "puppet" do |puppet|
puppet.manifests_path = "manifests"
puppet.manifest_file = "default.pp"
puppet.module_path = "modules"
end
end6.5 Provisioning Controls#
# Run provisioners on an already running VM
vagrant provision
# Force provisioners on vagrant up (even if already provisioned)
vagrant up --provision
# Skip provisioners
vagrant up --no-provision
# Run only specific provisioners
vagrant provision --provision-with shell7. Networking#
7.1 Port Forwarding#
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 443, host: 8443, protocol: "tcp"7.2 Private Network#
# Static IP
config.vm.network "private_network", ip: "192.0.2.10"
# DHCP
config.vm.network "private_network", type: "dhcp"7.3 Public Network (Bridged)#
# Bridged to a host interface (VM appears on the LAN)
config.vm.network "public_network", bridge: "eth0"8. Synced Folders#
# Default: project directory synced to /vagrant in guest
# Custom synced folders:
config.vm.synced_folder "./src", "/var/www/html"
config.vm.synced_folder "./data", "/data", type: "nfs"
config.vm.synced_folder "./code", "/code", type: "rsync",
rsync__exclude: [".git/", "node_modules/"]
# Disable the default /vagrant share
config.vm.synced_folder ".", "/vagrant", disabled: true9. Box Management#
9.1 Creating Custom Boxes#
Package a running VM into a reusable box:
# From a VirtualBox VM
vagrant package --output my-custom.box
# Add the custom box locally
vagrant box add my-custom my-custom.box
# Use it in a Vagrantfile
# config.vm.box = "my-custom"9.2 Box Commands#
| Command | Description |
|---|---|
vagrant box list | List all installed boxes |
vagrant box add <name> | Download and add a box |
vagrant box update | Update boxes to latest version |
vagrant box remove <name> | Remove a box |
vagrant box outdated | Check for box updates |
vagrant box prune | Remove old versions of boxes |
10. CLI Reference#
10.1 General Commands#
| Command | Description |
|---|---|
vagrant status | Status of current Vagrant machine(s) |
vagrant global-status | Status of all active Vagrant machines |
vagrant global-status --prune | Remove invalid entries from status list |
vagrant version | Show Vagrant version |
vagrant validate | Validate the Vagrantfile syntax |
10.2 VM Lifecycle#
| Command | Description |
|---|---|
vagrant up | Start and provision the environment |
vagrant halt | Graceful shutdown |
vagrant suspend | Suspend (save state to disk) |
vagrant resume | Resume a suspended machine |
vagrant reload | Halt then up (applies Vagrantfile changes) |
vagrant ssh | Connect via SSH |
vagrant ssh-config | Show SSH config (useful for direct ssh usage) |
vagrant destroy | Remove all traces of the machine |
vagrant destroy -f | Force destroy without confirmation |
10.3 Debugging#
# Verbose output for troubleshooting
VAGRANT_LOG=debug vagrant up
# Show SSH connection details
vagrant ssh-config
# Check Vagrantfile syntax
vagrant validateTroubleshooting#
| Issue | Cause | Solution |
|---|---|---|
vagrant up hangs at SSH | Guest SSH server not starting, or firewall blocking | Check VAGRANT_LOG=debug vagrant up; verify box supports the provider |
| Box download fails | Network issue or box not found | Check box name on Vagrant Cloud; try vagrant box add <url> directly |
| Synced folder mount fails | NFS not installed or firewall blocking | Install nfs-utils; for VirtualBox use type: "virtualbox" instead |
| Provider not found | Plugin not installed | Run vagrant plugin install vagrant-libvirt (or appropriate provider) |
| Port forwarding not working | Host port already in use | Change host port; check with ss -tlnp | grep <port> |
vagrant destroy leaves artifacts | Provider-specific cleanup incomplete | Manually remove VMs from VirtualBox/libvirt; run vagrant global-status --prune |
Provisioner runs every vagrant up | Provisioner not marked as run: "once" | Add run: "once" to provisioner config, or use --no-provision |