One Setup to Rule Them All: Vagrant + Laravel Mix + Browsersync

by Kelly Packer

We’ve traveled to the Misty Mountains and have returned with a pouch full of configs carefully wrapped in mallorn leaves. Together they create the one build process to rule them all.

A couple of recent changes to our internal development processes helped us on our quest for the one setup. The first was our switch to Laravel Mix from our home-grown set of Gulp tasks rolled into an npm package. (Read more about that in an upcoming blog post.) The second, was our broadened use of Vagrant. We’ve been using Vagrant on our application-type projects for a while, but we recently started using it everywhere.

TL;DR There are a few key pieces to the setup:

  • Vagrant Synced Folder Config Option - add to Vagrantfile synced folder options: ":nfs => true, :mount_options => ['actimeo=2']"
  • Use the Mix watch-poll npm Task - use --watch-poll not --watch
  • Mix + Browsersync Config - a few specifics in the Browserconfig to make it work with Vagrant

Vagrant Synced Folder Config Option

In the Vagrantfile on the synced_folder config line we added:

:nfs => true, :mount_options => ['actimeo=2']"

So the final line is this:

config.vm.synced_folder ".", "/var/www/#{vars['hostname']}", type: "nfs", :nfs => true, :mount_options => ['actimeo=2']

The "actimeo=2" option sets the absolute time for which file and directory entries are kept in the file-attribute cache after an update. In effect, this speeds the sync and allows for Browsersync to refresh the site in a timely manner.

Use the Mix watch-poll npm Task

We use the Mix 'watch-poll' task. We renamed the default Mix 'watch-poll' task to 'watch' and removed the former because it’s shorter and cuts down on the confusion of two watch tasks. In our scripts object in our package.json file:

  "scripts": {
    "watch": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",

The plain old --watch will not work with Vagrant. --watch-poll sets the task to periodically check for changes e.g. every 500ms (see Browsersync Config below).

The task should be run on the Vagrant box:

vagrant up
vagrant ssh
# in project folder, e.g. /var/www/
npm run watch

Mix + Browsersync Config

In our webpack.mix.js we setup some specific Browsersync config:

if (!mix.config.production) {
    // Vagrant box's hostname
    proxy: '',
    // list of compiled files in public or templates
    files: [
    // The Vagrant box's private ip
    host: '',
    port: 3000,
    open: false,
    https: {
      // allow Browsersync to access key: sudo chmod o+x /etc/ssl/private
      key: '/etc/ssl/private/',
      cert: '/etc/ssl/certs/',
    watchOptions: {
      usePolling: true,
      interval: 500,

With the watch task running, the site can be viewed with Browsersync at You will notice the Browersync notice in the top right of your browser if it’s working properly. Also notice it is using https, see below.

There are a couple of important important points on this config.

The hostname on the Vagrant box.

An array of files that will be checked for changes. Mix will run the build tasks when a file is changed. Browsersync will watch those files for changes and reload the browser. So this should be an array of compiled files and templates.

The Vagrant box’s private IP.

Everything needs to use HTTPS now. Even for local sites, the browser gives you guff about not using HTTPS. Our Vagrant boxes use their own self-signed certificates.

To make Browsersync to work with the key, we changed the permissions on the /etc/ssl/private directory so it’s open for "others" to traverse and see the files inside it. Alarm bells may be going off, but don't worry, this is just for local development.

sudo chmod o+x /etc/ssl/private

In summary, when we first use a project with Vagrant and Mix we run these commands:

vagrant up
vagrant ssh
# in project folder, e.g. /var/www/
npm install
npm run watch


Saying that this is the 'one' setup might be a *wee* bit of an overstatement. What about hot module reloading? What about x awesomeness that doesn't exist yet? Nothing ever stays the same with web development. Our process will continue to evolve with the changing landscape.

Posted in: Development

We can make it together.

Let's talk today

Recent write-ups