How to Deploy Ruby on Rails Apps on AWS LightSail

Pramodkumar
6 min readApr 14, 2021

LightSail is a user-friendly Virtual Private Server (VPS) that gives you everything you need to build an app or website, in addition to a low-cost monthly plan. Whether you’re new to the cloud or want to use it quickly with the AWS infrastructure.

Lets start first create a AWS account: Link to AWS
# After creating account when you will log in then you will get the console screen as below image

Lets Start

#Set up instance

First thing we need to do is to set up an instance in which our rails app is to be deployed.
Click on the LightSail link from aws console then you will be redirected to LightSails dashboard

Click on “create instance” to redirect to create instance page

#Click on “Create instance” to redirect to create instance page
Select the region, platform and blueprint
In this walkthrough select platform linux/unix and blue print ubuntu 18.04 LTS

# The select a plan (in this case we have selected $5 plan).
Add a name to identify the instance
Add tags and tag values

# Now on LightSail you will see the instance has been created. Click on the console to open the instance

In console add first get the updates by executing

sudo apt-get update

# Install the rbenv and Ruby dependencies with apt-get:

$sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev libffi-dev

# Add python dependency

sudo apt-get install software-properties-common

#Install rbenv

Clone the rbenv repository from GitHub into the directory

$git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

Next, add ~/.rbenv/bin to your $PATH so that you can use the rbenv command line utility. Do this by altering your ~/.bashrc file so that it affects future login sessions:

$echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc

Then add the command eval "$(rbenv init -)" to your ~/.bashrc file so rbenv loads automatically:

$echo 'eval "$(rbenv init -)"' >> ~/.bashrc

Next, apply the changes you made to your ~/.bashrc file to your current shell session:

$source ~/.bashrc

Verify that rbenv is set up properly by using the type command, which will display more information about the rbenv command:

type rbenv

Your terminal window will display the following:

rbenv is a function
rbenv ()
{
local command;
command="${1:-}";
if [ "$#" -gt 0 ]; then
shift;
fi;
case "$command" in
rehash | shell)
eval "$(rbenv "sh-$command" "$@")"
;;
*)
command rbenv "$command" "$@"
;;
esac
}

# Install Ruby

$rbenv install -v 2.2.3
$rbenv global 2.2.3

Ruby gems generates local documentation for each gem that you install, as this process can be lengthy. To avoid this

$echo "gem: — no-document" > ~/.gemrc

#Install Rails

$gem install rails
$rbenv rehash

Verify that Rails has been installed properly by printing its version, with this command

$rails -v

Install JavaScript Runtime

$sudo add-apt-repository ppa:chris-lea/node.js

Update apt-get and install the Node.js package

$sudo apt-get update
$sudo apt-get install nodejs

Now clone the repository from git-hub and CREATE & MIGRATE THE DATABASE

$git clone https://github.com/username/want-some-java.git

We need to setup BASH PROFILE for our rails app to run

$cd
$vim .bash_profile

Add this line in the last of the bash_profile opened

->press i
than add this line in bottom
->export RAILS_ENV="production"
->press esc
->press :wq
->press enter
-> type source .bash_profile

then
$cd REPO
$ rake secret

{copy the secret generated}

$cd
$vim .bash_profile

->press i

than add this line in bottom
export SECRET_KEY_BASE=”paste the previously copied secret”

->press esc
->press :wq
->press enter
-> type source .bash_profile

Setup environment

$cd REPO
$sudo apt-get install libpq-dev
$bundle install
$RAILS_ENV=production bundle exec rake db:create
$rake db:migrate RAILS_ENV=production

#Adding Unicorn

$vi Gemfile

At the end of the file, add the Unicorn gem with this line:

gem ‘unicorn’

To install Unicorn, and any outstanding dependencies, run Bundler:

$bundle

Unicorn is now installed, but we need to configure it.

Let’s add our Unicorn configuration to config/unicorn.rb. Open the file in a text editor:

$vi config/unicorn.rb

Copy and paste this configuration into the file:

# set path to application
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
working_directory app_dir
# Set unicorn options
worker_processes 2
preload_app true
timeout 30
# Set up socket location
listen "#{shared_dir}/sockets/unicorn.sock", :backlog => 64
# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"
# Set master PID location
pid "#{shared_dir}/pids/unicorn.pid"

Save and exit. This configures Unicorn with the location of your application, and the location of its socket, logs, and PIDs. Feel free to modify the file, or add any other options that you require.

Now create the directories that were referred to in the configuration file:

$cd REPO
$mkdir -p shared/pids shared/sockets shared/log

Create a script and open it for editing with this command (replace the highlighted part with your application name):

$sudo vi /etc/init.d/unicorn_REPO

Copy and paste the following code block into it, and be sure to substitute USER and APP_NAME(highlighted) with the appropriate values:

We have USER=ubuntu and APP_NAME=REPO

#!/bin/sh
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the unicorn app server
# Description: starts unicorn using start-stop-daemon
### END INIT INFO
set -e
USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"
# app settings
USER="ubuntu"
APP_NAME="REPO"
APP_ROOT="/home/$USER/$APP_NAME"
ENV="production"
# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="$APP_ROOT/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"
# make sure the app exists
cd $APP_ROOT || exit 1
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}oldsig () {
test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}

case $1 in
start)
sig 0 && echo >&2 "Already running" && exit 0
echo "Starting $APP_NAME"
su - $USER -c "$CMD"
;;
stop)
echo "Stopping $APP_NAME"
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
echo "Force stopping $APP_NAME"
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload|upgrade)
sig USR2 && echo "reloaded $APP_NAME" && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
$CMD
;;
rotate)
sig USR1 && echo rotated logs OK && exit 0
echo >&2 "Couldn't rotate logs" && exit 1
;;
*)
echo >&2 $USAGE
exit 1
;;
esac

Save and exit. This will allow you to use service unicorn_appname to start and stop your Unicorn and your Rails application.

Update the script’s permissions and enable Unicorn to start on boot:

$sudo chmod 755 /etc/init.d/unicorn_REPO
$sudo update-rc.d unicorn_REPO defaults

$sudo service unicorn_REPO start

#Adding Nginx

Install Nginx using apt-get:

$sudo apt-get install nginx

Now open the default server block with a text editor:

$sudo vi /etc/nginx/sites-available/default

Replace the contents of the file with the following code block. Be sure to replace the the highlighted parts with the appropriate username and application name:

upstream app {
# Path to Unicorn SOCK file, as defined previously
server unix:/home/ubuntu/REPO/shared/sockets/unicorn.sock fail_timeout=0;
}server {
listen 0.0.0.0;
server_name localhost; root /home/ubuntu/REPO/public; try_files $uri/index.html $uri @app; location @app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
} error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}

Save and exit. This configures Nginx as a reverse proxy, so HTTP requests get forwarded to the Unicorn application server via a Unix socket. Feel free to make any changes as you see fit.

Restart Nginx to put the changes into effect:

$sudo service nginx restart

Now navigate to ipv4 public IP your rails app will be live

Common mistakes

Unicorn not getting started
- Follow the exact steps as mentioned above
- Check the shared folder and sub folders have read and write permissions

Ruby environment is initialized when terminal is opened again
- Add this file in .bash_profile
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

--

--