Deploy a Ruby on Rails app on AWS Graviton - Part 1

If you use AWS, a small change can help you save money and gain better performance.

AWS launched AWS Graviton that are custom built by Amazon and use ARM based processors. They use less energy and are better price performant1. If you know about Apple M1 and its performance then you are already aware of the power of ARM processors.

There is enough material available on the Internet on how to deploy a Ruby on Rails on x86/Intel based processors, however, preparing an AWS Graviton EC2 instance for Ruby on Rails is slightly different.

In this post we will prepare an AWS Graviton EC2 instance for Ruby on Rails deployment. In later posts we will cover:2

  1. Setting up Puma & Nginx
  2. Setting up Puma & Sidekiq as systemctl services for easy management
  3. Setting up Capistrano for easy deployment

Please note:

  1. We will use Ubuntu as the OS.
  2. We will use RVM
  3. We will use Sidekiq as our ActiveJob processor
  4. We use PostgreSQL on RDS and will install only the client on the instance
  5. We will use Puma as application server and Nginx in front of Puma

Installations

Create a Graviton based EC2 instance from AWS Console, and ssh into it

Update packages

sudo apt-get update
sudo apt-get install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev

Install RVM

You need to add a custom repository to install RVM, and that also requires adding GPG keys. Check RVM website to get current keys.

gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
sudo apt-get install software-properties-common
sudo apt-add-repository -y ppa:rael-gc/rvm
sudo apt-get update
sudo apt-get install rvm
sudo usermod -a -G rvm ubuntu

Log out and log in to the machine again.

Install Ruby

We will use Ruby 2.7.2, however you can choose to install any version that is relevant for you.

rvm install 2.7.2
rvm use 2.7.2
rvm use --default 2.7.2

Install Node.js & Yarn

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
# Adding Yarn repository
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update
sudo apt-get install nodejs yarn

Install PostgreSQL and Redis Clients

sudo apt-get install postgresql-client
sudo apt-get install redis-tools

Install ImageMagick

This command is a bit specific for ARM processors, take care to use this exact command

sudo apt-get install imagemagick --fix-missing

Install Nginx

sudo apt-get install nginx

Install Gems that require custom setup for AWS Graviton

sassc gem

This one took a while for us to figure out

gem install bundler
gem install sassc --version=2.4.0 -- --disable-march-tune-native

pg gem

sudo apt-get install libpq-dev
gem install pg -v '1.2.3

Environment Variables

The simplest way to set environment variables is to place them in /etc/environment file

# set env variables in /etc/environment
export RAIL_ENV=production
export RACK_ENV=production
export DATABASE_URL=postgresql://DB_USERNAME:DB_PASSWORD@host:5432/DB_NAME
export RAILS_MASTER_KEY=
export RAILS_SERVE_STATIC_FILES=enabled
export REDIS_URL=redis://REDIS_HOST:6379
export rvmsudo_secure_path=1

Please take care to

  1. Create a valid DATABASE_URL by replacing DB_USERNAME, DB_PASSWORD and DB_NAME If your database uses a different port than 5432, take care to replace that too.
  2. Add RAILS_MASTER_KEY
  3. Add REDIS_HOST. If your redis server runs at a different port than 6379, replace that as well.

At this point, you should have your EC2 instance ready for Ruby on Rails app, and you can use your favourite mechanism to deploy code to the machine.

Conclusion

Although AWS is very different from other VPS providers, there are a lot of things you can do better, in terms of your workflow as well as security. Having spent 10+ years using Cloud Providers like AWS and GCP, and a couple of years managing them, I know AWS can be very overwhelming at first. However, if you deploy on AWS, your infrastructure growth will be more cost effective and better handled in the longer term.


Footnotes

  1. For comparisons check this 

  2. We can also open source our Terraform scripts that can help you create production grade infrastructure on AWS in a matter of minutes. Soopr API is built using Elixir/Phoenix and can write about how to deploy an Elixir/Phoenix app on AWS. Let us know on twitter if you are interested in any of these topics.