Introduction

Vagrant is a well-known tool used by many developers to help set up and configure their development environments. Vagrant makes it incredibly easy to set up and interact with virtual machines, it essentially tackles the “it works on my machine” issue.

In this guide we will be provisioning (setting up) Vagrant to handle a Laravel web application. Using a simple shell script we will instruct Vagrant to install and configure a database and fresh Laravel installation.

REQUIREMENTS

There are a few things we need to get
started;

  • Virtual Machine installed
  • Vagrant installed
  • Access to the Mac or Linux
    terminal / command line

Some recommendations (note: these are not
required);

  • Fast download speed
  • Knowledge of the Linux terminal

If you have the requirements listed above
then let’s proceed.

Getting Started

Let’s first check that we do have our
requirements installed. Open a terminal and run the following command;

virtualbox

This should open the GUI for VirtualBox, if this opens then you have VirtualBox installed. Let’s check its version to make sure it is up to date and will work with Vagrant. Look for the system tray, you should see the VirtualBox menu which is a dropdown, click on that and then click the “About VirtualBox” item.

You should then see a new window open which has the version number. You can see on the screenshot below that my version is “5.0.2 r108824”;

user_55169_581aecbcd13f6.png


Alternatively, you can also check the version from your terminal by typing the command:

vboxmanage --version

We are looking for version 5+. In my case we are safe to proceed. Let’s now check that we have Vagrant installed and its version. To do this, open a terminal and type the following command;

vagrant -v

You should see the version number returned in your terminal, as an example;

user_55169_581aed02e0dfc.png


You can see in the screenshot that its version number “1.8.1”, we are ideally aiming for 1.8+ so in this case we can proceed.

Choosing our base box

Vagrant uses “boxes”, these are similar to
image files (.iso). We will be using the official Ubuntu Trusty Tahr 14.04 box.

Configuring our Vagrantfile

We can now configure our Vagrantfile which will be set up to handle the shell provisioning and run the Ubuntu 14.04 box.

Let’s create a new folder for this project and call it “vagrant-laravel”. We can create this and move our terminal to that folder by using the following command;

mkdir vagrant-laravel && cd vagrant-laravel

Our terminal should now be located in the newly created folder. To generate the Vagrantfile we need to run the “vagrant init –minimal” command, we use the ‘–minimal’ flag so that we don’t get lots of extra generated content such as comments. You should now see the following message in your terminal;

user_55169_581aed4d23d0d.png


Let’s edit the Vagrantfile, I’ll be using the nano editor with the following command “sudo nano Vagrantfile”. Let’s look at the final version of our Vagrantfile and then break it down;


Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.synced_folder "app/", "/var/www/html/latest", :owner => "vagrant", :group => "www-data", :mount_option => ["dmode=775", "fmode=644"]
config.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
config.vm.provision "shell", path: "provision.sh"
end


Run the “ls” command and you should now see the Vagrantfile within your directory;

user_55169_581aed9171611.png


To edit the Vagrantfile I will by using the nano text editor;

sudo nano Vagrantfile

When you first open the Vagrantfile, there is already a lot of default configuration set and comments. Here are the main lines we will be focusing on;

  • config.vm.box
  • config.vm.network
  • config.vm.synced_folder
  • config.vm.provision

config.vm.box

Let’s set this file to Ubuntu box. Find this line in the Vagrantfile and change it to this;

config.vm.box = “ubuntu/trusty64”

config.vm.network

We’ll set the network type to private which means that only you (the host) can connect to the virtual machine and set the IP address;

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

config.vm.synced_folder

To make development easier, we will set a synced folder which will allow us to edit the files on our host machine and be shared with the virtual machine;

config.vm.synced_folder "app/", "/var/www/html/latest", :owner => "vagrant", :group => "www-data", :mount_option => ["dmode=775", "fmode=644"]

We’ve set the host folder to be “app” and to be shared with the “/var/www/html/latest” folder on the virtual machine. We will add the “vagrant” user to the “www-data” group. We will also set the folders permissions. This will sync everything in “app” to the specified directory, which means we can edit our app code locally and changes will be reflected automatically in the virtual machine.

config.vm.provision
Finally, we need to set the provision type and file to be used;


config.vm.provision "shell", path: "provision.sh"

We are using the “shell” provision type and the “provision.sh” file.

Provisioning with Vagrant

Let’s create our shell script by running the following command;

touch provision.sh

We can now open up that file using our text editor or IDE of choice or running the following command;

nano provision.sh

Now that we are ready to go, we need to think of this file as a recipe book. We will be writing a list of instructions that Vagrant must follow when setting up our virtual machine.

provision.sh

The first line of our provision.sh file will be the bash indicator;

#!/bin/bash

We can also echo out some text so we know
the status of our script. The second line of our file can be a ‘status’ line;

echo “Starting provision…"

That text will be outputted onto the screen when Vagrant starts to provision the virtual machine so we will know when it starts the provisioning stage.

Updating

First things first, let’s update our virtual machine so that all packages are up to date. You can enter this as a new line in our provision.sh file;

echo “Updating system...”
sudo apt-get update

Next we can install composer to handle all of our PHP dependencies. Add these next lines into your file;

echo "Installing essentials..."

sudo apt-get install -y zip unzip python-software-properties curl git

MySQL Database

Let’s install and configure the MySQL database;

echo "Installing and configuring MySQL database..."
debconf-set-selections <<< "mysql-server mysql-server/root_password password secret"
debconf-set-selections <<< "mysql-server mysql-server/root_password_again password secret"
apt-get install -y mysql-server mysql-client


We have pre-set the root password to use ‘secret’ so that the script can log in to set up our users and tables. You can see the MySQL-specific commands below;


mysql -u root -psecret -e "CREATE DATABASE homestead;"
mysql -u root -psecret -e "CREATE USER 'homestead'@'localhost' IDENTIFIED BY 'secret';"
mysql -u root -psecret -e "GRANT ALL PRIVILEGES ON homestead.* TO 'homestead'@'localhost';"
mysql -u root -psecret -e "FLUSH PRIVILEGES;"

Apache Web server

With our database ready to go, let’s install a web server. We will be using Apache, so let’s add the following lines;


echo "Installing Apache web server..."
sudo apt-get install -y apache2

PHP 5

With Apache installed, we can now install and configure PHP 5, we will also be installing some PHP components such as the MySQL client;


echo "Installing PHP5 and components..."
sudo apt-get install -y php5 libapache2-mod-php5 php5-mcrypt php5-curl php5-mysql php5-cli php5-json php5-mcrypt

Let’s enable the mcrypt PHP and Apache’s mod_rewrite component;


sudo php5enmod mcrypt
sudo a2enmod rewrite

Mcrypt is used for password generation and encryption by Laravel. The mod_rewrite component is used by Apache so that you can generate your own seo-friendly urls.

At this point Apache is not configured to use our Laravel application. Apache uses virtual hosts to handle multiple sites / domains on a single server. Let’s rewrite the default Apache config file with our own custom virtual host;


VHOST=$(cat <<EOF

<VirtualHost *:80>
DocumentRoot
"/var/www/html/latest/public"
<Directory
"/var/www/html/latest/public">
Options Indexes FollowSymLinks
MultiViews
AllowOverride All
Require all granted
</Directory>

</VirtualHost>

EOF)


echo "${VHOST}" > /etc/apache2/sites-available/000-default.conf

We’ve told Apache to look in the ‘/var/www/html/latest/public’ directory for our Laravel application code. We can now restart Apache so that it will now use the new configuration file;


sudo service apache2 restart

Composer

We have now configured our web server, so let’s install Laravel. Before we can install and configure Laravel, we need to set up composer. Composer is a PHP dependency manager. Composer is a great tool to have as a PHP developer and we will be using it to install Laravel and its dependencies;


echo "Installing and configuring composer..."
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer self-update --update-keys

We can now instruct our script to install Laravel. In this block we will also be creating the application folder and setting the permissions;


echo "Installing and configuring Laravel..."
mkdir /var/www/html/latest
composer create-project --prefer-dist laravel/laravel /var/www/html/latest "5.2.*"
sudo chmod -R 777 /var/www/html/latest
sudo chmod -R 777 /var/www/html/latest/storage

Congratulations! Once our provision script has gotten this far we will have successfully installed and configured our database (MySQL), our web server (Apache) and our web application code (Laravel). We have also added some important components and tools. Let’s finish off our script with the following line;


echo "Finished provisioning"


That’s the provision script finished and ready to go!

Running Vagrant

Let’s get the virtual machine up and running! We can do this by running the following command;

vagrant up

Vagrant will now start, read and set the configuration in our Vagrantfile and then run the provision.sh script. This process can take a while depending on your internet download speed and your hardware. When the process has completed, open up your web browser and visit the following IP address;

192.168.33.10

You should now see the Laravel 5 landing page!

user_55169_581aedc3d4467.png

You can now ssh into the Vagrant machine by running the following command;

vagrant ssh

From there you can run commands or make configuration changes. Congratulations, you have successfully configured and provisioned a Laravel web application with Vagrant, and you now have a repeatable process to launch more of these environments on completely different machines.

Troubleshooting

While writing this guide I came across a few quirks and issues. To avoid these, please make sure you have used these commands and configurations;

To stop the virtual machine
from running out of memory we need to set the minimum RAM to 1GB. We can set this in the Vagrantfile using the ‘vb.memory = 1024’ line.

You may run into a ‘zlib_decode()’ error with composer. This appears to be a security related issue, we can amend this by adding the following line into our provision.sh script: composer self-update –update-keys

If you run the vagrant up command, visit the IP address and get a HTTP 500 error, this will most probably be down to a permissions issue with Laravel’s storage folder. You can fix this by running the following command on the host machine (not in the Vagrant machine): sudo chmod -R 777 app/storage/

Sources / Resources

Vagrant websitehttps://www.vagrantup.com/

Laravel websitehttps://laravel.com/

Bash scripting cheat sheethttp://johnstowers.co.nz/pages/bash-cheat-sheet.html

Comments are disabled for this guide.