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
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/
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.
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.