Thomas Venturini
Vagrant - Configuration

Vagrant - Configuration

When you're done with the vagrant basics, this is what you should learn next.

Vagrantfile

The Vagrantfile created through the vagrant init ubuntu/xenial64 command, which we used in my last article, contains the main configuration of your vagrant box. Each vagrant project has it's own Vagrantfile. Vagrant is mostly used for development environments so you should commit your Vagrantfile to your version control system. This allowes your team to use the same setup as you do.

The Vagrantfile is also the place where you can do some basic provisioning or leave a reference to a dedicated provisioning script. If you do the provisioning in the Vagrantfile you should keep it simple and clean. If it gets complex, better use the dedicated provisioning script.

The Vagrantfile is written in Ruby but you don't need to know Ruby to do your configuration, so don't worry. It's all just basic variable assignment.

More Vagrantfiles - Load Order and Merging

When you set up a vagrant project, most of the time, you will be editing the Vagrantfile of the current project, but thats not the only Vagrantfile vagrant will load during the vagrant up setup. In this section we will cover the most important ones.

  1. The Vagrantfile which commes with the loaded box, located in ~/.vagrant.d/boxes/<BOX>/<VERSION>/<DRIVER>
  2. Your personal Vagrantfile in ~/.vagrant.d
  3. The Vagrantfile of your project

These Vagrantfiles are loaded in the given order. I recommend that you take a look at each one before you proceed but we will cover them here anyway.

The Box Configuration

This is the Vagrantfile that commes with the vagrant box ubuntu/xenial64 (~/.vagrant.d/boxes/ubuntu-VAGRANTSLASH-xenial64/20180313.0.0/virtualbox/Vagrantfile).

# Front load the includes
include_vagrantfile = File.expand_path("../include/_Vagrantfile", __FILE__)
load include_vagrantfile if File.exist?(include_vagrantfile)

Vagrant.configure("2") do |config|
  config.vm.base_mac = "022CD457A04B"

  config.vm.provider "virtualbox" do |vb|
     vb.customize [ "modifyvm", :id, "--uart1", "0x3F8", "4" ]
     vb.customize [ "modifyvm", :id, "--uartmode1", "file", File.join(Dir.pwd, "ubuntu-xenial-16.04-cloudimg-console.log") ]
  end 
end

This first tries to load another Vagrantfile or _Vagrantfile in this case, which is not present on my system. But it tells us, that we are free to add other configurations to our setup by simply loading them with the following logic.

include_configuration = File.expand_path("path/to/another/_Vagrantfile", __FILE__)
load include_configuration if File.exist?(include_configuration)

Next step in the box configuration is to init the actual configuration.

Vagrant.configure("2") do |config|
    ...
end

This only contains one thing to know - remember: we are not doing ruby, we are doing configuration. Vagrant enables you to switch between the old type of configuration wich is obsolete and the new one. So the passed argument of 2 refers to the new version, 1 would refer to the old one. You will see this in the other Vagrantfiles that we will look into as well.

Inside the configuration block there is only one thing worth to mention, which would be the setting for the log file. You can change the name of the logfile from ubuntu-xenial-16.04-cloudimg-console.log to anything you want.

vb.customize [ "modifyvm", :id, "--uartmode1", "file", File.join(Dir.pwd, "ubuntu-xenial-16.04-cloudimg-console.log") ]

Keep these three things in mind, they could comme in handy.

Personal Vagrantfile

This Vagrantfile is here to do some personalized configuration. If you have anything that you want present for all your projects or on this particular host system then you would add it in here.

A usefule example for this file might be to use a different provider than virtual box.

The file would be placed in the ~/.vagrant.d directory and is available for the given user.

Thats all there is to it for this one. Now lets go further and check the project configuration.

Project Vagrantfile

The basic Vagrantfile of our project, without all the comments, is as small as the following. But we are going to extend it.

Vagrant.configure("2") do |config|

  config.vm.box = "ubuntu/xenial64"

end

The current version of our Vagrantfile only contains the known configuration block with one new setting. As you can see it holds the chosen box.

At this point it also makes sense to talk about the config.vm configuration stack. This holds all settings of the virtual machine that vagrant manages.

As you might remember, by default the virtual machine you bring up with vagrant up is called default. This is most often the first thing I change. so let's update our Vagrantfile. Pay attention to the missing = in the code line.

Vagrant.configure("2") do |config|

  config.vm.box = "ubuntu/xenial64"

  # name your vagrant project
  config.vm.define "awesome-project"

end

We can confirm our changes with the following command.

vagrant status
Current machine states:

awesome-project           not created (virtualbox)

From now on, if we start the virtual machine it will have the name of awesome-project - sweet!

Now we are going to add some useful basics that you should know. Remember, that all the settings I am going to show are available as comments in your Vagrantfile, so you don't need to write them out if you pick one for your configuration.

When you are running vagrant up, vagrant checks for available updates. To prevent this you can use the following setting.

config.vm.box_check_update = false

If you need to, you can enable port forwarding between your host and guest system. The following setting will let you use port 8080 on your host system to access port 80 on your guest system.

config.vm.network "forwarded_port", guest: 80, host: 8080

If you want to restrict the access through the portforwarding you can do this by adding the host_ip. The following will ony allow access from the IP 127.0.0.1 which is your host system (localhost).

config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

Another way to access your machine is to give it a static IP address. This will allow host only access, like the setting before,

config.vm.network "private_network", ip: "192.168.33.10"

This way you can use the IP address or you can make an entry in the /etc/hosts of your system to use a chosen domain name.

Now let's talk about shared folders. Vagrant enables you to share folders between your host and guest system. By default the project folder is available through /vagrant on your guest system. This does the trick most of the time, but sometimes you want to share more then just the project folder with your guest system. With the following setting you can do so.

config.vm.synced_folder "../data", "/vagrant_data"

The first argument is the folder on your host system, the second one is the folder on your guest system.

The next section of your projects Vagrantfile is the provider specific configuration. We heard that a fiew times in this article, provider, but what does this mean? The provider is the software that enables you to setup a virtual machine in the first place. In our examples this will always be Virtual Box.

config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    vb.gui = true

    # Customize the amount of memory on the VM:
    vb.memory = "1024"
end

This section is usually commented out, but you are free to change that. If vb.gui is set to true, vagrant will show you a window, with a terminal. This is useful when you have to debug your boot process. The vb.memory setting can be used to increase or decrease the amount of memory you want to invest into your virtual machine.

Last but not least the provisioning section. This is the place where you can eather enter terminal commands directrly or you can refer to a dedicated provision script that holds the logic to setup your environment.

config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y apache2
SHELL

# or

config.vm.provision :shell, :path => "setup_script.sh"

Provisioning means installing and setting up your guest system so it's taylor made for your needs. In this example we just update the package list and install Apache.

And thats it! We have gone through all major elements of a vagrant configuration.

Conclusion

We have seen a lot in this article and you won't need everything, everytime you setup a vagrant environment, but now that you have already heard all of the important gears of your setup, you know where to look if something doesn't match up with your needs.

So now go ahead and setup development and test environments as you need them. You now can forget about the risk of testing something on your operating system in use.

In the next article I am going to cover the basics of provisioning. If you don't want to miss out on that you can follow me on twitter.

PS: I never thought I would write Vagrantfile so often when I started writing this 😅