Introduction
You’ve written the app, you’ve deployed it on Heroku, and now it’s time to deploy your app for production on a real server. There are a few advantages of a server (dedicated or VPS) over something like Heroku. It mainly boils down to:
- Optimization
- Security
- Flexibility and Customization
- Multi-app hosting
- Lower Cost
Signing Up
First, we need to sign up for DigitalOcean: a VPS service renowned for the speed and simplicity of their VPS instance (known as Droplets) spawning, as well as great features like backups, IPV6, and SSDs in all VPS instances. Sign up for DigitalOcean here!
Creating a Droplet
Let’s create a droplet. I’ve included a list of the specifications for the droplet I’m using, but you can see a screenshot of the settings here.
- Hostname: ruby-on-rails
- Size: $5 512mb / 1 CPU / 20GB SSD / 1TB Transfer
- Region: NY3 (supports backups)
- Image: CentOS 7x64
- Backups: Enabled (adds a small cost, but is more than worth it)
Logging In
The new droplet’s information will be emailed to you. It will include the IP and the server’s root password.
Let’s start by logging in to the droplet via SSH:
$ ssh [email protected]
[email protected]'s password:
Changing password for root.
(current) UNIX password:
New password:
Retype new password:
[root@ruby-on-rails ~]#
When prompted that the authenticity of the host can’t be established, type yes
. On first login, you will be prompted to change your password. Make sure you write it down! It is possible to change it later through DigitalOcean’s dashboard, but it is much easier to simply not forget in the first place!
Installation
Now that we’re logged in, let’s start with the installation of some basic tools we’ll need. I’m not going to go into much detail about these packages, as there are tons of resources on them.
We’ll also be using nginx as our server. Nginx is blazingly fast with very low memory usage. At the same time, it is easy to install and configure.
General Development Tools
We will be installing most of what we need using yum
, the package manager included with CentOS. When yum
asks Is this ok [y/d/N]:
, enter y
.
# yum install epel-release curl-devel httpd-devel
# yum groupinstall 'Development Tools'
nginx
To install nginx, we will be using nginx’s Official CentOS package.
# nano /etc/yum.repos.d/nginx.repo
And enter the following:
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
Then, we can use yum install nginx
which will install from nginx directly. This method is preferred over installation by any other method, including from source (unless necessary, as some features can only be enabled through installing from source).
Great! Nginx is installed. Let’s see if we can talk to it. Start nginx and navigate to your IP address (mine is 104.131.56.255) in the browser. You should see nginx’s welcome page:
# nginx
There is a bit more configuration for us to do, but we’ll come back to nginx later.
RVM
Though many distributions of linux come with Ruby installed, we’re going to do it the right way. This involves using RVM, the Ruby Version Manager.
To install RVM:
# gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
# \curl -sSL https://get.rvm.io | bash -s stable
Then, following the instructions given to us, we will add our user to the rvm
group (do this for all users that will be using RVM:
# usermod -a -G rvm root
And run /etc/profile.d/rvm.sh
:
# source /etc/profile.d/rvm.sh
You should now be able to run the rvm
command. Try the following:
# rvm -v
rvm 1.26.11 (latest)
Any output that isn’t an error is good news! At the time of writing this, my RVM version is 1.26.11.
Ruby
Once RVM is installed, installing a specific version of Ruby is easy! For this tutorial, I’m going to use 2.2.2. If your project requires a different version, replace 2.2.2
with that version.
We can install Ruby version 2.2.2 using RVM:
# rvm install 2.2.2 --no-docs
--no-docs
tells RVM to skip some of the files it would normally download. We don’t need these, and it speeds up our installation. If you’d like, just remove that flag and RVM will install those files as well.
Now go get a coffee. This takes a few minutes!
Once it’s installed, we’ll make sure we’re always using version 2.2.2:
# rvm use 2.2.2
# rvm --default 2.2.2
# ruby -v
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
We’re now up and running with a fresh installation of Ruby 2.2.2.
Rails
Of course, rails installation is simple.
# gem install rails
# rails -v
Rails 4.2.3
Puma
Start by cloning your repository. If you don’t have one, you can make a new one in /var/www/html with rails new
.
# cd /var/www/html
# git clone [email protected]:username/repositoryname.git
Add the following gems to your Gemfile
.
gem 'puma' # rails server
gem 'therubyracer' # javascript interpreter for CentOS
And install
# bundle install
Configuring the Webserver
Now we’ll configure puma and nginx. We’ll need a new nginx configuration, and want to remove the default:
# cd /etc/nginx/conf.d/
# mv default.conf default.bak
# nano rails.conf
And enter the following:
upstream rails {
server localhost:3000; # Puma is running here
}
server {
listen 80 default;
server_name 104.131.56.255; # YOUR IP HERE
location / {
proxy_pass http://rails;
}
}
Restart nginx and run your rails server
as normal. You’ll see that Puma starts with the rails server.
# nginx -s reload
# rails server
=> Booting Puma
=> Rails 4.2.3 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Puma 2.3.2 starting...
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://localhost:3000
Now visit your IP address in your browser. You should see the rails welcome page!
Next Steps
There are a few things left to do before your app is ready for use.
-
Right now, if the server crashes or is rebooted, nginx and puma will not restart. They need to be daemonized. CentOS has a tool for this called
chkconfig
. There are plenty of tutorials out there on how to set these up, and scripts on the nginx documentation site to help with nginx’s daemon. -
You’ll also have to point the DNS for your domain at the server. nginx will check the
server_name
of incoming requests, but if the requests never end up there in the first place, you’ll only ever be able to access the website through the ip. Your domain provider can assist you with this. -
Your app will probably also need SSL. SSL setup with nginx is easy, but you must first obtain a certificate from a certificate signing authority (CSA). Whoever you’ve purchased your domain from can probably help you obtain an SSL certificate.