SJ cartoon avatar

Development Installing NodeJS in Vagrant on Windows

I’ve almost never come across issues with using Vagrant to emulate a Linux environment, except for one time I was installing NodeJS.

Node’s package manager (npm) makes heavy use of symlinks and that’s one area where Windows falls over. If you’re doing everything inside of the VM, this isn’t an issue, however if you’re using shared folders (e.g. with source control in the host environment), then the symlinks will cause the provisioning to fail.

I’ve attached a sample Vagrantfile which works around that problem by setting the configuration of Virtualbox to allow symlinks. The trick is that the command prompt used when calling ‘vagrant up’ needs to be elevated to administrator privileges.

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  # Every Vagrant virtual environment requires a box to build off of.
  config.vm.box = "ubuntu/trusty64"
  config.vm.network "forwarded_port", guest:80, host: 8080, auto_correct: true
  config.vm.provider "virtualbox" do |v|
    v.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"]
  end

  # Uncomment this if you want to link to a shared folder (e.g. if you are running source control and want to link it to Vagrant)
  config.vm.synced_folder "./sample-app", "/home/vagrant/sample-app", create: true, group: "vagrant", owner: "vagrant"

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

end

And below is the Bash provisioning script.

#!/bin/bash

echo "*******************************"
echo "Provisioning virtual machine..."
echo "*******************************"


echo "***********************"
echo "Updating apt sources..."
echo "***********************"
sudo apt-get -qq update


echo "***********************************"
echo "Install and re-link node and npm..."
echo "***********************************"
sudo apt-get -y -qq install build-essential nodejs npm redis-server
sudo npm install -g forever
sudo ln -s "$(which nodejs)" /usr/bin/node


echo "***********************************"
echo "Run npm install and then run app..."
echo "***********************************"
cd sample-app
sudo npm install
sudo forever start server.js


echo "*********************************"
echo "Success! Navigate to localhost..."
echo "*********************************"

I’ve created a BitBucket repo GitHub repo which includes a sample NodeJS app that I found here. As a quick note, the provisioning script also includes the installation of Redis, as that’s what the sample app requires - as well as a symlink between ‘node’ and ‘nodejs’ to eliminate any problems with npm.

So, to summarize, pull down my repo, open up an elevated (administrator) command prompt, call ‘vagrant up’, and navigate to localhost:8080 and you should see the running NodeJS app!

Note: There is an alternative way to solve this problem, which involves using npm with a no-symlinks flag, but I still found that to be buggy, so I haven’t included that solution.