Good news, everyone!
Recently I made some experiments to setup a Rails 6 dev environment using Vagrant.
I started from rails/rails-dev-box and applied some changes.

VM Setup

These are the features of the Vagrant file that I’m using:

  • Ubuntu 18.04 LTS box;
  • ability to install different ruby versions;
  • project files (placed in ./project) kept in sync using rsync.

Vagrantfile (which I keep in ./_vagrant directory):

Vagrant.configure('2') do |config|      = 'ubuntu/bionic64' # 18.04 LTS
  config.vm.hostname = 'my-project' :forwarded_port, guest: 3000, host: 3000
  config.vm.provider 'virtualbox' do |vb|
    # vb.check_guest_additions = false
    vb.gui    = true
    vb.memory = ENV.fetch('RAILS_DEV_BOX_RAM', 4096).to_i   = 'my-project'
    vb.cpus   = ENV.fetch('RAILS_DEV_BOX_CPUS', 2).to_i
  config.vm.provision 'shell' do |sh|
    sh.env        = { 'RUBY_VERSION' => '2.7.2', 'SWAP_SIZE' => '2G' }
    sh.keep_color = true
    sh.path       = ''
    sh.privileged = false
  config.vm.synced_folder './project', '/project', type: 'rsync', rsync__exclude: ['.git/']

Dev Environment Setup:

Main features:

  • RVM setup + Ruby install;
  • chromedriver to run feature specs;
  • install NodeJS (14.x) using;

#!/usr/bin/env bash

# Suppress command output and exit on error
function check_result {
  echo "--- $1 ---"
  [email protected] > /dev/null
  test $result -eq 0 || \
    { echo "!!! error: $result"; exit $result; }

# Suppress installation steps output
function apt_install {
  echo "--- Installing $1 ---"
  sudo apt -y install "[email protected]" >/dev/null 2>&1

echo '~~~ Bootstrap script ~~~'

echo '--- Adding swap file ---'
sudo fallocate -l $SWAP_SIZE /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap defaults 0 0' | sudo tee -a /etc/fstab

# Prevents "Warning: apt-key output should not be parsed (stdout is not a terminal)".
curl -sS | sudo -E apt-key add -
echo "deb stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

check_result 'Updating package information' sudo apt-get -y update

apt_install 'development tools' build-essential autoconf libtool

echo '--- Setup RVM ---'
echo silent >> ~/.curlrc
check_result 'Add RVM key' gpg --keyserver hkp:// --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
\curl -sSL | check_result 'Installing RVM' bash -s stable

source $HOME/.rvm/scripts/rvm
check_result "Installing Ruby $RUBY_VERSION" rvm install $RUBY_VERSION

check_result 'Update Ruby gems' gem update --system -N
check_result 'Installing Bundler' gem install bundler -N

apt_install Git git
apt_install SQLite sqlite3 libsqlite3-dev
apt_install Redis redis-server
apt_install 'Nokogiri dependencies' libxml2 libxml2-dev libxslt1-dev
apt_install 'chromedriver' chromium-driver

# PostgreSQL setup
apt_install PostgreSQL postgresql postgresql-contrib libpq-dev
sudo -u postgres createuser --superuser vagrant
cat > /tmp/pg.conf <<- EOF
local   all             postgres                                trust
local   all             all                                     trust
local   replication     all                                     trust
host    all             all               trust
host    all             all             ::1/128                 trust
host    replication     all               trust
host    replication     all             ::1/128                 trust
sudo cp /tmp/pg.conf /etc/postgresql/10/main/pg_hba.conf
sudo systemctl restart postgresql

# NodeJS setup
curl -sL | check_result 'Update NodeJS sources' sudo bash -
apt_install 'NodeJS' nodejs yarn

# Setup locales
sudo update-locale LANG=en_US.UTF-8 LANGUAGE=en_US.UTF-8 LC_ALL=en_US.UTF-8

# Shell utils
cat >> $HOME/.bashrc <<- EOF
alias be="bundle exec"
export DB_HOST="localhost"
export REDIS_URL="redis://localhost:6379/0"
export CHROMEDRIVER_PATH="`which chromedriver`"
cd /project

echo '--- Project setup ---'
source $HOME/.bashrc
cd /project
check_result 'bundle install' bundle install
check_result 'yarn install' yarn install --check-files
check_result 'rails db:reset' bin/rails db:reset

echo '~~~ Ready! ~~~'


To setup MySQL in place of PostgreSQL:

debconf-set-selections <<< 'mysql-server mysql-server/root_password password root'
debconf-set-selections <<< 'mysql-server mysql-server/root_password_again password root'
install MySQL mysql-server libmysqlclient-dev libssl-dev
# Set the password in an environment variable to avoid the warning issued if set with `-p`.
MYSQL_PWD=root mysql -uroot <<SQL
CREATE USER 'rails'@'localhost';

To install ASDF in place of RVM:

git clone $HOME/.asdf --branch v0.8.0
. $HOME/.asdf/
asdf plugin-add ruby
asdf install ruby 2.7.2

Project Setup

The database configuration is pretty standard - project/config/database.yml:

default: &default
  adapter: postgresql
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

  <<: *default
  database: db_development

  <<: *default
  database: db_test

Selenium configuration for RSpec (for feature and system specs) - project/spec/support/selenium.rb:

Capybara.register_driver :selenium_chrome_headless do |app|
  Selenium::WebDriver::Chrome::Service.driver_path = ENV['CHROMEDRIVER_PATH'] if ENV['CHROMEDRIVER_PATH']
  capabilities =
    'goog:chromeOptions' => {
      'args': %w[disable-dev-shm-usage disable-gpu headless no-sandbox window-size=1600,1000]
  options = {
    browser: :chrome,
    desired_capabilities: capabilities,
  }, options)

RSpec.configure do |config|
  config.before(:each, type: :feature, js: true) do |_spec|
    Capybara.current_driver = :selenium_chrome_headless
    Capybara.javascript_driver = :selenium_chrome_headless

  config.before(:each, type: :system) do


  • Start the machine (and create the machine the first time): vagrant up
  • Enter in the machine: vagrant ssh
  • Start the server (then point the browser to localhost:3000): bin/rails s -b
  • Watch for changes (in another shell): vagrant rsync-auto
  • Stop the machine: vagrant halt
  • Destroy the machine (and delete the VM): vagrant destroy