Locally Run Amazon Linux 2 for Ruby on Rails Development

Motivation

I want to make it easy for other people I collaborate to be up and running with a Ruby on Rails app without having to provision their own machine. Since I’m using an EC2 instance running on Amazon Linux 2, I want to approximate that experience the best I can by downloading and using that virtual image.

Vagrant and Docker are interesting choices, though I want to be as close to as AWS for knowledge transfer if anyone has to work on the architecture such as updating the user-data that setups on the instance.

I’ve been using Docker and Vagrant for years and they create lots of friction for small teams without the sunken knowledge, so I think just passing along a VM image that is 1GB in size and it will take up another 1GB in virtual disk space is acceptable. All you need is VirtualBox and you’re ready to go.

Considerations

This image will be running:

  • Ruby on Rails app
  • Postgres for database
  • Redis for Sidekiq

In production I use RDS for my database and Elasticache for Redis so its not 1-to-1 the same but this is “good enough” for our use-case to provide the least amount of developer friction.

Getting Started

To keep things organized I’m going to create a VirtualImages directory in my user’s home directory and place all files in there.

mkdir ~/VirtualImages

Install VirtualBox

If you have yet to do so already go and install VirtualBox

https://www.virtualbox.org/wiki/Downloads

Download the VDI

Then we’ll download Amazon Linux 2 VDI file and I’m going to place it in my VirtualImages directory.

https://cdn.amazonlinux.com/os-images/2.0.20180810/virtualbox/

Create boot.iso

We need to create a directory called seedconfig and within that file we need to create two files called user-data and meta-data. These will be yaml files though its important you omit the extension.

Create the User and Meta Data

user-data

#cloud-config
#vim:syntax=yaml
users:
- default
chpasswd:
list: |
ec2-user:password

meta-data

local-hostname: amazonlinux.onprem
# eth0 is the default network interface enabled in the image. You can configure static network settings with an entry like the following.
network-interfaces: |
auto eth0
iface eth0 inet dhcp
remember to omit the extensions or you’ll have a bad time.

Validate the YAML Files

Before we create our boot image lets make sure that our yaml files are valid because if they are not then the user and meta data will not be loaded.

You can paste the contents of the yaml files into http://www.yamllint.com/ to verify there are no issues with the format of these files.

Create the ISO File

Then from the directory one above seedconfig directory we’ll run this command in terminal to create the seed.iso

hdiutil makehybrid -o seed.iso -hfs -joliet -iso -default-volume-name cidata seedconfig/
There’s an error but I just ignore it since it doesn’t matter.

Create and Configure the VM

We want to create a NEW VM in Virtualbox. You can name the box whatever you wish and leave the default settings. I chose the type as Linux and version as Other Linux (64 bit). Then for the hard disk we’ll attach the VDI image.

You’ll notice it says 25GB, it won’t take up this much space on your hard drive but it should take up 1GB a virtual disk space.

Once we create our box we don’t want to launch it just yet because we need to attach the seed.iso to the optical disk drive so it uses it on boot.

right click on your box to get to settings

Also just make sure the optical driver is above the hard drive since we want it to boot the seed.iso first.

Port Forwarding

Under network we’ll leave the Host and Guest IP blank so they are inferred and forward our host to guest ports.

SSH into Guest

From your local machine SSH with ec2-user on port 2222 and when prompted fill in the password, which I have set as password

ssh ec2-user@localhost -p 2222

Manually Provision Rails

Here is the provisioning script I spent tirelessly with AWS Support to craft for Amazon Linux 2. I would suggest running each uncommented line 1 by 1. If these appears very manual don’t fret because we’re going to include this in our user-data file.

#!/usr/bin/env bash
# To run Rails 5 we want the latest ruby version
# so we need to use amazon linux extras
sudo amazon-linux-extras install -y ruby2.4
# ruby-devel - needed to compile ruby gem
# xml2, xstl and patch - is for nokogiri
# redhat-rpm-config - in order to install native extensions with gems
# sqlite-devel - default database thats configured with Rails
sudo yum install -y gcc ruby-devel libxml2 libxml2-devel libxslt libxslt-devel patch redhat-rpm-config sqlite-devel
# Extra Packages for Enterprise Linux (EPEL)
sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum-config-manager --enable epel
# Rails required a Javascript Runtime because of of execjs
# Not in Amazon's repo so using epel to install
# https://github.com/rails/execjs
sudo yum install -y nodejs npm --enablerepo=epel
# For some reason rdoc wasn't automatically installed
# and fails the first time but not the second so weird workaround
gem install rdoc
gem install rdoc

# Required to use Rails, installs all gems in a Rails project
gem install bundler
# Install Rails
gem install rails
rails new example
# !!! You may have to add to your Gemfile Big Decimal
echo "gem 'bigdecimal" >> /home/ec2-user/example/Gemfile
cd example
bundle install

Start Rails and View Example Page

Once you get through all that you can now start the rails server.

rails s

From our web-brower we should be able to access the server running in the Guest OS.

If we’re happy with our setup we could snapshot the state of our VM and call it a day.