Vagrant setup for The Ruby on Rails Tutorial Part 2

June - 2015

Basic notes for my setup of Vagrant. These are kinda all over the place but there might be something useful as a snippet.


This is a follow up to Vagrant setup for The Ruby on Rails Tutorial. It details the commands in the Vagrantfile I created for The Ruby on Rails Tutorial (3rd ed.). For the full file, check that post.


###Command:

config.vm.box = "ubuntu/trusty64" 

What it does:

Tells Vagrant to base the virtual machine off the 64-bit version of Ubuntu 14.04 LTS (Long Term Support). I use the LTS versions to avoid getting caught in upgrade-hell for as long as possible.


###Command:

config.vm.network "forwarded_port", guest: 3000, host: 3000

What it does:

Creates a connection between the host and virtual machines so that accessing http://localhost:3000/ on a browser on the host machine will show the Rails server running on the same port inside the virtual machine.


###Command:

config.vm.provision :shell, inline: <<-END_OF_COMMANDS

What it does:

Tells Vagrant to run the following set of commands between this and the line with just "END_OF_COMMANDS" on it in the shell on the virtual machine. This is done as the root user.


###Command:

echo 'LC_ALL="en_US.UTF-8"' >> /etc/environment

What it does:

Sets the locale to prevent this warning when logging in the first time:

    _____________________________________________________________________
    WARNING! Your environment specifies an invalid locale.
     This can affect your user experience significantly, including the
     ability to manage packages. You may install the locales by running:

       sudo apt-get install language-pack-utf-8
         or
       sudo locale-gen utf-8

    To see all available language packs, run:
       apt-cache search "^language-pack-[a-z][a-z]$"
    To disable this message for all users, run:
       sudo touch /var/lib/cloud/instance/locale-check.skip

###Commands:

apt-get update
apt-get -y upgrade

What they do:

Make sure that all the base software is up to date. Probably not strictly necessary, but it's a good habit to be in to make sure security patches are installed.


TKTKTKTK I think you can kill this one

###Command:

apt-get -y install g++

What it does:

TKTKTKTKT This should be the solution to the heroku gem not being able to install.


###Command:

apt-get -y install git

What it does:

Installs the Git version control software package.


###Command:

apt-get install zlib1g-dev

What it does:

Installs the development library for zlib. This is necessary because the version of Nokogiri used by Rails 4.2 compiles its own version of libxml. Without installing zlib1g-dev, Vagrant chokes when it tries to install Rails and produces this error:

    ==> default: Building native extensions.  This could take a while...
    ==> default: /home/vagrant/.rvm/rubies/ruby-2.2.1/bin/ruby -r ./siteconf20150506-4805-9u68er.rb extconf.rb
    ==> default: checking if the C compiler accepts ...
    ==> default: yes
    ==> default: Building nokogiri using packaged libraries.
    ==> default: checking for gzdopen() in -lz...
    ==> default: no
    ==> default: zlib is missing; necessary for building libxml2
    ==> default: *** extconf.rb failed ***
    ==> default: Could not create Makefile due to some reason, probably lack of necessary
    ==> default: libraries and/or headers.  Check the mkmf.log file for more details.  You may
    ==> default: need configuration options.
    ==> default:
    ==> default: Provided configuration options:
    ==> default:  --with-opt-dir
    ==> default:  --without-opt-dir
    ==> default:  --with-opt-include
    ==> default:  --without-opt-include=${opt-dir}/include
    ==> default:  --with-opt-lib
    ==> default:  --without-opt-lib=${opt-dir}/lib
    ==> default:  --with-make-prog
    ==> default:  --without-make-prog
    ==> default:  --srcdir=.
    ==> default:  --curdir
    ==> default:  --ruby=/home/vagrant/.rvm/rubies/ruby-2.2.1/bin/$(RUBY_BASE_NAME)
    ==> default:  --help
    ==> default:  --clean
    ==> default:  --use-system-libraries
    ==> default:  --enable-static
    ==> default:  --disable-static
    ==> default:  --with-zlib-dir
    ==> default:  --without-zlib-dir
    ==> default:  --with-zlib-include
    ==> default:  --without-zlib-include=${zlib-dir}/include
    ==> default:  --with-zlib-lib
    ==> default:  --without-zlib-lib=${zlib-dir}/lib
    ==> default:  --enable-cross-build
    ==> default:  --disable-cross-build
    ==> default: ERROR:  Error installing rails:
    ==> default:  ERROR: Failed to build gem native extension.
    ==> default:
    ==> default:     Building has failed. See above output for more information on the failure.
    ==> default: extconf failed, exit code 1
    ==> default:
    ==> default: Gem files will remain installed in /home/vagrant/.rvm/gems/ruby-2.2.1/gems/nokogiri-1.6.6.2 for inspection.
    ==> default: Results logged to /home/vagrant/.rvm/gems/ruby-2.2.1/extensions/x86_64-linux/2.2.0/nokogiri-1.6.6.2/gem_make.out
    The SSH command responded with a non-zero exit status. Vagrant
    assumes that this means the command failed. The output for this command
    should be in the log above. Please read the output to determine what
    went wrong.

Note that during the install you'll see a bunch of warnings like:

    ==> default: xml_node_set.c: In function ‘dealloc_namespace’:
    ==> default: xml_node_set.c:9:13: warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual]
    ==> default:      xmlFree((xmlChar *)ns->href);
    ==> default:              ^
    ==> default: xml_node_set.c:11:13: warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual]
    ==> default:      xmlFree((xmlChar *)ns->prefix);
    ==> default:              ^

and

    ==> default: xml_node.c: In function ‘reparent_node_with’:
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_ATTRIBUTE_NODE’ not handled in switch [-Wswitch]
    ==> default:        switch (reparentee->type) {
    ==> default:        ^
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_ENTITY_NODE’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_DOCUMENT_NODE’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_DOCUMENT_FRAG_NODE’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_NOTATION_NODE’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_HTML_DOCUMENT_NODE’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_DTD_NODE’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_ELEMENT_DECL’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_ATTRIBUTE_DECL’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_ENTITY_DECL’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_NAMESPACE_DECL’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_XINCLUDE_START’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_XINCLUDE_END’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:168:7: warning: enumeration value ‘XML_DOCB_DOCUMENT_NODE’ not handled in switch [-Wswitch]
    ==> default: xml_node.c:186:7: warning: enumeration value ‘XML_ATTRIBUTE_NODE’ not handled in switch [-Wswitch]
    ==> default:        switch (reparentee->type) {
    ==> default:        ^
    etc....

They can be ignored. As ugly as they are they don't halt the installation or prevent Nokogiri from working properly.


###Command:

apt-get install libsqlite3-dev

What it does:

Installs the SQLite libraries necessary to create a new Rails app with the default Gemset. Without it, running rails new {APP_NAME} inside the virtual machine fails with:

    Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

        /home/vagrant/.rvm/rubies/ruby-2.2.1/bin/ruby -r ./siteconf20150506-24454-6cwwiw.rb extconf.rb
    checking for sqlite3.h... no
    sqlite3.h is missing. Try 'port install sqlite3 +universal',
    'yum install sqlite-devel' or 'apt-get install libsqlite3-dev'
    and check your shared library search path (the
    location where your sqlite3 shared library is located).
    *** extconf.rb failed ***
    Could not create Makefile due to some reason, probably lack of necessary
    libraries and/or headers.  Check the mkmf.log file for more details.  You may
    need configuration options.

    Provided configuration options:
      --with-opt-dir
      --without-opt-dir
      --with-opt-include
      --without-opt-include=${opt-dir}/include
      --with-opt-lib
      --without-opt-lib=${opt-dir}/lib
      --with-make-prog
      --without-make-prog
      --srcdir=.
      --curdir
      --ruby=/home/vagrant/.rvm/rubies/ruby-2.2.1/bin/$(RUBY_BASE_NAME)
      --with-sqlite3-dir
      --without-sqlite3-dir
      --with-sqlite3-include
      --without-sqlite3-include=${sqlite3-dir}/include
      --with-sqlite3-lib
      --without-sqlite3-lib=${sqlite3-dir}/lib

    extconf failed, exit code 1

    Gem files will remain installed in /home/vagrant/.rvm/gems/ruby-2.2.1/gems/sqlite3-1.3.10 for inspection.
    Results logged to /home/vagrant/.rvm/gems/ruby-2.2.1/extensions/x86_64-linux/2.2.0/sqlite3-1.3.10/gem_make.out
    An error occurred while installing sqlite3 (1.3.10), and Bundler cannot continue.
    Make sure that `gem install sqlite3 -v '1.3.10'` succeeds before bundling.
             run  bundle exec spring binstub --all
    /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/resolver.rb:369:in `resolve': Could not find gem 'sqlite3 (>= 0) ruby' in the gems available on this machine. (Bundler::GemNotFound)
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/resolver.rb:167:in `start'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/resolver.rb:129:in `resolve'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/definition.rb:193:in `resolve'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/definition.rb:132:in `specs'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/definition.rb:177:in `specs_for'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/definition.rb:166:in `requested_specs'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/environment.rb:18:in `requested_specs'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/runtime.rb:13:in `setup'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler.rb:122:in `setup'
      from /home/vagrant/.rvm/gems/ruby-2.2.1@global/gems/bundler-1.8.4/lib/bundler/setup.rb:18:in `<top (required)>'
      from /home/vagrant/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
      from /home/vagrant/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'

###Commands:

apt-get -y install postgresql
apt-get -y install pq
apt-get -y install libpq-dev

What they do:

Install the postgres database and supporting tools. The postgresql and pg packages aren't necessary for the tutorial but they are nice to have if you want to do more advanced exploration.

The "libpq-dev" package is required TKTKTKTKTKT


###Command:

wget -qO- https://toolbelt.heroku.com/install.sh | sh

What it does:

Installs the stand alone heroku client.


###Command:

sed -i -r "s/127.0.0.1\s+localhost/0.0.0.0  localhost/" /etc/hosts

What it does:

Allows the virtual machine to accept incoming traffic from the host machine when accessing https://localhost:3000/


###Command:

config.vm.provision :shell, privileged: false, inline: <<-END_OF_COMMANDS

What it does:

Like the earlier version, this line tells Vagrant to run all the commands between it and the final "END_OF_COMMANDS" in a shell on the virtual machine. The difference here is the "privileged: false" portion. With that set, the commands are run as a regular user named "vagrant" instead of root. The vagrant user is what's used when logging into the virtual machine from the host machine with the vagrant ssh command. So, everything in this section sets up the account that actually gets used during development.


###Commands:

/bin/bash -lc 'git config --global user.email "vagrant_vm@example.com"'
/bin/bash -lc 'git config --global user.name "Vagrant VM"' 

What they do:

Define the minimum account info necessary to use Git. Without this, git complains with:

    *** Please tell me who you are.

    Run

      git config --global user.email "you@example.com"
      git config --global user.name "Your Name"

    to set your account's default identity.
    Omit --global to set the identity only in this repository.

    fatal: empty ident name (for <vagrant@vagrant-ubuntu-trusty-64.(none)>) not allowed

You should set these for real if you plan to publish your versions of the tutorial publicly.


###Command:

echo 'gem: --no-document' > ~/.gemrc

What it does:

Creates a .gemrc file in the vagrant user's home directory and sets a flag telling the gem command not to bother building documentation. This speeds up the setup processes a little by making the assumption that you won't need the docs to live on the virtual machine.


###Commands:

gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
curl -sSL https://get.rvm.io | bash -s stable

What they do:

Installs RVM, the Ruby Version Manager. Using RVM makes it easier to experiment with different versions of ruby. It's not strictly necessary but useful for potential experimentation.

The first line fetches a security key necessary to verify the second step. The next line uses "curl" to grab and run the installer. At press time version 1.26.11 is installed. That will change as RVM is updated since the command installs whatever the latest stable version is.


###Command:

/bin/bash -lc 'rvm mount -r https://rvm.io/binaries/ubuntu/14.04/x86_64/ruby-2.2.1.tar.bz2'

What it does:

Installs version 2.2.1 of Ruby via RVM via a pre-build binary. This means Ruby is installed without having to compile it on the virtual machine. This saves a lot of time.

Ruby is updated relatively frequently. However, it often takes a while for someone to make the pre-built binaries. For example, the current version of Ruby at the time this post was written is 2.2.2 but no pre-build binary is available for it yet. Version 2.2.1 is the latest available. So, that's what's used. Links to all the available pre-built versions for Ubuntu 14.04 64-bit are here.

Just switch out the URL in the Vagrantfile to use a different one.

There's no need to worry about checking for updates if all you're doing is running through the tutorial on a virtual machine. The time you'd need to stay current is if the server was going to be hosting a live site on the web where security updates are critical.

/bin/bash -lc 'rvm --default use 2.2.1'
/bin/bash -lc 'gem install -V rails -v 4.2.0'
/bin/bash -lc 'gem install json -v 1.8.2'



###Command:

What it does:



Note that the '-V' in the gem installs is just so you can see more output. It takes some time, so this helps you know the process isn't stalled.

This is with the '20150506.0.0' version of the ubuntu/trusty64 box.

  • apt-get install libpq-dev - is for 'pg' gem

The gems included are those that are those that match the explicit Gemfile defined in the Tutorial. They also include the gems that are used with the rails 4.2 defaults at the time the script was created. This is all done at install time so that ones the install is complete, you don't immediately run into having to download stuff the first time bundle install is run.

The Ruby on Rails Tutorial is an excellent way to get their bearings.

http://news.railstutorial.org/rails_tutorial_3rd_ed_screencast_access/


apt-get -y install nodejs

Because Ruby needs a javascript runtime. 

Note that in Chapter 3, when you copied in the full Gemfile from 11.67 (or whatever), 'bundle exec rake test' hung indefinitely. You went back and just uses the Gemfile from Chapter 3. Directly. Keep an eye out for updates to the Gemfile to see if you can catch what made it go sideways.


Updated memory to 1024 to give some padding to run rails and spring running at the same time.


Without TKTKTKTTK, heroku dies with this:

    ERROR:  Error installing heroku:
      ERROR: Failed to build gem native extension.

        /home/vagrant/.rvm/rubies/ruby-2.2.1/bin/ruby -r ./siteconf20150514-6002-f2nji3.rb extconf.rb
    checking for main() in -lstdc++... no
    creating Makefile

    make "DESTDIR=" clean

    make "DESTDIR="
    compiling unf.cc
    make: g++: Command not found
    make: *** [unf.o] Error 127

    make failed, exit code 2

    Gem files will remain installed in /home/vagrant/.rvm/gems/ruby-2.2.1/gems/unf_ext-0.0.7.1 for inspection.
    Results logged to /home/vagrant/.rvm/gems/ruby-2.2.1/extensions/x86_64-linux/2.2.0/unf_ext-0.0.7.1/gem_make.out

TKTKTKT: Add this to .vimrc for some standard vim usage if people use it.

set nu
set nowrap
set tabstop=2
set shiftwidth=2
set softtabstop=2
set expandtab
set smarttab
set autoindent
set copyindent
set smartcase
set autowrite

# these are optoins you use that probably shouldn't be in the deployment.
let mapleader=","
nmap <CR> o<Esc>

TKTKTKT: Add oh-my-zsh and setup to show the ruby version and branch your on along with some nice colors.


TKTKTK: Add instructions in the readme about how to setup: git config --global core.editor "vim"


TKTKTKT: Pull down files from a gitrepo instead of trying to inline them. Make sure to pull down specific version branches. You can coninue to update the branch as necessary. If you need to make a new version, it'll let you target both explicitly.


TKTKTKT: Setup a web server to host readme files.


TKTKTKT: In section 6.1.4 on looking for an invalid user the console response on your rails console is a lot longer than what's in the book. Probably that's not related to the vagrantfile, but take a look anyway.


TKTKKTKT: Add config for VIM so that it doesn't some automatic tabbing for Ruby.