Vagrant

Introduction

All the cool kids are using Vagrant for web development (and other kinds of development). What is it?
  • Vagrant is a cross-platform application written in Ruby that, when installed, provides a set of command-line tools for creating and interacting with virtual machines (VMs).
  • Vagrant does not actually run virtual machines. Rather, it depends on a separate program (a "provider") that runs VMs.
  • Typically, the VM provider is VirtualBox, but others are possible (including AWS).
  • Note: On Windows, it's easiest to execute Vagrant-related commands from a Bash shell, since Vagrant-related resources on the web tend to assume that's what you're doing. 
    • So you will also want to install Git Bash, which comes with Git for Windows.
    • You can also use bash from Cygwin (and you might need Cygwin to get rsync, which you need for working with AWS).
Vagrant is so keen to seem simple that it does not explain very well how it works. In particular, it does not explain up front where it stores things, nor does it explain how to change where it stores things. And most Vagrant tutorials that I have seen don't fill this gap. Instead, they provide recipes (do x, y, and z), but they don't teach you how to cook. This page aims to fill the knowledge gap.

First, you must understand that Vagrant basically has three components: two different types of VMs, plus configuration files.
  1. Boxes (VM type 1) are basically templates. You don't really interact with them.
  2. Machines (VM type 2) are created from boxes, but then have a life of their own. They are what you actually interact with.
  3. Configuration files are what Vagrant uses to create a VM from a box. They are named Vagrantfile.
    • Note: Vagrant is very sensitive to the directory you are in when you execute its commands. 

Configuring file locations

Where do Vagrant's three components live by default, how do they get there, and how do you change where they live?
  • Boxes
    • By default, boxes live in the Vagrant home directory, in a "boxes" subdirectory.
      • On Windows, the Vagrant home directory is \.vagrant.d inside a user's home directory (represented by ~), so boxes are at:
        • ~\.vagrant.d\boxes
    • They can get there in two ways: 
      • You can load a box in advance, for future use, with this command: vagrant box add [user/box]
        • So, for instance, this command would add a Ubuntu 14.04 box: 
          • vagrant box add ubuntu/trusty64
        • To update the box:
          • vagrant box update // (to update box specified in current directory) or
          • vagrant box update --box [user/box]
        • Note: if you just specify [user/box], you will pull from Hashicorp's box repository. You can pull from anywhere, though, if you have a URL to the box you want.
      • You can also just begin the process of initializing a specific Vagrant machine, and Vagrant will grab the box and save it in the \boxes subdirectory of Vagrant's home directory if it is not already there.
        • So, for instance, this command will cause Vagrant to grab a Ubuntu 14.04 box if it doesn't already have one: 
          • vagrant init ubuntu/trusty64
    • The easiest way to change where boxes live is to move the Vagrant home directory. This moves everything, not just \boxes. (If you want to move just \boxes, you may have to do something with symlinks or junction points, depending on your OS; I don't discuss that here). You will need to log out and log back in to have Vagrant recognize the change.
      • The home directory is stored in an environment variable, VAGRANT_HOME (though on Windows, I don't think case matters).
      • From a command prompt (either a Windows prompt, or a Git Bash prompt—either works), execute:
        • setx vagrant_home "X:/your/path"
          • This sets it for the current user; OR
        • setx vagrant_home "X:/your/path" /M
          • This sets it globally, for all users
  • Machines
    • Machines are created by your provider at Vagrant's direction, so their location is specified by the provider's setup.
    • On a typical Windows setup using VirtualBox, they will be created in the VirtualBox home directory, in a user's home directory (~) here:
      • ~\.VirtualBox
    • You can change this in the VirtualBox GUI:
      • File -> Preferences -> General -> Default Machine Folder: Set it wherever you would like. 
  • Configuration files
    • Vagrant is sensitive to the directory you are in when you enter commands.
    • But the directory for your configuration files has no direct relationship to the directories for boxes and machines, and it can be arbitrarily named.
    • Typically, however, you will have one directory, with one configuration file in it, per machine. The configuration file is a text file named Vagrantfile.

Creating a Vagrant machine on Windows

Once Vagrant and VirtualBox are installed, creating a Vagrant machine will involve these steps:
  1. Create a directory for your configuration files. Let's call it \vagrant1
  2. Open a Git Bash prompt inside \vagrant1
  3. Run vagrant init, with whatever options you want. So to have Vagrant create a configuration file based on a specific base box: 
    1. vagrant init [user/box]
    2. For instance: vagrant init ubuntu/trusty64
  4. [If you like, review and edit the Vagrantfile that the init command has just created in your directory. The Vagrantfile is a script for creating a new VM; the file's contents determine what your machine (based on the underlying box) will look like.]
    1. In particular, you may want to mess with the port mappings or IP addresses if you want to use your VM for web development.
      1. By default, your Vagrant machine will be at 127.0.0.1 (localhost). The port mappings relate only to this address.
        1. Note: You can have multiple Vagrant VMs running at the same time, all using 127.0.0.1, as long as they have different port mappings.
      2. You can assign your Vagrant machine an IP address by uncommenting this line (set the IP to something on a 192.168.x.x subnet):
        1. config.vm.network "private_network", ip: "192.168.33.10"
          1. But note: the port mappings for localhost do not apply to this IP address. Ports will have their ordinary mappings.
          2. Also note: don't end the IP address in .1. 
    2. Note: You will not have a machine yet. 
  5. [Commit the Vagrantfile to version control (e.g., Git) if you are doing real development.]
  6. [You can further script the creation (i.e., provisioning) of your machine if you like.]
    1. The simplest way to do that is via shell scripting. The shell script will execute inside your VM as Vagrant is creating it.
    2. You can embed your commands right in your Vagrantfile, or you can call the script from inside the Vagrantfile.
    3. Alternatively, you can let Vagrant create the machine first, then execute the script yourself from inside the created machine.
  7. Run vagrant up in this directory.
    1. Vagrant will then use the Vagrantfile to create a machine for you. 
      1. The machine's name will be based on the folder name in which your Vagrantfile is found, and in which you ran vagrant up.For instance:
        1. Directory name: \vagrant1
        2. Machine name (as shown in VirtualBox): vagrant1_default_1475555264808_82184
      2. The machine's hard drive and OS configuration will be in VirtualBox's default folder for VMs.
      3. Other Vagrant-specific files will be in the \.vagrant subdirectory, so in our example, in:
        1. \vagrant1\.vagrant

Interacting with a Vagrant machine on Windows

  • You can log on to the VM via SSH, to get a command prompt, two ways:
    • In the machine's configuration directory, at the command prompt, run: 
      • vagrant ssh
        • Vagrant will authenticate you automatically, with stored credentials (a keypair, I think).
    • Or using an SSH client like Putty, connect to localhost (127.0.0.1) on port 2222
      • User: vagrant
      • Password: vagrant
    • Note: by default, Vagrant machines are set up to forward port 2222 (on the host/your machine) to port 22 (on the guest). If you run multiple Vagrant machines at once, you need to create a unique port forwarding rule for each (e.g., forward 2223 on the host to 22 on the guest). You can do this in your Vagrantfile. See joequery.me's post for more info.
      • Vagrant may also fix this itself, by forward a different port when you run vagrant up for a machine. Check the command-line output to see if Vagrant changed the port assignment.
    • You can assign a different IP (other than 127.0.0.1) to the VM in the Vagrantfile:
      • Uncomment this line: config.vm.network "private_network", ip: "192.168.33.10"
  • In general, to interact with a specific machine, either:
    • Run your commands in the directory that holds the Vagrantfile; or
    • Specify the machine id at the end of the command, e.g., from anywhere, run: 
      • vagrant destroy 12fb333 
  • Other things you might want to do:
    • Get info about all machines: 
      • vagrant global-status
      • vagrant global-status --prune // to force Vagrant to update its cache to be sure you are getting current status information
    • Get info about one machine:
      • vagrant status
    • Get info about port mappings
      • vagrant port
    • Start a machine (or create it if it does not exist):
      • vagrant up
        • Note: If a Vagrant machine's ports collide with those on another machine, Vagrant will create the machine, but might not be able to bring it up if the other is running (it depends on whether Vagrant can remap the ports on its own).
        • This is equivalent to running VBoxManage startvm #NAME -type headless
    • Shut down a machine
      • vagrant halt 
    • Restart a machine
      • vagrant reload
        • Equivalent to vagrant halt, followed by vagrant up
    • Suspend a machine (basically, put it to sleep)
      • vagrant suspend
    • Resume a suspended machine
      • vagrant resume
    • Remove a machine (though not the box it is based on): 
      • vagrant destroy
        • This destroys the VM and its disk, but not any of the configuration files in the directory
    • Share files between your VM and your host machine
      • By default, Vagrant maps :
        • \vagrant inside the VM -> host machine directory holding Vagrantfile (what Vagrant calls the "project directory")
    • Create snapshots of the VM
      • vagrant snapshot [options]

Vagrant and WordPress development

Other features

Resources

Comments