Vagrant filesystem issues with npm

Issue

I have been encountering an issue with Vagrant machines and npm. Files within the file-system suddenly become read-only. In all cases, a synced directory, that contained a Git repository, was involved.

The following is a provisioning setup that enables me to encounter the issue with. Both files are located in the root of a node-oriented Git repository like the one found here.

Vagrantfile

# 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|
  # Use host's SSH keys
  config.ssh.forward_agent = true

  # Get current directory name (presumably, repo dirname)
  repo_dirname = File.basename(Dir.getwd)

  # Set US locale
  ENV['LC_ALL']="en_US.UTF-8"

  # Ensures virtualbox can create symlinks in shared folders
  config.vm.provider "virtualbox" do |vb|
    vb.customize ["setextradata", :id,
                  "VBoxInternal2/SharedFoldersEnableSymlinksCreate/vagrant", "1"]
  end

  # Forward usual dev port through to host machine
  config.vm.network :forwarded_port, guest: 3000, host: 3000
  # Also forward production port just in case
  config.vm.network :forwarded_port, guest: 80, host: 8080
  # Forward a folder for the repo so that code can be worked on from outside the
  # VM as usual
  config.vm.synced_folder ".", "/home/ubuntu/#{repo_dirname}", create: true
  
  config.vm.define "#{repo_dirname}-vm" do |repo_vm|
    repo_vm.vm.box = "ubuntu/xenial64"
    repo_vm.vm.host_name = "#{repo_dirname}-vm"
    repo_vm.vm.provision :shell do |sh|
      sh.path = "vagrant_provision.sh"
      sh.privileged = false
      sh.env = {
        REPO_DIR: repo_dirname
      }
    end
  end

end

vagrant_provision.sh

#!/usr/bin/env bash

function set_locale() {
    sudo locale-gen en.US
}

function get_builds() {
    sudo apt-get update &&
        sudo apt-get upgrade -y &&
        sudo apt-get install -y curl build-essential
}

function get_n_installer() {
    if [ -f n-install ]
    then
        echo "n installer already exists. Not downloading."
        return 0
    else
        echo "n installer not found. Downloading..."
        wget -L https://git.io/n-install
    fi
}

function install_n() {
    if [ -d "n" ]
    then
        echo "n install directory already exists. Not installing."
        return 0
    else
        echo "n install directory not found. Installing..."
        yes | bash n-install
    fi
}

function add_github_keys() {
    # Adds the github server key to known hosts
    ssh-keyscan github.com >> ~/.ssh/known_hosts &&
        return 0 || return 1
}

function add_n_to_path() {
    # Added by n-install, but ignored by vagrant
    export N_PREFIX="$HOME/n";
    [[ :$PATH: == *":$N_PREFIX/bin:"* ]] || PATH+=":$N_PREFIX/bin"
}

function get_repo() {
    if [ -d "$2" ]
    then
        echo "Destination directory $2 already exists. Deleting contents..."
        rm -rfv ./$2
    fi
    echo "Cloning $1 into $2..."
    git clone $1 $2
}

function install_npm_deps() {
    echo "Installing npm dependencies..."
    npm install
}

function rebuild_node_sass() {
    # Needed because of https://github.com/sass/node-sass/issues/1579
    npm rebuild node-sass
}

# . ~/.bashrc &&
set_locale &&
    add_github_keys &&
    get_builds &&
    get_n_installer &&
    install_n &&
    add_n_to_path &&
    cd $REPO_DIR &&
    install_npm_deps &&
    rebuild_node_sass &&
    echo "Provisioned user is: $USER" &&
    echo "Frontend provisioned. To run, type 'vagrant ssh'."

The main step that seems to cause a problem is the execution of npm install by the unprivileged provisioner. Sometimes an archive unpacking error occurs, but other times, npm fails with ENOENT errors.

Upon logging in with vagrant ssh to finish the job, read-only filesystem errors appear. Despite this, there is plenty of space on the system (say, 7 out of 8GB remaining).

Read-only filesystem errors also appear when the webpack server is running under the same circumstances.

There are questions and tickets floating around that quote similar errors, but I haven’t seen any exploration into what the underlying mechanism is. What’s the deal?

Solution

I have been experiencing similar issues with Vagrant 1.8.7 and Virtualbox 5.1.10. I was able to fix the filesystem readonly problematic by reducing the number of cpu cores to 1:

config.vm.provider "virtualbox" do |v|
  v.cpus = 1
end

Build issues are still occuring for me (npm modules not being found, ENOENT, ELIFECYCLE,…) but at a lesser rate. Unfortunately I have not been able to locate the root cause of these errors.

In my setup npm is not writing into the shared directory. If the write location is the shared folder you can try a different syncing mechanism that gets around some limitations of the virtualbox shared folder implementation.

Answered By – nmn

Answer Checked By – Timothy Miller (AngularFixing Admin)

Leave a Reply

Your email address will not be published.