What is Vagrant for

Vagrant is a virtual machine manager. It makes easy for creating, running and monitoring of VM’s on your host machines. It’s an open source and cross-platform (for MacOS, Windows and Linux) software. Right now you can you can manage VMs for VMWare, VirtualBox ve AWS (Amazon Web Services). This means you can easily manage different kinds of VMs from one Vagrant configuration which is beautiful!

But what real benefits we can get from it? What are the examples from real life?

First of all, this could heavily increase of your development quality: Do you remember how much time did you spend for just running projects on your local computer for the first time?

Or you would be much older after doing all of these work for all of your environments like staging, test and production. Let’s say you need to setup and run your project on a new environment lets say: UAT. You will need to prepare all of the project’s dependencies manually. That can react to a one week period depending your project’s complexity and size.

But maybe the most beneficial part would be the ability to reproduce production errors and bugs on your development environment. Because it is so easy to run VMs with exactly the same configuration on any computer with Vagrant. Goodbye “can’t reproduce, runs on my machine” issues.

vagrant

Prerequisites

Vagrant needs a VM manager as a provider. I already told vagrant can use multiple VM managers but for this article I chose VirtualBox which is an open and free provider presented by default on Vagrant. To download VirtualBox: click here.

Note: Vagrant VM user is vagrant, and its password is vagrant too.

Vagrant setup

1. Download Vagrant from: http://www.vagrantup.com/downloads

Setup Box Path

Note: This is for MacOS and Linux only:

Vagrant uses this path to download VMs by default:

~/.vagrant.d/boxes

VMs could take up a lot of space so you might want to change its default path before installing any operating system. To change it just open .bash_profile on your favourite editor (you can use vi instead of nano)

Add this line:

export VAGRANT_HOME="/<TYPE PATH HERE>" New downloads will be under this directory.

Setup operating system

There are lots of Linux distributions provided from Hashi Corp’s Atlas but I chose Ubuntu which I’m already familiar and it is a LTE version! https://atlas.hashicorp.com/ubuntu/boxes/trusty64

Setup as told by the documentation:

init command will create a file named VagrantFile on the current path. vagrant up command will use information on this file.

up command will download and install OS specified on to that VM.

You can see and examine many useful commands with vagrant --help

Connecting to the Box

To see the list of the boxes we type vagrant box list command.

Now we need to use vagrant ssh, which will connect to the VM written in the VagrantFile.

My terminal connection is changed to the above which means I’m connected using ssh.

Installing Requirements

These requirements are totally for my node.js example application and will be changed by the project and development/running stack you use.

Lets do the Redis configuration: (you can use vi instead of nano) Our application uses redis with this configuration:

change the line with notify-keyspace-events to this:

After that restart redis:

Now download and install the application:

We’ll need to write all these commands to a file: provision.sh. Afterwards open and change the VagrantFile to this:

Exit from ssh with exit command and then type:

With this line Vagrant will close, reopen and make installments based on instruction you wrote on provision.sh file.

Vagrant synchronization

It might be hard for you to develop on Vagrant VMs especially with non-graphical terminals. If you’re not used to terminal apps like Vim or Emacs and you want to use your IDE and tools on your host machine, you can do this by enabling Vagrant’s synchronization mode. That could also be used for any data transfer.

I’ll be explaining usage of synchronization between Mac OSX host machine and VirtualBox ubuntu guest machine. A different combination would need something else and related information can be found on vagrant documentation about synced folders.

Lets change the VagrantFile:

• We added config.vm.synced_folder command.
• First parameter path, is on the host machine.
• Second parameter path, is on the guest machine

We can check the new options by

Now when we change a file using our favourite editor/IDE from our host machine within the specified path, it will automatically synchronized by given guest path.

Port Forwarding

Port forwarding means binding a port number used from guest machine to host machine’s any port to be able to use from there.

Now VM’s 3000 port could be used from our compter with 3000 port.

You can try the application running on guest, by entering this URL to your computer’s browser: http://localhost:3000. Bon appetit 🙂

Private Network

You can also communicate with your VMs from a private network defined by you. You should change the configuration as follow:

With this method, there is no need for port forwarding, instead localhost you can use this network’s IP address directly and test from here: http://192.168.1.20:3000.

By defining an IP for the guest OS, you can even use your DNS which can be used for clustering.

For VirtualBox use these commands (to make sure VM is closed type vagrant halt):

For local usages, you can set meaningful names on your computer’s hosts file. For Mac OSX change that file using this command (you can use vi instead of nano):

Add 192.168.1.20 nodeapp.com to the bottom of the file and save. After that we can reach to our node.js application from http://nodeapp.com:3000 from the host machine. Furthermore other VMs can reach to that if we made the same configuration on that VMs.

I’ll continue with nodeapp.com below examples.

These changes will cause problems on facebook login and socket processes. Facebook application settings should be changed to use nodeapp.com instead of localhost. These changes will be on config/commons.js on socket_host variable and on test.json file on callbackURL variable. Things to be done:

  1. We need to change application settings from http://developers.facebook.com I suggest you to use Test Apps to create a new application and change Site URL to http://nodeapp.com:3000/.  You need to change test.json with related configuration variables with new AppID and AppSecret given by facebook.
  2. On config/index.js there is a little issue that I didn’t notice before. We’ll change that to override common settings by the given one:
  3. On test.json add this to override commons.json:

Run Application as a Service

Until now, I explained what to be done to install and use our node.js application. Now I’ll explain managing and monitoring it by using a tool named PM2 which is very popular in node.js community. We’ll use it to restart our application on application *crash*es and I also show you how to add our application to the OS as a service of Ubuntu/Linux which automates running application on OS restarts.

Install PM2:

Run this command to install PM2’s command completion tool to help us write many complex commands:

You can close and reopen your terminal window for completion to work or run this command:

NOTE: PM2 has actually lots of handy features for us, but that would be a topic for another article so I’ll pass for now. If you’d like you can search on your own from: http://pm2.keymetrics.io/docs/usage/pm2-doc-single-page/

Before going through service options, we need to make changes on grunt side. Until now our application ran on dev mode. I decided to use test mode for VM. We are still going to use grunt for running redis and mongo in the same instance but we don’t use watch of grunt or nodemon, instead we’ll use PM2 for that features.

Spoiler: You can get the code ready for VM by typing git checkout bes but you’d still need to do some of these tasks:

  1. copy dev.json content to a file called test.json.
  2. Type service --status-all to check if redis and mongo services are active.
  3. Run and test application with NODE_ENV=test pm2 start app.js.
  4. If it runs without an error, kill it with pm2 kill
  5. Add a new file called startup.sh which will provide starting, stoping etc. of the service. Have a look on variables like NAME, PM2, USER, APP_HOME and change as your needs. For instance check your user name with whoami (which will be vagrant) or get the path of PM2 executable with which pm2
  6. Copy the file to the path of services with sudo cp startup.sh /etc/init.d/nodeapp.
  7. Give execute right to the file with sudo chmod a+x /etc/init.d/nodeapp
  8. Run the service with sudo service nodeapp start. You can sudo /etc/init.d/nodeapp start without using service.
  9. Check if application started with pm2 list.
  10. Stop the service with sudo service nodeapp stop. Check if no application is running with pm2 list and there is no node.js process with ps aux | grep node.
  11. If everything is OK, type this command to register service to start after VM started sudo update-rc.d nodeapp defaults.
    Note:If you encounter any issue trying these, proceed from basic to advanced. For instance first check startup.sh is working or not then check the service.
  12.  We also need to make changes to the provision.sh file:

That’s all for now. If you don’t feel familiar to all these Linux commands and such, there are tons of free sources for Linux from novice to advanced. If you encounter a problem you can’t solve, I’d like to help from the comments.

The next article will be about how to manage logging on different machines using Vagrant to help simulate it. Wait for it 🙂