Max Krebs

Deploying Rails to a Linux VPS

This is part three in my series on hosting a Rails application on a Linux Virtual Private Server. You can read part one here and part two here.

It’s About Time

Finally we are going to talk about what you actually do once you have a fancy new Linux server up and running. We are going to put our website on the Internet!

The stack that I use is Nginx with a Puma proxy for the web server, Postgres for the database, and rbenv to manage the Ruby version both on my local machine and on the server (RVM people, don’t email me). Finally we are going to configure out Rails app to use Capistrano for deployment.

Installing your Web Server

Every guide I’ve ever read has the first step of doing anything as updating your package manager so in that great tradition:

% sudo apt update && sudo apt upgrade

First things first, we will need to install Nginx and some other dependencies for later. You might have already installed git, but if not, make sure you do now.

% sudo apt install curl git-core nginx -y

Installing Your Database

Next we are going to install Postgres (I refuse to call it PostgreSQL). We also need a user that our application is going to use to connect to the database when it runs. Conventionally, that user has the same name as the application. I like to create my database at this point too, just because I am going to be in the psql interface and I would probably forget if I didn’t get it over with.

% sudo apt-get install postgresql make postgresql-contrib libpq-dev -y

Along with Postgres, we are installing make, the GNU collector of executables, and libpq, which is the C library for interfacing with Postgres (you will not have to worry about this).

Like I said before, we also need to create a user (or role) in the postgres database for our application. This command is a little hairy.

% sudo -u postgres createuser -s user_name

sudo -u postgres means “run the following command as the postgres user.” postgres is the default superuser account for the database and so we want to use that user to run commands against the database until we have our own application user. Replace user_name with the name of your application, or whatever user name you want to use to connect your app to your database.

This is all boring database admin, but hang in there, we will get to the fun stuff in a second. Next, we have to log in to the database interface to set the password for our newly created database user.

Much like our previous command, we need to use the postgres user to access the psql interface to the PostgreSQL database (confusing).

% sudo -u postgres psql

You will never guess what the command for resetting a user’s password is.

posgres=# \password user_name

Pick a strong password, and make sure you store it somewhere secure like a password manager because you will need to at least one more time.

While you are logged in, create your production database. The convention here is appname_environment.

postgres=# CREATE DATABASE appname_production;

Then you can exit psql. This is not super obvious at first because while most command line interfaces use some form of exit to quit, psql uses

postgres=# \q

Yay databases! If you have an existing database the you would have dumped and would like to load the data from, you can run this command:

% pg_restore --verbose --clean --no-acl --no-owner -h localhost -U myuser -d mydb latest.dump

But if you are setting up an app from scratch or deploying for the first time, no need to worry about that just yet.

Installing Ruby <3

Finally! The relatively fun stuff. Before we can get our application up on the server, we need the Ruby programming language, and a way to manage what version of ruby is installed. If you are using a environment manager for Ruby on your development machine (which you should be) you can just use that one for your server. Like I said before, I use rbenv so if you use RVM, the following commands will be different and you will have to sub out rbenv for RVM in future commands or configuration.

There are some more packages that need to be installed first. I wont go over what each of them does, but they are all needed down the line.

 %  sudo apt-get install make build-essential nodejs libssl-dev zlib1g-dev libreadline-dev libyaml-dev -y

Luckily for us, there is a rbenv installation script we can run to get up and running fairly quickly.

% curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-installer | bash

That will probably end by giving you a message about how you need to put rbenv in your path variable. Down the line, its also going to ask you to add some more settings into your path. To save time, just add them all now. Run the following commands to add the Path config to the rc file for whichever shell you are using (the default is bash so use .bashrc, but I use zsh).

% echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc
% rbenv init
% echo 'eval "$(rbenv init -)"' >> ~/.zshrc
% source .zshrc

Along with that installer script for rbenv, there is also a rbenv doctor script that just runs the checks to make sure that everything is setup correctly. We can run this with

% curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash

If there is anything missing, that script will tell you the command you need to run. It will say there are no versions of ruby installed, so lets take care of that.

 % rbenv install 2.3.1
 % rbenv rehash
 % rbenv global 2.3.1
 % ruby -v

The first command will install Ruby version 2.3.1 (replace this with whichever version is most recent) and then next two will tell rbenv to use the version of Ruby you just installed as the global Ruby version. If all goes according to plan, the output from ruby -v should be 2.3.1.

Install Rails and Bundler

Rails and bundler are the two gems you will need to get a basic app up and running, so you want to install them now.

% gem install rails -V --no-ri --no-rdoc
% gem install bundler -V --no-ri --no-rdoc

The -V flag is verbose output, --no-ri and --no-rdoc prevent any documentation from being downloaded so that the gem takes up as little space on disk as possible.

Okay! I think that is everything for getting the server prepped for our Rails application. Next we are going to go through the configuration steps for getting a Rails app deployed using Capistrano.