Vagrant Cheatsheet - VM Init, Up, SSH & Provisioning

Vagrant reduces to one promise: write how the environment is built into a Vagrantfile, and vagrant up reproduces the same machine on anyone laptop. The lifecycle commands are not the hard part. What actually breaks are three things: pinning the box version, choosing a synced folder type, and understanding exactly when provision scripts run. This table groups those configuration points alongside the lifecycle commands, covering box management, Vagrantfile settings, networking and synced folders, multi-machine definitions, and snapshots. Reach for it when inheriting a Vagrantfile that will not boot, when sharing an environment with a new teammate, when Windows file watching makes the default shared folder painfully slow, or when you need several machines up together for integration work. The test of a good definition is destructiveness: if destroy followed by up reproduces an equivalent machine, the setup is genuinely portable rather than accidentally working.

SysOps·40 commands·Last updated 2026-07-21
vagrantVirtual MachinesDev Environmentsdevops

Typical Use Case

For teams that need a multi-machine environment on one laptop and want every member to reach the same system with a single command: a local LAMP stack, a multi-node load-balancing rehearsal, or a CI job needing a service dependency. The machine and its provisioning scripts both live in a reviewable Vagrantfile, so the key is four state lines: VM lifecycle, box management, networking and synced folders, and provisioning on up and reload. The command to fear is destroy.

VM Lifecycle 9

vagrant init ubuntu/jammy64
Initialize a Vagrant project
vagrant up
Start the VM
vagrant ssh
SSH into the VM
vagrant halt
Shut down the VM
vagrant destroy
Destroy the VM
vagrant suspend / vagrant resume
Suspend / resume the VM
vagrant reload
Restart and reload config
vagrant status
Show VM status
vagrant global-status
List all local Vagrant environments

Box Management 6

vagrant box add ubuntu/jammy64
Download a box image
vagrant box list
List installed boxes
vagrant box outdated
Check for box updates
vagrant box update --box ubuntu/jammy64
Update a specific box
vagrant box remove ubuntu/jammy64
Remove a box image
vagrant box add my-box ./package.box
Add a box from a local file

Vagrantfile 6

config.vm.box = "ubuntu/jammy64"
Set the base box
config.vm.hostname = "dev-server"
Set the hostname
config.vm.provider "virtualbox" do |vb| vb.memory = "2048" vb.cpus = 2 end
Configure VM resources
config.vm.synced_folder "./src", "/var/www"
Sync a folder
config.vm.provision "shell", path: "setup.sh"
Shell script provisioning
config.vm.provision "shell", inline: "apt-get update"
Inline shell provisioning

Network & Sync 6

config.vm.network "forwarded_port", guest: 80, host: 8080
Port forwarding
config.vm.network "private_network", ip: "192.168.33.10"
Private network (fixed IP)
config.vm.network "public_network"
Public network (bridged)
config.vm.synced_folder "./src", "/var/www", type: "nfs"
NFS sync (better performance)
config.vm.synced_folder "./data", "/data", disabled: true
Disable a sync folder
vagrant port
Show port-forward mappings

Multi-Machine & Provision 6

config.vm.define "web" do |web| web.vm.box = "ubuntu/jammy64" end
Define the web machine
config.vm.define "db" do |db| db.vm.box = "ubuntu/jammy64" end
Define the db machine
vagrant up web
Start a specific machine
vagrant ssh web
SSH into a specific machine
vagrant provision
Re-run provisioning
vagrant provision --provision-with shell
Run only a provisioner type

Snapshots & Plugins 7

vagrant snapshot save my-snapshot
Save a snapshot
vagrant snapshot restore my-snapshot
Restore a snapshot
vagrant snapshot list
List all snapshots
vagrant snapshot delete my-snapshot
Delete a snapshot
vagrant plugin install vagrant-vbguest
Install a plugin (auto Guest Additions)
vagrant plugin list
List installed plugins
vagrant package --output my-box.box
Package the VM into a box

Parameter matrix

ParameterEffectExample
vagrant init ubuntu/jammy64Writes a working Vagrantfile into the current directory; every later command depends on this file existing.vagrant init ubuntu/jammy64
vagrant upCreates and boots the machine. The first run downloads the box and provisions it, and every later boot runs provisioning again.vagrant up
vagrant sshLogs in as the vagrant account, which spares you from remembering a username and password.vagrant ssh
vagrant haltPowers the machine off cleanly while keeping its disk and configuration. This is the right command for pausing work overnight.vagrant halt
vagrant destroyDestroys the machine and its disk. It cannot be undone; the Vagrantfile survives but the box download and provisioning have to happen again.vagrant destroy
vagrant suspend / vagrant resumeWrites a memory snapshot to disk and suspends; resume brings the machine back exactly as it was. Faster than halt, but it consumes disk.vagrant suspend
vagrant reloadRestarts the machine and re-runs provisioning, the standard response after editing a provisioning script.vagrant reload
vagrant statusShows the state of every machine in the project: running, poweroff or not created.vagrant status
vagrant global-statusLists the machines of every project under the directory, which settles the "am I operating in the wrong folder" confusion.vagrant global-status
vagrant box add ubuntu/jammy64Caches a box locally, so other projects using the same box no longer download it.vagrant box add ubuntu/jammy64
vagrant box listLists the locally cached boxes and their versions, which often explains a version mismatch.vagrant box list
vagrant box outdatedReports whether cached boxes have newer versions available, the standard pre-upgrade check.vagrant box outdated
vagrant box remove ubuntu/jammy64Removes a cached box; if it refuses, check first whether a machine is still built from it.vagrant box remove ubuntu/jammy64
config.vm.boxSelects which box to use. The version pin lives here, and changing it requires a destroy and rebuild to take effect.config.vm.box = "ubuntu/jammy64"
config.vm.hostnameSets the hostname inside the machine, handy for confirming which box you are actually connected to.config.vm.hostname = "dev-server"
vb.memory / vb.cpusTunes memory and CPU inside the provider block; a reload is required before the new values apply.config.vm.provider "virtualbox" do |vb| vb.memory = "2048" vb.cpus = 2 end
config.vm.synced_folder "./src", "/var/www"Mounts a host directory into the guest. The default VirtualBox shared folder is slow, so switch to nfs when performance matters.config.vm.synced_folder "./src", "/var/www"
type: "nfs"Serves the mount over NFS instead, noticeably faster than shared folders on a Linux host.config.vm.synced_folder "./src", "/var/www", type: "nfs"
disabled: trueLeaves the directory unmounted by default, to be enabled on demand with vagrant up and the matching enable flag.config.vm.synced_folder "./data", "/data", disabled: true
config.vm.provision "shell", path: "setup.sh"Points at an external script for initialisation, which stays maintainable once the script logic grows past a line or two.config.vm.provision "shell", path: "setup.sh"
config.vm.provision "shell", inline: "apt-get update"Inlines a command directly, suitable for one-line initialisation steps.config.vm.provision "shell", inline: "apt-get update"
forwarded_portMaps a host port onto a guest port, the standard way to reach a service running inside the machine.config.vm.network "forwarded_port", guest: 80, host: 8080
private_network, ip: "192.168.33.10"Assigns a fixed address on the private network; both machine-to-machine access and documented addresses depend on it.config.vm.network "private_network", ip: "192.168.33.10"
vagrant portReports the port actually assigned, which differs from the configuration when Vagrant picked a free port or the configured one was taken.vagrant port
config.vm.define "web" / "db"Defines several machines so that later commands can address just one of them.config.vm.define "web" do |web| web.vm.box = "ubuntu/jammy64" end
vagrant up webStarts only the named machine, which avoids booting the whole set in a multi-machine project.vagrant up web
vagrant ssh webLogs into a specific machine; without the name a multi-machine project logs into the wrong one.vagrant ssh web
vagrant provisionRe-runs the provisioning scripts without rebooting, which is the correct move after editing setup.sh.vagrant provision
vagrant provision --provision-with shellRuns only the shell provisioners and skips the chef, puppet and other provisioners.vagrant provision --provision-with shell
vagrant snapshot save / restore / list / deleteSnapshots give finer-grained rollback points than boxes; taking one after dependencies are installed saves a great deal of reinstall time.vagrant snapshot save my-snapshot
vagrant plugin installInstalls a Vagrant plugin. Provider support for virtualbox or libvirt also arrives through plugins.vagrant plugin install vagrant-vbguest
vagrant plugin listLists installed plugins, the first place to look when a provider seems unavailable.vagrant plugin list
vagrant package --output my-box.boxPackages the current machine as a box the team can reuse, effectively a custom base image you own.vagrant package --output my-box.box

Common pitfalls

Symptomvagrant up reports that the box cannot be found, or boots a version other than the one expected.

CauseThe Vagrantfile names a floating version or a short name while the local cache holds a different version, and the two do not line up.

FixRun vagrant box list to see the version actually cached, pin the Vagrantfile to that exact version, and add the box with vagrant box add if it is missing.

SymptomAfter vagrant destroy the next vagrant up takes forever and everything installed is gone.

Causedestroy wipes the virtual disk, so nothing that provisioning created survives; only the Vagrantfile remains.

FixTake a snapshot once dependencies are in place with vagrant snapshot save my-snapshot and roll back with vagrant snapshot restore rather than reinstalling.

SymptomCommands were changed inside setup.sh, but re-running vagrant up makes no difference.

Causeup merely boots an existing machine; editing the provisioning file does not by itself trigger a re-run, and a re-run is only safe if the script itself is idempotent.

FixRun vagrant provision or vagrant reload after editing, and write the script so it can be executed repeatedly, for example by asking package managers to converge on a desired state rather than installing unconditionally.

SymptomThe host can ping the private address, but machines inside the environment cannot reach each other.

CauseA private_network was configured without an ip, leaving the address uncertain, and the host firewall may not permit the subnet Vagrant chose.

FixPin an ip for every machine and confirm the host firewall allows 192.168.33.0/24.

SymptomThe synced folder appears empty inside the machine, or file access is painfully slow.

CauseThe host path is wrong or contains characters that break the mount, and the default shared folder is extremely slow in some setups.

FixCheck the mount inside the machine to confirm it really attached, and set type to "nfs" on a Linux host.

SymptomA forwarded port refuses connections from the host with connection refused.

CauseThe service listens on 127.0.0.1 rather than 0.0.0.0, so forwarded connections are rejected, or the port was already taken.

FixHave the service bind 0.0.0.0 and confirm the host port with vagrant port.

Symptomvagrant box remove reports that the box is still in use.

CauseA machine is still built from that box, and Vagrant refuses to remove one that is referenced.

FixRun vagrant status to find the projects involved, destroy those machines, then remove the box.

SymptomIn a multi-machine project vagrant ssh always lands on the same machine.

CauseWith no machine name given, Vagrant picks the first machine defined in the Vagrantfile.

FixAlways pass the name explicitly, as in vagrant ssh web, and cross-check each machine with vagrant status.

Troubleshooting

  1. 1Check the state of every machine in this directory

    vagrant status

    Telling not created, poweroff and running apart decides whether to bring a machine up or reload it.

  2. 2Check machine state across all projects

    vagrant global-status

    Use it to locate yourself whenever you suspect the current directory is not the right one.

  3. 3Verify cached boxes and their versions

    vagrant box list

    A version mismatch is the first suspect when boot fails.

  4. 4Check whether a box upgrade is available

    vagrant box outdated

    Back up the Vagrantfile and the provisioning scripts first.

  5. 5Confirm installed plugins and provider support

    vagrant plugin list

    Check this before assuming anything about a missing provider.

  6. 6Look up the port actually assigned

    vagrant port

    A value that differs from the host port in the Vagrantfile means Vagrant reallocated it automatically.

Command Examples

Bring up a dev box with a forwarded port

vagrant init ubuntu/jammy64 vagrant box add ubuntu/jammy64 vagrant up vagrant port vagrant ssh

vagrant init only writes the Vagrantfile; it does not download the image, so run vagrant box add explicitly. Vagrant may fetch it automatically when synced folders are configured, but adding it first avoids surprises. vagrant port tells you the mapping that actually took effect: when 8080 is already taken, VirtualBox silently shifts to the next port, so never assume the number in your config file.

Output

==> web: 80 (guest) => 8080 (host)
==> default: Running (virtualbox)

Provision is the idempotent entry point; re-run it while debugging

vagrant provision vagrant provision --provision-with shell vagrant reload

After editing setup.sh there is no need to destroy and up: vagrant provision re-runs the script and saves minutes of rebuild time. Shell provisions must be idempotent on their own — apt-get update always runs, and an unguarded >> appends the config a second time — because Vagrant only guarantees the script runs once, not that it is safe to run twice.

Snapshot before any destructive operation

vagrant status vagrant snapshot save my-snapshot vagrant snapshot list vagrant snapshot restore my-snapshot

Save a snapshot before destroy: recovery then means vagrant snapshot restore my-snapshot instead of starting over with a fresh vagrant init, up, and a full provision run. Snapshots live in the .vagrant directory, so make sure no cleanup script removes them — they can be copied along with the project directory.

Multi-machine: define them, then bring up a specific one

vagrant status vagrant up web vagrant ssh web vagrant global-status

Two config.vm.define blocks live in the same Vagrantfile, and a bare vagrant up starts every machine, doubling memory and port usage. Always name the machine explicitly when you only need the web box. vagrant global-status shows every VM across every project on the host, which makes it the first place to look when a box "is up but unreachable".

Output

==> web: machine => web
==> db: machine => db

Drop the default synced folder in favour of a fixed-IP direct route

config.vm.synced_folder "./data", "/data", disabled: true config.vm.network "private_network", ip: "192.168.33.10" vagrant reload

Shared folders provided by the hypervisor are far slower than native host IO for build-heavy work. The common pattern is disabled: true on the default /vagrant mount plus a private_network fixed IP, so the host reads and writes the guest directory directly. A vagrant reload is required for the network change to take effect.

Common Pitfalls

  • vagrant destroy cannot be undone: the virtual disk, everything provisioned, databases, and keys inside are gone. Source survives if the default synced_folder mount exists, but apt packages, database files, and manually created users inside the VM are destroyed with it. Always vagrant snapshot save first, or vagrant package --output backup.box to keep a copy.
  • vagrant halt only powers the machine off (state: poweroff) while vagrant destroy deletes it. Both make the box "disappear", but halt can be undone with vagrant up and keeps its data. When someone says they "shut it down", confirm they are not about to run destroy.
  • A synced_folder mounts the entire host project directory read-write inside the VM. Any code running there, including postinstall scripts of dependencies or a Makefile target, can rewrite your host sources. On untrusted environments or unknown projects, think hard about that mount direction before starting.
  • A forwarded_port whose host port is already taken does not error; VirtualBox silently moves to the next free port and vagrant up still reports success. A CI script hardcoding http://localhost:8080 then talks to the wrong thing or nothing. Read the real mapping with vagrant port instead of hardcoding it.
  • vagrant box remove deletes the global box cache (by default under ~/.vagrant.d/boxes). Removing a shared team image means every machine re-downloads hundreds of megabytes to several gigabytes on the next vagrant up, which simply hangs offline. Check vagrant box list and tell the team first.
  • vagrant package captures the full current state, including all data, tokens, .env files, and private keys (unattended VirtualBox generates authorized_keys inside the machine). Never upload the resulting .box to a public location or commit it; strip sensitive data first.

Tips

  • vagrant up downloads the box on first run; later starts are fast.
  • Vagrantfile is Ruby, but only basic config is needed.
  • vagrant-vbguest auto-updates VirtualBox Guest Additions.
  • snapshot save/restore quickly persists/restores VM state.
  • NFS sync outperforms the default VBox shared folder for big projects.
  • vagrant package bundles a configured VM into a box for sharing.

FAQ

Should I reload or destroy the VM after installing new dependencies?

Prefer vagrant reload: it restarts the machine and re-reads the Vagrantfile while keeping the data on disk. To re-run provisioning scripts, use vagrant provision, or scope it to one provisioner with --provision-with shell. vagrant suspend and vagrant resume are the fastest pair for closing the laptop and picking work back up. vagrant destroy wipes the machine and every change in it, so reserve it for deliberate clean slates. For a read-only check use vagrant status, or vagrant global-status to see every Vagrant environment on the machine at once.

Why is a prepared VM so much faster than the base box, and what does it cost me?

The first vagrant up downloads the box image and runs a full provision pass that installs dependencies and initialises the machine; every later boot reuses that on-disk state and is ready in seconds. The cost is a slow first run plus a locally dirty environment: after editing a template you must reload or re-provision manually. When repeated rebuilds get expensive, store a clean baseline with vagrant snapshot save my-snapshot and return to it any time via vagrant snapshot restore my-snapshot. Review them with vagrant snapshot list and delete the ones you no longer need.

How do I define multiple machines (web and db) in the Vagrantfile?

Name each machine with config.vm.define: config.vm.define "web" do |web| web.vm.box = "ubuntu/jammy64" end and config.vm.define "db" do |db| db.vm.box = "ubuntu/jammy64" end. Then vagrant up web boots just that machine and vagrant ssh web logs into it, while omitting the name starts everything. Cross-machine access is handled by the network config: config.vm.network "forwarded_port", guest: 80, host: 8080 publishes a guest port on the host, and vagrant port shows the active mapping. For a stable address use config.vm.network "private_network", ip: "192.168.33.10".

Installing dependencies over the shared folder is painfully slow — what about NFS?

The default VirtualBox shared folder performs badly with many small files, exactly what npm install and pip install generate. Switching with config.vm.synced_folder "./src", "/var/www", type: "nfs" routes traffic through NFS and is typically far quicker. Trim the surface with config.vm.synced_folder "./data", "/data", disabled: true so large trees are not mounted at all. Size the machine itself in the same config.vm.provider "virtualbox" block: vb.memory = "2048" and vb.cpus = 2, so the VM has enough headroom before you install anything. You can also run vagrant plugin install vagrant-vbguest to keep Guest Additions current.

How do I hand my tuned VM to the team instead of making everyone reinstall?

Export it: vagrant package --output my-box.box bundles the current VM into a box file, and a teammate installs it locally with vagrant box add my-box ./package.box before pointing their project at it. Tidy your box inventory first with vagrant box list, check vagrant box outdated for newer versions, refresh one with vagrant box update --box ubuntu/jammy64, and reclaim space with vagrant box remove for anything unused. Keep the Vagrantfile and provision scripts under version control as the source of truth — the packaged box is a snapshot of the environment, and both together are what guarantee your colleague gets the same setup.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Jul 21, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us