DEV Community

Andrew Welch
Andrew Welch

Posted on • Originally published at nystudio107.com on

1

Local Development with Vagrant / Homestead

Local Development with Vagrant / Homestead

A local devel­op­ment envi­ron­ment with Vagrant/​Homestead allows you to work on projects more safe­ly and effectively

Andrew Welch / nystudio107

Homestead Prairie Schooner

Home­stead is a pro­vi­sion­ing tool which sets up a local devel­op­ment envi­ron­ment that allows you to work on web­dev projects with­out fear. You get a mod­ern stack with every­thing you need for devel­op­ment, includ­ing an array of fan­tas­tic debug­ging tools.

We’re going to talk about why I use Home­stead for local devel­op­ment, but before we get into the nuts and bolts, let’s talk about why we use a local devel­op­ment envi­ron­ment to begin with.

N.B.: Although Craft CMS is ref­er­enced in this arti­cle, Home­stead works well for any kind of web devel­op­ment with any kind of CMS or dev stack (Lar­avel, Node­JS, whatevs).

                            You don’t work on a car’s engine while it’s run­ning, bar­rel­ing down the high­way at <span>100</span>km/​h
Enter fullscreen mode Exit fullscreen mode

In the bad old days, web devel­op­ment was done com­man­do, edit­ing .html files direct­ly on the serv­er. Then peo­ple start­ed real­iz­ing this was a bad idea, and files were edit­ed local­ly, and then copied down to the serv­er using an FTP app after some rudi­men­ta­ry testing.

The prob­lem is that mod­ern web devel­op­ment isn’t just edit­ing markup any­more. Mod­ern web devel­op­ment is on a col­li­sion course with soft­ware engi­neer­ing & infor­ma­tion archi­tec­ture. Some would argue — I think quite right­ly — that we’re already there.

Car Servicing Engine

That means we have to be seri­ous about our tool­ing. We need to have a way to design, devel­op, and debug our projects using mod­ern tools, in a way that does­n’t inter­fere with the pub­lic-fac­ing website.

The Mul­ti-Envi­ron­ment Con­fig for Craft CMS arti­cle talks more in-depth about how to set up Craft CMS for this type of set­up where you have local devel­op­ment, staging, and live pro­duc­tion environments.

If you’re not using some kind of local devel­op­ment envi­ron­ment, you will find it increas­ing­ly dif­fi­cult to stay up to speed. So let’s do it.

Why Vagrant/​Homestead?

There are as many ways to set up a local devel­op­ment envi­ron­ment as there are to skin a cat. The rea­son I’m par­tial to using Home­stead to set up my local devel­op­ment envi­ron­ment is that it cre­ates an entire­ly sep­a­rate vir­tu­al machine (VM) inside of your computer.

This has sev­er­al advantages:

  • You can install what­ev­er you want in your Home­stead VM with­out affect­ing your actu­al computer
  • You can eas­i­ly cre­ate and destroy as many VMs as you want, so an ​“oops” moment means min­utes, not hours
  • You get a real™ Lin­ux box that mir­rors your pro­duc­tion serv­er as close­ly as possible
  • You get all of the tools you need pre-installed, with­out hav­ing to add them in piecemeal

Hav­ing some­thing that close­ly mir­rors a pro­duc­tion envi­ron­ment means few­er unex­pect­ed sur­pris­es when you deploy to pro­duc­tion, and it means you spend less time on the ​“meta-work” of get­ting your devel­op­ment envi­ron­ment working.

The fact that you can cre­ate a pre-pro­vi­sioned VM quick­ly and eas­i­ly means that you can devel­op with­out fear. If you roy­al­ly screw up your devel­op­ment envi­ron­ment, no big deal, you just spin up anoth­er one.

Here’s what it looks like:

Homestead Vagrant Virtualbox

Home­stead is a Vagrant box (along with some set­up & pro­vi­sion­ing scripts). Vagrant is pro­vi­sion­ing soft­ware that uses a pre­con­fig­ured ​“box” to set up a Vir­tu­al Machine from a provider. The ​“provider” is what actu­al­ly runs the VM, and can be either Vir­tu­al­Box (which is free), VMware (which is not free), or Par­al­lels (which is also not free).

I’m going to assume that you’re cheap like me, and you’re going to use Vir­tu­al­Box, because it’s free. But any of the three will do, and in fact, VMware offers sig­nif­i­cant­ly bet­ter per­for­mance than the free Vir­tu­al­Box, so you might con­sid­er giv­ing it a go.

                            So Home­stead is the recipe, Vagrant is the chef, and Vir­tu­al­Box is the wait­er that serves you up the scrump­tious dish.
Enter fullscreen mode Exit fullscreen mode

All of this runs as a vir­tu­al machine (VM) inside of your com­put­er. Noth­ing that is in this VM can hurt your actu­al com­put­er, it’s com­plete­ly sep­a­rate and insulated.

Russian Matryoshka Doll

You have your own lit­tle serv­er inside your com­put­er, and com­bined with a set­up as described in the Data­base & Asset Sync­ing Between Envi­ron­ments in Craft CMS arti­cle, you have a mobile envi­ron­ment that you can use any­where. Even with­out Inter­net access.

What’s more, if you work with oth­er peo­ple, the deter­min­is­tic way in which Home­stead pro­vi­sions your VM means you can ensure that they also have the exact same local devel­op­ment envi­ron­ment that you do.

Con­sis­ten­cy in tool­ing amongst your team means less fric­tion, and few­er problems.

Becom­ing a Homesteader

So enough talk! Let’s get a Home­stead envi­ron­ment. If you pre­fer video instruc­tions, check out the Set­up Craft CMS on Vagrant Home­stead YouTube video.

First, you’ll need to down­load and install:

Both of them come with native installers for Mac, Win­dows, and Lin­ux. You don’t need to do any kind of set­up for either of them, just install them. Then we need to add the laravel/homestead box to Vagrant via the following:


vagrant box add laravel/homestead

Enter fullscreen mode Exit fullscreen mode

Next up we’ll need to install Home­stead by cloning the repo:


git clone https://github.com/laravel/homestead.git Homestead

Enter fullscreen mode Exit fullscreen mode

…and check­ing out the desired ver­sion (v5.1.0 is the lat­est as of this writing):


cd Homestead
git checkout v5.1.0

Enter fullscreen mode Exit fullscreen mode

Tan­gent: A word about ver­sions. As we men­tioned ear­li­er, Home­stead comes in two parts, the Home­stead Vagrant box, and then the scripts that com­pose Home­stead itself. There’s a sep­a­rate ver­sion num­ber for each. As of this writ­ing, the lat­est ver­sion of the Home­stead Vagrant box is 2.0.0, and the lat­est ver­sion of Home­stead itself is 5.1.0. Just some­thing to keep in mind when updat­ing Home­stead.

Final­ly, the first time we install Home­stead, we also need to ini­tial­ize it from the Homestead direc­to­ry. On Mac/​Linux, we do:


bash init.sh

Enter fullscreen mode Exit fullscreen mode

…and on Win­dows, we do:


init.bat

Enter fullscreen mode Exit fullscreen mode

This cre­ates a Homestead.yaml file in the Homestead/ direc­to­ry. This is the file we’ll be using to con­fig­ure our Home­stead set­up. Here’s a sim­ple exam­ple (edit your Homestead.yaml file to suit your own needs, using this as a guide):


---
ip: "192.168.10.10"
memory: 2048
cpus: 1
provider: virtualbox
mariadb: true

authorize: ~/.ssh/id_rsa.pub

keys:
    - ~/.ssh/id_rsa

folders:
    - map: /Users/andrew/webdev/sites
      to: /home/vagrant/sites
      type: nfs

sites:
    - map: nystudio107.dev
      to: /home/vagrant/sites/nystudio107/public

    - map: craft3.dev
      to: /home/vagrant/sites/craft3/public

databases:
    - nystudio
    - craft3

variables:
    - key: APP_ENV
      value: local

# blackfire:
# - id: foo
# token: bar
# client-id: foo
# client-token: bar

# ports:
# - send: 93000
# to: 9300
# - send: 7777
# to: 777
# protocol: udp

Enter fullscreen mode Exit fullscreen mode

What this will do is pro­vi­sion our VM to have 2048mb of mem­o­ry, and use 1 vir­tu­al CPU. A decent rule of thumb is to use 1/​8th of your com­put­er’s RAM to ded­i­cate to the VM.

We’re using mariadb instead of mysql because it does­n’t have the annoy­ing issue with Craft CMS 2.x that MySQL 5.7 does. Mari­aDB does­n’t whine about Warn­ing: Using a pass­word on the com­mand line inter­face can be inse­cure, and it’s a more active codebase.

Don’t wor­ry, Mari­aDB a 100% drop-in replace­ment for MySQL, and it’s 100% com­pat­i­ble (it’s a fork of the same code­base, by the orig­i­nal author of MySQL). If for some rea­son you real­ly don’t want to use Mari­aDB, just omit this line, and it’ll use MySQL by default.

folders allows you to map direc­to­ries from your com­put­er to your VM. This lets you use native edi­tors like Sub­lime or Php­Storm to edit your code, while also allow­ing the VM to access the files as well.

Remem­ber, the VM is effec­tive­ly a sep­a­rate com­put­er, so this direc­to­ry map­ping is a bridge between the two. So you can edit the same files either on your com­put­er, or in the VM. A key set­ting is to use nfs as the type because its a more per­for­mant way to do this file sharing/​syncing.

sites lets you set up map­pings from a domain name to a direc­to­ry on the VM where the web­site lives. You can add as many as you want in the same VM.

databases lets you tell Home­stead to cre­ate the mysql data­bas­es for you. Again, you can have as many data­bas­es as you like in the same VM.

Then we need to tell our com­put­er where to find these sites by them to our hosts file, which is at /etc/hosts on Mac/​Linux, and at C:\Windows\System32\drivers\etc\hosts on Windows:


192.168.10.10 nystudio107.dev
192.168.10.10 craft3.dev

Enter fullscreen mode Exit fullscreen mode

The eas­i­est way to edit the hosts file on a Mac is just doing: sudo nano /etc/hosts which will bring up a very sim­ple edi­tor. Since this is a sys­tem file, you’ll need to enter your admin pass­word to edit it.

On Win­dows, you sim­i­lar­ly need to edit the hosts file with admin rights. For exam­ple, run Notepad with right click > run as admin and then edit the hosts file.

If you get tired of edit­ing your hosts file man­u­al­ly, you can always use the host­sup­dater Vagrant plu­g­in to do it for you.

Final­ly, let’s do a lit­tle bit of set­up that isn’t strict­ly nec­es­sary, but it’ll make your dai­ly life with Home­stead a lot nicer.

Home­stead is a spe­cif­ic type of Vagrant box; so we could use the stan­dard Vagrant com­mands when work­ing with our Home­stead box. But it’s much more con­ve­nient to set up a com­mand that works specif­i­cal­ly with our Home­stead environment.

On the Mac do this to edit your Bash pro­file: nano ~/.bash_profile and add this to the end of it:


function homestead() {
    ( cd ~/Homestead && vagrant $* )
}

Enter fullscreen mode Exit fullscreen mode

Make sure to tweak the ~/Homestead path in the func­tion to the loca­tion of your actu­al Home­stead installation.

While you’re in there, if you want the com­mand line prompt to tell you what git repo & branch you’re cur­rent­ly in, add this to the end of your ~/.bash_profile too:


parse_git_branch() {
     git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1="\u@\h \[\033[32m\]\w\[\033[33m\]\$(parse_git_branch)\[\033[00m\] $ "

Enter fullscreen mode Exit fullscreen mode

You’ll have to close your Ter­mi­nal win­dow and re-open it for the changes to your ~/.bash_profile to take effect, so do that now.

On Win­dows, cre­ate a homestead.bat batch file any­where on your machine with the fol­low­ing contents:


@echo off

set cwd=%cd%
set homesteadVagrant=C:\Homestead

cd /d %homesteadVagrant% && vagrant %*
cd /d %cwd%

set cwd=
set homesteadVagrant=

Enter fullscreen mode Exit fullscreen mode

Make sure to tweak the exam­ple C:\Homestead path in the script to the actu­al loca­tion of your Home­stead instal­la­tion. After cre­at­ing the file, add the file loca­tion to your PATH

There’s plen­ty more you can do with Home­stead, includ­ing installing it via Com­pos­er on a per-project basis, and more. Check out the Home­stead Doc­u­men­ta­tion for fur­ther details.

Ladies & Gen­tle­men, start your engines

Phew! That was a lot of set­up work, but thank­ful­ly we only have to do it once. Let’s fire up our VM! Type:


homestead up

Enter fullscreen mode Exit fullscreen mode

What actu­al­ly hap­pens is the homestead com­mand changes the cur­rent work­ing to where we installed Home­stead, and then maps the rest of the argu­ments to vagrant because of the com­mand we set up earlier.

The way Vagrant works is that if there is a Vagrantfile in the cur­rent work­ing direc­to­ry when you exe­cute the vagrant com­mand, it assumes you want to work with that VM, and it uses it.

So set­ting up that homestead com­mand saved us from hav­ing to switch to the Homestead/ direc­to­ry (or know the Vagrant machine ID) each time we want to do some­thing with it. That’s all.

The first time you do homestead up it’ll take a bit of time, and you will have to enter your admin pass­word to allow the nfs direc­to­ry map­ping to work.

Smooth Sailing

After that, though, it’s smooth sail­ing. I gen­er­al­ly just leave my VM run­ning all the time, since I use it every day, and it has very lit­tle CPU/​battery impact when it’s just idling in the background.

I set it up so that every project I work on lives in the same VM. Spin­ning up a new project just involves adding the appro­pri­ate lines to the sites and databases in the Homestead.yaml file, adding the domain name to the hosts file, and then pro­vi­sion­ing the VM by doing:


homestead reload --provision

Enter fullscreen mode Exit fullscreen mode

Don’t wor­ry, nei­ther homestead reload nor homestead reload --provision will affect your files or data­bas­es stored on your VM.

All of the data­bas­es that Home­stead cre­ates for you have the fol­low­ing credentials:

  • User: homestead
  • Pass­word: secret

So you’ll want to enter that into your mul­ti-envi­ron­ment con­fig so that you can access your data­base. By far the eas­i­est way to pull your pro­duc­tion data­base down is to do so via Craft-Scripts, as dis­cussed in the Data­base & Asset Sync­ing Between Envi­ron­ments in Craft CMS article.

If you want to access your web­site that’s run­ning from your VM, just put the domain name in your web brows­er, and away you go, e.g.: nystudio107.dev

The web­sites that you spec­i­fied via sites in the Homestead.yaml file result in the cor­re­spond­ing Nginx .conf files for the vir­tu­al hosts in /etc/nginx/sites-available (and a sym­link in /etc/nginx/sites-enabled). You can edit them as you see fit, but they will be reset if you do a homestead up --provision or homestead reload --provision.

If you want to ssh into your VM, just type:


homestead ssh

Enter fullscreen mode Exit fullscreen mode

…and you’re in! No pass­words or any­thing. It’s a real Lin­ux box, run­ning Ubun­tu 16.04 (at the time of this writ­ing), so you can install what­ev­er you like.

One thing you’re going to need to install if you’re run­ning Craft 2.x is the mycrypt pack­age for PHP. mycrypt is dep­re­cat­ed as of PHP 7.1 (though it still works), and Craft 3.x does­n’t use it, but we need this lega­cy pack­age for Craft 2.x. So let’s install it.

While we’re at it, let’s install Imagemag­ick as well, for doing our image trans­forms and such. Home­stead comes with GD installed by default, but we can eas­i­ly add Imagemag­ick too. From inside of your VM, sim­ply do:


sudo apt-get install php7.1-mcrypt php-imagick

Enter fullscreen mode Exit fullscreen mode

Impor­tant: If, when installing things, it ever asks you whether you want to replace an exist­ing .conf file, always say No (or just hit the Return key, which defaults to the safest option).

You can install oth­er stuff, too!

Let’s say you want to play around with using .webp images as per the Cre­at­ing Opti­mized Images in Craft CMS arti­cle; just install cwebp on your VM via:


sudo apt-get install webp

Enter fullscreen mode Exit fullscreen mode

…and away you go. If you want to edit your files to, you know, actu­al­ly do some devel­op­ment work, just do that how­ev­er you nor­mal­ly would.

The files are auto­mat­i­cal­ly synced between your com­put­er and your VM. Edit them in Sub­lime or Php­Storm on your com­put­er. Edit them in nano or vim on your VM. Home­stead does­n’t care.

If you do plan to use Php­Storm for local devel­op­ment, check out the Using Php­Storm with Vagrant / Home­stead arti­cle for how to set that up.

Home­stead Like a Pro

Now that we have Home­stead up and run­ning, here are a few tips I’ve found that can make it real­ly sing. You don’t have to do any of these things, they are com­plete­ly option­al, but some will make your life on the trail much easier.

American Gothic Homestead

We’re already using nfs for our direc­to­ry map­ping, which is great, because oth­er­wise Vir­tu­al­Box can be pret­ty slow at sync­ing files. There is, how­ev­er, one annoy­ing side-effect, which is that all of your shared files will look like this:


vagrant@homestead /htdocs/nystudio107 (develop) $ ls -al gulpfile.js
-rw-r--r-- 1 501 dialout 11269 Feb 15 04:51 gulpfile.js

Enter fullscreen mode Exit fullscreen mode

What’s going on here is that it’s using the UID and GID from your com­put­er in the VM; and it has dif­fer­ent users and groups than your com­put­er does. If you’re unfa­mil­iar with Unix users, groups, and per­mis­sions, check out the Hard­en­ing Craft CMS Per­mis­sions arti­cle for a primer.

So in this case, there’s no user with the UID of 501 in the VM, and the staff GID on my com­put­er hap­pens to be the GID of the dialout user on my VM.

While this is mild­ly annoy­ing to look at, it can become a real prob­lem with per­mis­sions some­times. So let’s fix it. To do so, we’ll use the vagrant-bindfs Vagrant plu­g­in; just install it on your com­put­er via:


vagrant plugin install vagrant-bindfs

Enter fullscreen mode Exit fullscreen mode

Home­stead will auto­mat­i­cal­ly use this Vagrant plu­g­in if it is present, so there’s no need to alter your Vagrantfile. Then reload your VM con­fig with:


homestead reload

Enter fullscreen mode Exit fullscreen mode

…and all will be well with the universe:


vagrant@homestead /htdocs/nystudio107 (develop) $ ls -al gulpfile.js
-rw-r--r-- 1 vagrant vagrant 11269 Feb 15 04:51 gulpfile.js

Enter fullscreen mode Exit fullscreen mode

Next up, there’s a handy shell script in the Homestead/ fold­er called after.sh. This script is exe­cut­ed after Home­stead has fin­ished pro­vi­sion­ing the VM, so you can add what­ev­er you want to it, and it’ll be exe­cut­ed after a homestead up --provision or homestead reload --provision.

As a for-instance, I use cus­tomized ver­sions of the Nginx .conf files for my web­sites, set up via Nginx-Craft. These nor­mal­ly would get reset to their defaults after a homestead up --provision or homestead reload --provision. so we can stash the cus­tomized ver­sions in the setup/sites direc­to­ry inside the Homestead/ fold­er, and restore them via after.sh:


# -- Copy over customized nginx configs
# As per: https://laracasts.com/discuss/channels/requests/homestead-provision-deletes-custom-nginx-settings

# define your sites config directory located on your host machine
SITES=/home/vagrant/setup/sites/*

# copy every site file from /home/vagrant/setup/sites/ to your Nginx sites-available folder
yes | sudo cp -rf $SITES /etc/nginx/sites-available

# enable each site by creating a symbolic link to each file
for p in $SITES
do
    FILE=$(basename $p)
    sudo ln -s /etc/nginx/sites-available/$FILE /etc/nginx/sites-enabled/
done

# restart the nginx service
sudo service nginx restart

Enter fullscreen mode Exit fullscreen mode

We’ll also need to add an addi­tion­al direc­to­ry to our folders in Homestead.yaml map­ping too:


- map: /Users/andrew/Homestead/setup
      to: /home/vagrant/setup
      type: nfs

Enter fullscreen mode Exit fullscreen mode

Make sure you change the first path to point to your Homestead/setup directory.

Next, let’s make some tweaks to our nfs mounts to speed them up when deal­ing with lots of files (such as git repos, node_​modules fold­ers, etc.). Add this to the bot­tom of your Vagrant file:


# Speed up NFS as per: https://www.jverdeyen.be/vagrant/speedup-vagrant-nfs/
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    # …
    config.vm.synced_folder "/Users/andrew/webdev/sites", "/home/vagrant/sites", type: "nfs", mount_options: ['rw', 'vers=3', 'tcp', 'fsc' ,'actimeo=2']
end

Enter fullscreen mode Exit fullscreen mode

Change the paths to be what­ev­er you set your folders to be in your Homestead.yaml file. Note that the first direc­to­ry is the direc­to­ry on your com­put­er, the sec­ond direc­to­ry is the direc­to­ry in your VM. Then reload your VM with:


homestead reload

Enter fullscreen mode Exit fullscreen mode

One final tip relat­ed to per­for­mance, here are some tweaks you can make by adding this to the bot­tom of your Vagrantfile:


# As per https://www.mkwd.net/improve-vagrant-performance/
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    # …
    config.vm.provider "virtualbox" do |v|
        # change the network card hardware for better performance
        v.customize ["modifyvm", :id, "--nictype1", "virtio"]
        v.customize ["modifyvm", :id, "--nictype2", "virtio"]

        # enable IO APIC so that the virtual machine can make use of the additional cores
        v.customize ["modifyvm", :id, "--ioapic", "on"]
    end
end

# Speed up VirtualBox i/o as per: https://joeshaw.org/terrible-vagrant-virtualbox-performance-on-mac-os-x/
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    # …
    config.vm.provider "virtualbox" do |v|
        v.customize [
            "storagectl", :id,
            "--name", "SATA Controller",
            "--hostiocache", "on"
        ]
    end
end

Enter fullscreen mode Exit fullscreen mode

Then restart your VM with:


homestead reload

Enter fullscreen mode Exit fullscreen mode

So What’s the Bad News?

So what are the down­sides to using a Home­stead VM? If you’ve read this far, you’re aware that there’s some set­up work involved. But giv­en that this is a one-time thing, and it installs mod­ern ver­sions of every­thing you’ll need in one shot, I haven’t found this to be burdensome.

Pick an after­noon, get a cup of cof­fee, and spend a lit­tle upfront time mak­ing the rest of your work­ing life better.

Cup Of Coffee

The oth­er down­side to a VM is that it can be slow­er than if you use ​“native” local devel­op­ment envi­ron­ments such as Valet, Mamp, or what have you.

These ​“native” tools install the devel­op­ment envi­ron­ment on your com­put­er itself, so there’s no VM lay­er to go through. I’ve found that the con­ve­nience and func­tion­al­i­ty offered by an actu­al VM is worth it; not to men­tion the time saved by hav­ing it match your pro­duc­tion envi­ron­ment, and not hav­ing to tin­ker around with some odd­ball setup.

In gen­er­al, local devel­op­ment para­dox­i­cal­ly can often be slow­er than your pro­duc­tion serv­er regard­less of what tool you use. That’s because you’re run­ning things like XDe­bug, dev­Mode is on, templateCaching is off, and in gen­er­al things are set up for development/​debugging rather than performance.

Your mileage, of course, may vary. Use what­ev­er tool works; half of the bat­tle is just the fact that you’re using some­thing for local development.

Tool up. Be awesome.

Further Reading

If you want to be notified about new articles, follow nystudio107 on Twitter.

Copyright ©2020 nystudio107. Designed by nystudio107

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

Try REST API Generation for MS SQL Server.

DevOps for Private APIs. With DreamFactory API Generation, you get:

  • Auto-generated live APIs mapped from database schema
  • Interactive Swagger API documentation
  • Scripting engine to customize your API
  • Built-in role-based access control

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay