How to deploy Rails 5.2 on AWS EC2 + Ubuntu + Nginx + Passenger

Keisuke Inaba
ITNEXT
Published in
5 min readFeb 7, 2019

--

In this article, I will illustrate how to deploy a Rails 5.2 app on AWS EC2, Ubuntu, Nginx and Passenger in details.

It takes 1–2 hours if everything goes well.

Environments

  • Ruby 2.5.1
  • rvm 1.29.7
  • Rails 5.2
  • AMS EC2
  • Ubuntu 18.04 LTS 20180814

1. Set up EC2 Ubuntu

Visit AWS EC2 console page and create a new EC2 instance.

Select “Ubuntu Server 18.04 LTS”.

FYI, the pricing is the same as Amazon Linux:
Ubuntu 18.04 LTS — Bionic

Login to the EC2 via ssh after it starts.

NOTE: the defaul user name is “ubuntu”.

$ ssh -p 22 -i ~/.ssh/[YOUR_KEY] ubuntu@[YOUR_IP_ADDRESS]

2. Install Ruby

Next, install Ruby in the Ubuntu.

System configuration

$ sudo apt-get update
$ sudo apt-get install -y curl gnupg build-essential

RVM configuration

$ sudo apt-get install gnupg2 -y
$ curl -sSL https://get.rvm.io | bash -s stable — ruby=2.5.1
$ sudo gpg2 — keyserver hkp://pool.sks-keyservers.net — recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
$ curl -sSL https://get.rvm.io | sudo bash -s stable
$ sudo usermod -a -G rvm ‘YOUR_USER_NAME’

Re-login to the EC2 in order to apply the above configurations.

$ exit
$ ssh -p 22 -i ~/.ssh/[YOUR_KEY] ubuntu@[YOUR_IP_ADDRESS]
$ rvm -v
rvm 1.29.7 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]

Ruby configuration

Install Ruby secifying a particular version that you want to use globally, and set it as the default.

$ rvm install ruby 2.5.1
$ rvm — default use ruby 2.5.1

Install bundler

$ gem install bundler — no-rdoc — no-ri

Install Node.js

$ sudo apt-get install -y nodejs &&
> sudo ln -sf /usr/bin/nodejs /usr/local/bin/node

3. Set up Passenger & Nginx

Install Passenger packages

$ sudo apt-get install -y dirmngr gnupg
$ sudo apt-key adv — keyserver hkp://keyserver.ubuntu.com:80 — recv-keys 561F9B9CAC40B2F7
$ sudo apt-get install -y apt-transport-https ca-certificates

$ sudo sh -c ‘echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bionic main > /etc/apt/sources.list.d/passenger.list’
$ sudo apt-get update

$ sudo apt-get install -y libnginx-mod-http-passenger
$ sudo apt-get install -y libnginx-mod-http-passenger

Activate Passenger Nginx

Confirm the path of the configuration file, and add the link.

$ if [ ! -f /etc/nginx/modules-enabled/50-mod-http-passenger.conf ]; then sudo ln -s /usr/share/nginx/modules-available/mod-http-passenger.load /etc/nginx/modules-enabled/50-mod-http-passenger.conf ; fi
$ sudo ls /etc/nginx/conf.d/mod-http-passenger.conf

Re-start the Nginx after the above commands.

$ sudo apt install nginx-core
$ sudo service nginx restart

Confirm the install

Make sure if the Passenger has been successfully installed.

$ sudo /usr/bin/passenger-config validate-install
What would you like to validate?
Use <space> to select.
If the menu doesn’t display correctly, press ‘!’
‣ ⬢ Passenger itself
⬡ Apache
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -
* Checking whether this Passenger install is in PATH… ✓
* Checking whether there are no other Passenger installations… ✓
Everything looks good. :-)

Also, make sure if the Nginx has started the Passenger.

$ sudo /usr/sbin/passenger-memory-stats
Version: 6.0.1
Date : 2019–01–17 21:25:01 +0000
— — — — — Nginx processes — — — — — -
PID PPID VMSize Private Name
— — — — — — — — — — — — — — — — — — —
14759 1 141.1 MB 0.4 MB nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
14762 14759 143.7 MB 0.7 MB nginx: worker process
### Processes: 2
### Total private dirty RSS: 1.02 MB
— — — Passenger processes — — -
PID VMSize Private Name
— — — — — — — — — — — — — — — -
14738 389.2 MB 2.3 MB Passenger watchdog
14748 673.0 MB 3.2 MB Passenger core
### Processes: 2
### Total private dirty RSS: 5.51 MB

Everything is fine if both Nginx and Passenger are running.

Update regulary

Both Nginx and Passenger are periodically updated via APT. So, it is better to update them regulary with the following commands.

$ sudo apt-get update
$ sudo apt-get upgrade

4. Deploy Rails App

Software to be pre-Installed

Install Git.

$ sudo apt-get install -y git

Install MySQL.

$ sudo apt-get install mysql-server mysql-client
$ sudo apt-get install libmysqlclient-dev

Install Yarn if it is required by your app.

$ 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 yarn

Rails configuration

Clone your app with Git.

$ cd /var/www
$ sudo git clone [YOUR_GIT_URL]
$ sudo chown [YOUR_USER_NAME] -R [APP_REPOSITORY]

Set up your app with the following commands.

Write the code which was generated when “rails new” was conducted in “config.master.key”.

$ cd [APP_REPOSITORY]
$ vim config/master.key
$ bundle install — deployment — without development test
$ bundle exec rake db:create RAILS_ENV=production
$ bundle exec rake assets:precompile RAILS_ENV=production

Enhance the security level of the configuration files.

$ chmod 700 config db
$ chmod 600 config/database.yml config/master.key

“Uglifier::Error” occurred?

The following error could happen when “rake assets:precompile” is conducted.

Uglifier::Error: Unexpected token: punc ({). To use ES6 syntax, harmony mode must be enabled with Uglifier.new(:harmony => true)

It can be solved by editting “config/environments/production.rb” as follows.

# config.assets.js_compressor = :uglifier 
config.assets.js_compressor = Uglifier.new(harmony: true)

Nginx configuration

Obtain the path of Ruby.

$ passenger-config about ruby-command
passenger-config was invoked through the following Ruby interpreter:
Command: /usr/local/rvm/gems/ruby-2.5.1/wrappers/ruby
Version: ruby 2.5.1p57 (2018–03–29 revision 63029) [x86_64-linux]
To use in Apache: PassengerRuby /usr/local/rvm/gems/ruby-2.5.1/wrappers/ruby
To use in Nginx : passenger_ruby /usr/local/rvm/gems/ruby-2.5.1/wrappers/ruby
To use with Standalone: /usr/local/rvm/gems/ruby-2.5.1/wrappers/ruby /usr/bin/passenger start

The path “/usr/local/rvm/gems/ruby-2.5.1/wrappers/ruby” is used later as [YOUR_RUBY_PATH].

Create an app configuration file.

$ sudo vim /etc/nginx/sites-enabled/[APP_REPOSITORY].conf

Write the settings in the file as follows.

[YOUR_RUBY_PATH] is the Ruby path as mentioned above.

# /etc/nginx/sites-enabled/[APP_REPOSITORY].conf
server {
listen 80;
server_name [YOUR_DOMAIN];
# Tell Nginx and Passenger where your app’s ‘public’ directory is
root /var/www/[APP_REPOSITORY]/public;
# Turn on Passenger
passenger_enabled on;
passenger_ruby [YOUR_RUBY_PATH];
}

Re-start Nginx and check if it is working.

$ sudo service nginx restart
$ curl http://[YOUR_DOMAIN]

That’s it if the root HTML codes are properly displayed.

Your Rails app is ready to go!

Need to make it HTTPS?

Find out more:
How to make EC2 + Ubuntu + Nginx + Passenger HTTPS with Let’s Encrypt

Need to set up Action Cable?

Find out more:
How to set up Rails 5 Action Cable in production

Sources

--

--

BE Software Engineer / Shopify Public App Owner & Developer / Ruby / Rails / JavaScript / React / Next.js / https://lnk.bio/kei178