How to Configure a Rails Application Server with RVM, Apache, and Passenger on Ubuntu 16.04

This tutorial will guide you through setting up a Rails application server using Apache as a front-end server and Passenger as a back-end.

Before You Begin

You’ll need:

  • An Ubuntu 16.04 server with at least 1GB of RAM and a non-root user with sudo access.
  • Your Rails application in a Git repository
  • Your Rails application’s database system installed on the server.

Step 1: Configure RVM

We’ll use RVM to install Ruby. This is the recommended approach for using Passenger with Ruby.

Log in to your server as your non-root user.

ssh deploy@your_ip_address

RVM has a few prerequisites you’ll need to install:

sudo apt-get update
sudo apt-get install -y curl gnupg build-essential dirmngr gnupg  apt-transport-https ca-certificates

Once those complete, Install RVM:

sudo gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
curl -sSL https://get.rvm.io | sudo bash -s stable

Add your user to the rvm group:

sudo usermod -a -G rvm `whoami`

Now execute this command to enable RVM to work with the secure_path setting for sudo:

if sudo grep -q secure_path /etc/sudoers; then sudo sh -c "echo export rvmsudo_secure_path=1 >> /etc/profile.d/rvm_secure_path.sh" && echo Environment variable installed; fi

Log out of your machine and log back in.

Install Ruby:

rvm install ruby-2.5.0

You’ll be prompted for your sudo password to install additional dependencies.

Execute this command to make this version of Ruby the default version of Ruby:

rvm --default use 2.5.0

Install Bundler, the dependency manager for Ruby applications:

gem install bundler --no-rdoc --no-ri

Now install Node.js, which Rails applications use for the Asset Pipeline.

curl --fail -ssL -o setup-nodejs https://deb.nodesource.com/setup_8.x
sudo bash setup-nodejs
sudo apt-get install -y nodejs

With these components installed, you can move on to installing Passenger.

Step 2: Installing Passenger

Passenger is the application server that will launch your Rails app. It works well with Apache, so that’s how we’ll configure it.

First, ensure Apache is installed:

sudo apt-get install apache2

We’ll install Passenger and its module using Passenger’s repository:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger xenial main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update
sudo apt-get install -y libapache2-mod-passenger

Once Passenger is installed, enable the module and restart Apache:

sudo a2enmod passenger
sudo apache2ctl restart

Passenger itself is installed. Now let’s configure it to serve our Rails app.

Step 3: Configure Passenger for Rails

Create a virtual host for your Rails application. You’ll point it to /var/www/example.com/current/public, which is the location of your Rails application’s public folder.

First, create the web app folder and ensure the deploy user owns it:

sudo mkdir -p /var/www/example.com
sudo chown deploy: /var/www/example.com

Create a new site:

sudo nano /etc/apache2/sites-available/example.com.conf

Add this to the file:

<VirtualHost *:80>
    ServerName example.com

    # Tell Apache and Passenger where your app's 'public' directory is
    DocumentRoot /var/www/example.com/current/public

    PassengerRuby /usr/local/rvm/gems/ruby-2.5.0/wrappers/ruby
    
    # Relax Apache security settings
    <Directory /var/www/example.com/current/>
      Allow from all
      Options -MultiViews
      # Uncomment this if you're on Apache >= 2.4:
      #Require all granted
    </Directory>
</VirtualHost>

Enable the site

sudo a2ensite example.com

Disable the default site

sudo a2dissite 000-default

Now let’s deploy the app.

Step 4: Deploying your App

We’ll deploy the app manually by using Git to check out the application into your server’s /var/www/example.com folder into a subfolder called v1. We’ll then use a symlink to link the v1 folder to the /var/www/example.com/current folder that Rails and Passenger will serve.

This way, when you deploy new versions, you have the option of checking them out to a new folder, like v2 and changing the symlink. Then if something goes wrong, you can roll back. This is similar to methods that automated deployment tools like Capistrano use, and this makes it easier for you to migrate your process to those tools.

Deploy your app from Git.

cd /var/www/example.com
git clone git://github.com/username/myapp.git v1

Now create a symlink from v1 called current.

ln -nfs v1/ current/

Then switch to the current directory:

cd current/

This tutorial assumes your config/database.yml file is configured to talk to a database. If it’s not, you should make those configuration changes now before moving on.

Install dependencies for deployment only:

bundle install --deployment --without development test

Now compile assets for production and apply database migrations:

bundle exec rake assets:precompile db:migrate RAILS_ENV=production

Finally, ensure the file config/secrets.yml exists.

cat config/secrets.yml

If you see this at the end:

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

then you should set an environment variable in your .bashrc file.

nano ~/.bashrc

At the top of the file, add this:

export SECRET_KEY_BASE=some_long_value_nobody_will_guess

Save and exit the file.

Your app is now deployed.

Visit http://example.com to view it.

Conclusion

Deploying Rails with Passenger involves many steps, and this is a very manual deployment process. Once you have your application deployed, you’ll want to explore more automated solutions such as Capistrano.