Vagrant and load balancing

08 Jul 2019

Have you ever needed load balancing on your local dev environment? I have. And luckily for me it was much easier to create than I expected.

Long story short, I needed to check if web app I was working on can work on multiple web nodes. For this particular project I was using Vagrant as my server. My goal was to introduce load balancing into dev stack.

It turned out that it’s easier than I expected. There’s a whole section in Vagrant docs called “Multi-Machine”. After few experiments I was ready to test load balancing.

The whole process can be split into those steps:

  1. Define web and db servers.
  2. Create separate Ansible roles for load balancer, web and db servers (this step is optional. I use Ansible to provision my machines, you can use whatever you want).
  3. Provision VMs.
  4. Provision load balancer.

Main difference between default Vagrantfile and my configuration was a simple loop I used to iterate over list of web servers and additional configuration for a load balancer. This is how my Vagrantfile looks like.

# list of servers I need to create
hosts = {
  'web1' => '',
  'web2' => '',
  'web3' => '',
  'db1' => ''

Vagrant.configure(2) do |config| = "bento/centos-7.4"

  config.ssh.forward_x11 = true
  config.ssh.insert_key = false

  total_hosts = hosts.length

  # iterate over list of servers
  hosts.each_with_index do |(name, ip), index|

    config.vm.define name do |machine|
      machine.vm.hostname = "#{name}.local" :private_network, ip: ip

      # this could be done better, db servers don't need this
      machine.vm.synced_folder "/host/path/", "/vm/path/", mount_options: ["dmode=777,fmode=777"]

      # Ansible will be responsible for provisioning web and db servers. that's why I use one list for web and db servers
      machine.vm.provider "virtualbox" do |v|
        # VM configuration

      # with Ansible we don't need to provision each server separately. we can run it once for all machines
      if index == total_hosts - 1
        machine.vm.provision "ansible" do |ansible|
          # Ansible configuration

  # load balancing
  config.vm.define "load_balancer" do |lb|
    lb.vm.hostname = "web-site.local" :private_network, ip: ""
    lb.vm.provider "virtualbox" do |v|
      # VM configuration

    lb.vm.provision provisioner do |ansible|
      # Ansible configuration

For load balancing I have used nginx. Here’s the configuration.

upstream webnodes {
    server; # web1
    server; # web2
    server; # web3

server {
    listen 80;
    server_name web-site.local;

    location / {
        proxy_pass http://webnodes;

And that’s all. With this few simple steps I was able to load balance Vagrant machines.

Here are some useful links I used while I was building my configuration: