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|\n vb.memory = "2048"\n vb.cpus = 2\nend
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|\n web.vm.box = "ubuntu/jammy64"\nend
Define the web machine
config.vm.define "db" do |db|\n db.vm.box = "ubuntu/jammy64"\nend
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/jammy64在当前目录生成一份可用的 Vagrantfile,是所有后续命令的前提vagrant init ubuntu/jammy64
vagrant up创建并启动虚拟机;首次会下载 box 并执行 provision,之后每次启动都会重新跑 provisionvagrant up
vagrant ssh用 vagrant 账号登录虚拟机,省去记用户名与密码vagrant ssh
vagrant halt正常关机,磁盘与配置保留;这是「暂停一天」该用的命令vagrant halt
vagrant destroy销毁虚拟机与其磁盘;不可撤销,Vagrantfile 保留但要重新下载与 provisionvagrant destroy
vagrant suspend / vagrant resume把虚拟机内存快照落盘后挂起,恢复时状态与挂起前完全一致,比 halt 更快但占磁盘vagrant suspend
vagrant reload重启虚拟机并重新执行 provision,是「改了 provision 脚本」后的标准动作vagrant reload
vagrant status查看当前项目下每台机器的状态(running / poweroff / not created)vagrant status
vagrant global-status列出目录下所有项目的虚拟机状态,解决「我是不是在别的目录操作」的困惑vagrant global-status
vagrant box add ubuntu/jammy64把 box 下载到本地缓存,之后其它项目用同一个 box 就不用再下vagrant box add ubuntu/jammy64
vagrant box list列出本地已缓存的 box 与版本,能解释为什么版本对不上vagrant box list
vagrant box outdated检查已装 box 是否有新版本,是升级前的标准检查vagrant box outdated
vagrant box remove ubuntu/jammy64移除本地缓存的 box;报错时先确认没有虚拟机仍在使用它vagrant box remove ubuntu/jammy64
config.vm.box指定使用哪个 box;版本锁定写在这里,改它需要 destroy 后重建才生效config.vm.box = "ubuntu/jammy64"
config.vm.hostname设置虚拟机内主机名,排障时用于确认连的是哪台config.vm.hostname = "dev-server"
vb.memory / vb.cpus在 provider 块里调整内存与 CPU;改后必须 reload 才生效config.vm.provider "virtualbox" do |vb|\n vb.memory = "2048"\n vb.cpus = 2\nend
config.vm.synced_folder "./src", "/var/www"把宿主机目录挂进虚拟机;默认类型是 VirtualBox 共享文件夹,性能差时改 nfsconfig.vm.synced_folder "./src", "/var/www"
type: "nfs"同步目录改用 NFS,在 Linux 宿主机上性能明显好于共享文件夹config.vm.synced_folder "./src", "/var/www", type: "nfs"
disabled: true默认不挂载该目录,需要时再用 vagrant up --enable-... 打开config.vm.synced_folder "./data", "/data", disabled: true
config.vm.provision "shell", path: "setup.sh"引用外部脚本做初始化,脚本逻辑复杂时比 inline 更可维护config.vm.provision "shell", path: "setup.sh"
config.vm.provision "shell", inline: "apt-get update"直接内联一段命令,适合一两行的轻量初始化config.vm.provision "shell", inline: "apt-get update"
forwarded_port把宿主机端口映射到虚拟机端口,是本地访问容器内服务的标准做法config.vm.network "forwarded_port", guest: 80, host: 8080
private_network, ip: "192.168.33.10"私有网络固定 IP,多机互相访问与文档化地址都依赖它config.vm.network "private_network", ip: "192.168.33.10"
vagrant port查映射端口的实际分配值;自动分配或被占用时会与配置不同vagrant port
config.vm.define "web" / "db"定义多台机器,之后可以只操作其中一台config.vm.define "web" do |web|\n web.vm.box = "ubuntu/jammy64"\nend
vagrant up web只启动具名的那一台,多机项目里避免全部拉起来vagrant up web
vagrant ssh web登录指定机器;多机项目里不加名字会登错vagrant ssh web
vagrant provision不重启直接重跑 provision 脚本,是改完 setup.sh 后的正确做法vagrant provision
vagrant provision --provision-with shell只跑 shell 类 provision,跳过 chef/puppet 等其它 provisionervagrant provision --provision-with shell
vagrant snapshot save / restore / list / delete快照是比 box 更细粒度的回滚点,装完依赖后存一个能省大量重装时间vagrant snapshot save my-snapshot
vagrant plugin install安装 Vagrant 插件;provider 支持(virtualbox / libvirt)也靠插件提供vagrant plugin install vagrant-vbguest
vagrant plugin list确认已装插件,排查 provider 不可用时先看这里vagrant plugin list
vagrant package --output my-box.box把当前虚拟机打包成 box 供团队复用,等于团队的自定义基础镜像vagrant package --output my-box.box

Common pitfalls

Symptomvagrant up 报找不到 box,或用的 box 版本与预期不符。

CauseVagrantfile 里写的是浮动版本或短名,本地缓存的却是另一个版本,两者不匹配。

Fix用 vagrant box list 看本地实际版本,再把 Vagrantfile 锁到该精确版本;需要时先 vagrant box add 补齐。

Symptomvagrant destroy 后再 vagrant up,耗时极长且装好的东西全没了。

Causedestroy 销毁的是虚拟机磁盘,provision 的一切都不保留,只有 Vagrantfile 还在。

Fix在装完依赖后执行 vagrant snapshot save my-snapshot,日后用 vagrant snapshot restore 回滚,而不是重装。

Symptom改了 setup.sh 里的命令,重新 vagrant up 却没有生效。

Causeup 只是启动已存在的机器,provision 脚本内容不会因文件变化而自动重跑(即使重跑也依赖脚本自身幂等)。

Fix改完脚本执行 vagrant provision 或 vagrant reload;并让脚本自身可重复执行(用 apt 的 state=present 思路而非裸安装)。

Symptom宿主机能 ping 通私有 IP,但虚拟机里连不上对方。

Cause配置了 private_network 却没指定 ip 时地址不确定;宿主机防火墙与 Vagrant 允许的网段也可能不一致。

Fix为每台机器固定 ip,并确认宿主机防火墙放行了 192.168.33.0/24。

Symptom同步目录在虚拟机里是空的,或者性能极卡。

Cause宿主机路径写错、路径含中文/空格导致挂载失败;默认的共享文件夹在部分场景下 I/O 非常慢。

Fix在虚拟机里 mount 检查挂载是否真的成功;Linux 宿主机上把 type 改成 "nfs"。

Symptom端口映射后宿主机访问不通,报 connection refused。

Cause服务只监听了 127.0.0.1 而不是 0.0.0.0,端口转发进来的连接因此被拒;或端口已被占用。

Fix让服务监听 0.0.0.0,并用 vagrant port 核对实际分配到的宿主端口。

Symptomvagrant box remove 报 box 仍在使用中。

Cause有虚拟机仍在以该 box 创建,Vagrant 拒绝删除正在被引用的 box。

Fix先 vagrant status 确认相关项目,把对应虚拟机 destroy 掉再移除 box。

Symptom多机项目里 `vagrant ssh` 总是登进同一台,停错了机器。

Cause未指定机器名时 Vagrant 使用 Vagrantfile 里第一个 define 的机器。

Fix始终显式写机器名(vagrant ssh web),并用 vagrant status 核对每台的当前状态。

Troubleshooting

  1. 1看当前目录下每台机器的状态

    vagrant status

    区分 not created / poweroff / running,再决定该 up 还是 reload。

  2. 2看所有项目的机器状态

    vagrant global-status

    怀疑自己在别的目录操作时用它定位。

  3. 3核对本地缓存的 box 与版本

    vagrant box list

    版本错配是启动失败的第一嫌疑。

  4. 4检查是否有 box 可升级

    vagrant box outdated

    升级前先备份好 Vagrantfile 与 provision 脚本。

  5. 5确认已装插件与 provider 支持

    vagrant plugin list

    provider 不可用时先确认插件是否装上。

  6. 6查端口实际分配值

    vagrant port

    与 Vagrantfile 里写的 host 端口不一致时,说明发生了自动改分配。

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