Moving your finished application into production and making it available to users requires you to make many choices. You can choose from a variety of web hosting providers, Rails application servers, databases, and automated deployment systems. In Chapter 6, you learned about Heroku, a hosting service that uses Git for deployment.
Most large companies have an operations team to configure servers and deploy applications. But as a beginning Rails programmer, you may not have the luxury of a dedicated operations team to deploy your application.
In this chapter, you’ll set up a server to host your application, configure your application’s production environment, push your application to GitHub, and finally deploy to your server using Capistrano.
A virtual private server (VPS) is a type of virtual machine sold by web hosting providers. A single physical server can run many virtual private servers. An individual VPS is often referred to as an instance.
When you buy a VPS, you get part of the processing power, memory, and disk space of a larger physical server. You get you full access to your part of the server, including the ability to choose your operating system. So you are free to install the software you need and configure the server however you like. Unfortunately, you are also responsible for any installation and configuration errors on the server.
Many different hosting providers offer VPS services. A quick Google search leads to hundreds of competing providers. A popular choice among both startups and established companies is Amazon Web Services (AWS).
The rest of this chapter uses AWS to set up a server and deploy your application, but the instructions are not AWS specific. If you would rather use a different service, create an instance running Ubuntu Linux 14.04 LTS, and you should be able to follow along with no problem. Ubuntu Linux 14.04 LTS is a long-term support release with guaranteed support until April 2019.
In addition to being a popular choice, Amazon also provides an AWS free usage tier for new users. You can read more about the free usage tier at http://aws.amazon.com/free/ to see if you qualify. Even if you don’t qualify for the free usage tier, you can still get an AWS Micro instance for a few cents an hour.
Amazon calls their VPS service Amazon Elastic Compute Cloud (Amazon EC2). Rather than cover the details of setting up your Amazon account here, please refer to the Amazon EC2 documentation at http://aws.amazon.com/documentation/ec2/.
Click the User Guide link, and follow the instructions, starting with Setting Up. This section walks you through the process of signing up for AWS, creating a user account in the AWS Identity and Access Management (IAM) system, creating a key pair, and creating a security group. Be sure you store your IAM credentials and private key—you’ll need them for this chapter.
Then move on to Getting Started. In this section, you should launch an EC2 instance, connect to your instance, add a storage volume, and finally clean up your instance and volume. The EC2 user guide uses an Amazon Linux machine image that we won’t be using again, so be sure to follow the clean-up instructions in the User Guide when you’re done with this section.
Once you’re up to speed on Amazon EC2, you can set up your production server as described in this section. I recommend Ubuntu Linux, so the instructions that follow are Ubuntu specific. From the EC2 Management Console, click the Launch Instance button to create a new server instance, and choose the Ubuntu Server 14.04 LTS (PV) Amazon Machine Image in the Quick Start section. Because this is a web server, you need to configure the security group to allow HTTP traffic. Click the Next button in the Launch Instance wizard until you reach Step 6: Configure Security Group. Now click the Add Rule button, select HTTP from the Type drop-down menu, and click the Review and Launch button. Finally, click the Launch button.
Once the instance is running, make note of the public DNS name displayed in the EC2
Management Console, and then connect to the instance with SSH in a terminal window.
Using the following command, replace your_key_file
with the full path to the private key
file you created in the Setting Up section of the EC2 User Guide and your_instance_name
with the public DNS
name of your instance:
$ ssh -i your_key_file ubuntu@your_instance_name Welcome to Ubuntu 14.04 LTS... --snip--
The default user account on the Ubuntu AMI is named ubuntu. So this command connects to the user named ubuntu at your instance.
Once you’re connected, you can configure the instance for hosting Ruby on Rails applications. Enter all of the commands in this section on your instance over the SSH connection.
Ubuntu uses a system called apt-get
for installing software from
online repositories. The first thing you need is Ruby. Unfortunately, the default
repositories often contain an older version of Ruby, but you have a way around
that.
The developers at a hosting company called Brightbox have set up their own Ubuntu repository with the latest version of Ruby and made it available to the public. This repository is known as a Personal Package Archive (PPA). You can add this repository to your instance and get the latest version of Ruby using these commands:
$ sudo apt-get install python-software-properties Reading package lists... Done --snip-- Setting up python-software-properties (0.92.36) ... $ sudo apt-add-repository ppa:brightbox/ruby-ng Next generation Ubuntu packages for Ruby ... --snip-- http://brightbox.com More info: https://launchpad.net/~brightbox/+archive/ruby-ng Press [ENTER] to continue or ctrl-c to cancel adding it
Press ENTER when prompted, and then
wait for the word OK
to appear. After you add the Brightbox
repository, update the apt-get
package lists so it can find the
newer versions of the Ruby packages.
$ sudo apt-get update Ign http://us-east-1.ec2.archive.ubuntu.com trusty ... --snip-- Fetched 13.7 MB in 9s (1,471 kB/s) Reading package lists... Done
Now install Ruby version 2.1. The following command installs both the Ruby interpreter and the development headers needed to compile additional gems:
$ sudo apt-get install ruby2.1 ruby2.1-dev Reading package lists... Done --snip- Do you want to continue? [Y/n]
Press ENTER to continue. Once the installation completes, check the Ruby version.
$ ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux-gnu]
Since Ruby is frequently updated, you’ll probably see a newer version number than the one shown here. Now that Ruby’s installed, you need a web server for Ruby on Rails applications.
A variety of web servers are available today. The most popular web server is Apache, and that’s what we’ll use. Install the Apache HTTP Server version 2 with this command:
$ sudo apt-get install apache2 Reading package lists... Done --snip-- Do you want to continue? [Y/n]
Press ENTER to continue.
Once you’ve completed this, open your web browser and go to the public DNS name of your instance to see the default Ubuntu website. Although you can’t see your application yet, you’re making progress.
Apache is great for serving web pages, but you need an application server to run your Ruby on Rails application. A popular application server that integrates with Apache is Phusion Passenger.
Phusion provides the Passenger application server through its own
apt-get
repository. It’s not a PPA like the Brightbox
repository you used earlier, however, so the setup has a few more steps.
First, enter the apt-key
command to import
Phusion’s RSA key for the Ubuntu key server:
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7 Executing: gpg --ignore-time-conflict ... --snip-- gpg: imported: 1 (RSA: 1)
The apt-get
program uses this key to ensure that packages you
install are really coming from Phusion. Phusion’s repository uses an encrypted
HTTP connection (HTTPS) to communicate with your instance.
First, you need to add the Phusion Passenger repository to your instance. Enter
the following command to open a new file in the nano
editor on your
instance. (Or, if you’re more comfortable with another command-line editor, use
that instead.)
$ sudo nano /etc/apt/sources.list.d/passenger.list
Enter deb
https://oss-binaries.phusionpassenger.com/apt/passenger trusty
main
on the first line to add the address of the Phusion
Passenger repository to your instance. Then, if you’re using
nano
, press CTRL-O followed
by ENTER to save the file and CTRL-X to exit the editor.
Now update the apt-get
package lists again:
$ sudo apt-get update Ign http://us-east-1.ec2.archive.ubuntu.com trusty InRelease --snip-- Reading package lists... Done
Then install the Apache 2 Phusion Passenger module:
$ sudo apt-get install libapache2-mod-passenger Reading package lists... Done --snip-- Do you want to continue? [Y/n]
Press ENTER to continue. Once the installation completes, your instance should be set up to serve both standard web pages and Ruby on Rails applications.
With your web server installed, create a directory for your application. The default directory for regular HTML web pages is /var/www/html. Because you’re deploying a Ruby on Rails application, create a separate directory with these commands.
$ sudo mkdir /var/www/social $ sudo chown ubuntu /var/www/social $ sudo chgrp ubuntu /var/www/social
The first command creates a directory named /var/www/social. The next two commands assign ownership of that directory to your ubuntu user and group, allowing you to write files to that directory as needed.
Now you need to install and set up a database for your application.
This chapter uses the PostgreSQL database, but which database software you choose is mostly up to you. MySQL is another popular, open source option you might consider.
Install PostgreSQL with this command:
$ sudo apt-get install postgresql postgresql-contrib Reading package lists... Done --snip- Do you want to continue? [Y/n]
Press ENTER to continue. Now that the database
software is installed, let’s add a user account and create a few databases. The
default user account for PostgreSQL is named postgres, so you
need to issue the createuser
command as the
postgres
user with the sudo -u postgres
command:
$ sudo -u postgres createuser --superuser ubuntu
This command creates a new user named ubuntu with superuser access to the database. This user has full access to all database commands. PostgreSQL is configured with an authentication system known as ident sameuser, by default, in Ubuntu. This means if your Ubuntu username matches your PostgreSQL username, you can connect without a password.
Now that you’ve created a PostgreSQL account for yourself, add a database and then see if you can connect to it:
$ createdb ubuntu $ psql psql (9.3.4) Type "help" for help. ubuntu=# help You are using psql, the command-line interface to PostgreSQL. Type: copyright for distribution terms h for help with SQL commands ? for help with psql commands g or terminate with semicolon to execute query q to quit ubuntu=#
Your account can now log in to PostgreSQL and run commands. Enter
q
to quit. Now add a
production database for your social application by entering this command:
$ createdb social_production
You won’t need to enter any other PostgreSQL commands on your instance. Now that you’ve created the production database, the migrations in your application create the tables needed by your application. You’ll configure the application to use this database before you deploy to your instance.
Your instance is almost ready to go! Before you can deploy your application, however, you need to install a few more tools. Some of the gems your application uses need to be compiled, and to do so, you need build tools such as a C compiler. You also need Git for retrieving code from repositories and header files for PostgreSQL to compile the PostgreSQL database gem.
Fortunately, this single command should install all of the build tools you need:
$ sudo apt-get install build-essential git libpq-dev Reading package lists... Done --snip-- Do you want to continue? [Y/n]
The build-essential
package is a collection of common build
tools needed to compile many different types of software. You’re already
familiar with Git from Chapter 6. The libpq-dev
package is needed to compile PostgreSQL client applications such as the pg gem.
The last setup step is to install the gems your application needs. As you’ll
learn in the next section, the bundle
command runs automatically
when you deploy, but installing gems while you’re connected to the server helps
to verify everything is working.
Gems normally generate documentation during installation. On the server, this
documentation just takes up space and slows down the installation. You can tell the
gem
command to not generate documentation by adding gem:
--no-document
to your .gemrc file:
$ echo "gem: --no-document" >> ~/.gemrc
Now that you’ve turned off gem documentation, install Rails:
$ sudo gem install rails Fetching: thread_safe-0.3.3.gem (100%) Successfully installed thread_safe-0.3.3 Fetching: minitest-5.3.3.gem (100%) Successfully installed minitest-5.3.3 --snip--
Because you’re using the PostgreSQL database, also install the pg gem. Parts of this gem are written in C, and they’ll be compiled automatically during the installation.
$ sudo gem install pg
Building native extensions. This could take a while...
Successfully installed pg-0.17.1
1 gem installed
Finally, you need a gem called therubyracer. This gem embeds Google’s V8 JavaScript interpreter into Ruby. Rails uses this gem to compile assets on the server. Parts of this gem must also be compiled.
$ sudo gem install therubyracer
Building native extensions. This could take a while...
Successfully installed therubyracer-0.12.1
1 gem installed
With these gems in place, your instance is ready to run Rails applications. Now that the VPS setup is complete, let’s learn about Capistrano and the changes you need to make to your application to deploy and run it in production.
Capistrano is an open source tool for automating the process of running scripts and
deploying applications on remote servers over an SSH connection. Capistrano extends the
rake
tool that you’ve used already. Just like
rake
, Capistrano uses a simple DSL to define
tasks, which are applied to different servers based on their
role.
Tasks include things such as pulling code from a Git repository, running
bundle install
, or running database migrations with
rake
. Roles are different types of servers such as web, application,
or database. Currently, these are all on the same server, but when your application gets
too big for a single server, Capistrano makes splitting the work among multiple servers
easy.
Capistrano also supports deploying an application to different stages. Capistrano stages are sets of servers, such as staging servers and production servers. Both of these servers run your Rails application in the production environment, but the staging server is probably used only for testing, whereas the production server is accessible by your users.
Exit the SSH session on your VPS or open another terminal window on your local computer to set up Capistrano. Because Capistrano is a gem, you first need to update your application’s Gemfile. Capistrano is already in the file, but it’s commented out. Remove the pound sign from the beginning of the line for the capistrano-rails gem to install both Capistrano and the Rails-specific tasks you need.
While you’re editing the Gemfile, also make the changes needed for running in production:
--snip-- # Use sqlite3 as the database for Active Record 1 gem 'sqlite3', group: [:development, :test] --snip-- # See https://github.com/sstephenson/execjs#readme... 2 gem 'therubyracer', platforms: :ruby, group: :production --snip-- # Use Capistrano for deployment 3 gem 'capistrano-rails', group: :development 4 # Use PostgreSQL in production gem 'pg', group: :production # Use debugger gem 'byebug', group: [:development, :test]
These changes first specify that the SQLite gem is only needed in the
development
and test environments ➊. Next, therubyracer gem
is needed to compile assets in production ➋ as mentioned in the last section. The
capistrano-rails gem is only needed in development ➌. Finally, you also need the
PostgreSQL gem in production ➍.
Now update the installed gems on your computer:
$ bin/bundle install --binstubs --without production Fetching gem metadata from https://rubygems.org/........ Fetching additional metadata from https://rubygems.org/.. Resolving dependencies... --snip--
The --binstubs option tells bundler to also install the executable files in the bin/ directory. For example, Capistrano includes the cap command that you’ll use to deploy your application, and you’ll run that from bin/. The --without production option tells bundler to install only gems for the development and test environments.
Next, you need to install Capistrano in your application:
$ bin/cap install
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
Capified
This process generates the files you need to configure Capistrano to deploy your application. Let’s dig into those next.
Now that your application has been Capified, you may notice some new files. The first of these is named Capfile and is located in the root of the application. You need to make one small change to that file:
# Load DSL and Setup Up Stages require 'capistrano/setup' # Includes default deployment tasks require 'capistrano/deploy' ➊ # Include all Rails tasks require 'capistrano/rails' --snip--
As the comment says, the new require
line includes
Capistrano’s Rails-specific tasks in your application ➊. After you save
this file, you can see a list of Capistrano tasks by entering the bin/cap
-T
command in your terminal.
Next, you need to edit the file config/deploy.rb. This file contains configuration that is shared by all deployment stages, such as the name of your application and the address of your Git repository.
# config valid only for Capistrano 3.1 lock '3.2.1' ➊ set :application, 'social' set :repo_url, 'https://github.com/yourname/social.git' # Default branch is :master # ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call # Default deploy_to directory is /var/www/my_app ➋ set :deploy_to, '/var/www/social' --snip-- namespace :deploy do desc 'Restart application' task :restart do on roles(:app), in: :sequence, wait: 5 do # Your restart mechanism here, for example: ➌ execute :touch, release_path.join('tmp/restart.txt') end end after :publishing, :restart --snip-- end
First, set the name of your application to social
and
specify the URL of your Git repository ➊. Replace yourname
with your GitHub username. Next, set the
deploy directory to the /var/www/social
directory that you created on your instance ➋. Finally, uncomment the
execute
line ➌ in the restart
task. This
line executes the touch tmp/restart.txt
command. This command is
needed to restart the Passenger application server after deployment.
Now that the shared settings are updated, edit the config/deploy/
production.rb file. This file contains settings specific to the Capistrano
production
stage. Replace the existing code in this file with the
following code:
server 'your_instance_name', ➊ user: 'ubuntu', roles: %w{web app db} ➋ set :ssh_options, { keys: 'your_key_file ' }
First, Capistrano needs the address of your servers, along with the username and
roles of each server ➊. Your instance is fulfilling all three roles, and the
username is ubuntu
. Replace your_instance_name
with your server’s public
DNS name. Next, specify the SSH options needed to connect to your instance ➋.
Capistrano needs the path to your private key to connect. Replace your_key_file
with the full path to
your private key file.
Next, configure your application to use the PostgreSQL database you created earlier.
Database configuration is in the file config/database.yml. Update
the production
section, as shown here:
--snip-- production: adapter: postgresql encoding: unicode ➊ database: social_production pool: 5 ➋ username: ubuntu ➌ password:
This code tells Rails to use the PostgreSQL database named
social_production
➊ in the production
environment. Rails will connect to the database with the username
ubuntu
➋ and no password ➌, thanks to the
Ubuntu’s ident sameuser authentication setup mentioned earlier.
The last thing you need to set up is the secret key used to sign your application’s cookies. This value is stored in the file config/secrets.yml. This file can also be used to store other secret information such as passwords or API keys needed by your application.
--snip--
development:
secret_key_base: 242ba1d...
test:
secret_key_base: 92d581d...
➊ # Do not keep production secrets in the repository,
# instead read values from the environment.
production:
➋ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
As mentioned in the comment, you shouldn’t keep production secrets in this
file ➊. If the code for your application is stored in a public Git repository,
these secrets would then be publicly available. Instead, this file uses an ERB tag to
read the value of the SECRET_KEY_BASE
environment variable
➋.
Before you can set this environment variable on your server, generate a value using the following command:
$ bin/rake secret
a3467dbd655679241a41d44b8245...
Copy the value output by this command and save it in a safe place. You’ll need it again when you set up the virtual host for your application later in this chapter.
With Capistrano configured and the database configured, you’re ready to create
a Git repository for your application and push your code to GitHub. Capistrano runs
git
commands on your instance to pull changes to your application
from GitHub during deployment.
First create a Git repository on your local computer with the following commands. (Refer back to Chapter 6 if you need a refresher on Git.)
$ git init Initialized empty Git repository in ... $ git add . $ git commit -m "Initial commit" [master (root-commit) 1928798] Initial commit 123 files changed, 1826 insertions(+) --snip--
Now log in to your GitHub account and create a new public repository named social. Once the repository is created, add a remote to the local repository you just created and push the code up to GitHub.
$ git remote add origin https://github.com/yourname/social.git $ git push -u origin master Counting objects: 141, done. --snip-- Branch master set up to track remote branch master from origin.
Once Capistrano is configured and your application is on GitHub, you’re ready to deploy.
First, test the connection to your instance and check if the instance is ready to
receive a deployment from Capistrano. The deploy:check
task ensures
everything on the instance is set up correctly:
$ bin/cap production deploy:check INFO [722a06ac] Running /usr/bin/env ... --snip-- INFO [5d3c6d3e] Finished ... exit status 0 (successful).
Note that I specified the production
stage in the command. You
must include the stage with every Capistrano command.
If the deploy:check
task finishes successfully, you’re
ready to deploy your application for the first time:
$ bin/cap production deploy INFO [e6d54911] Running /usr/bin/env ... --snip-- INFO [3cb59e26] Finished ... exit status 0 (successful).
The deploy task not only checks out the latest code from GitHub but also runs
bundle install
to update installed gems, compiles your
application’s assets, and migrates the database. Even once your application is
installed on your instance and running, however, you still need to make one more
configuration change to see your application on the Internet.
A Virtual Host is a way to host multiple sites on the same server or instance. The Apache web server allows you to set up many different sites on the same physical server. It then uses the DNS name of each site to serve the correct site for each incoming request. You currently have only a single site running on your instance, but you still need to set it up as a Virtual Host.
You perform this step one time. You won’t need to do this again unless you decide to add another site to the same server. You needed to wait until after your application was deployed since the directory names you’re going to specify didn’t exist before.
First, connect to your instance with SSH, and then create a configuration file for the social application in the /etc/apache2/sites-available directory:
$ sudo nano /etc/apache2/sites-available/social.conf
The previous command opens the new file in the nano
editor. Enter
the following Apache configuration code in the new file:
➊ <VirtualHost *:80> ➋ ServerName your_instance_name ➌ DocumentRoot /var/www/social/current/public ➍ SetEnv SECRET_KEY_BASE a3467dbd65... ➎ <Directory /var/www/social/current/public> Allow from all Options -MultiViews </Directory> </VirtualHost>
The first line means this Virtual Host responds to all requests (indicated by the
star) on port 80 ➊. Next, specify the server name of this Virtual Host ➋.
Replace your_instance_name
with the public DNS
name of your instance.
Then set the document root for this Virtual Host ➌. The document root is normally the location of the site’s HTML files, but here, you set it to your application’s public directory. This configuration is specific to the Passenger application server.
The next line sets the SECRET_KEY_BASE
environment variable
➍. Replace the partial key shown here with the complete 128-digit key generated
by the bin/rake secret
command you entered earlier.
Finally, set options for the document root directory ➎. The Allow
from all
line means that all hosts and IP addresses are allowed access to
the files in this directory. The Options -MultiViews
line turns off
the MultiViews feature in Apache. This feature uses automatic content negotiation, which
can cause Apache to serve files to a client even if the file extension is not specified,
which you don’t want.
Press CTRL-O followed by ENTER to save the file, and then press CTRL-X to exit the editor.
Now that the new site is configured in Apache, you need to disable the default site that comes with Apache and enable the social site:
$ sudo a2dissite 000-default Site 000-default disabled. To activate the new configuration, you need to run: service apache2 reload $ sudo a2ensite social Enabling site social. To activate the new configuration, you need to run: service apache2 reload
Once this is done, reload Apache to activate the changes:
$ sudo service apache2 reload
* Reloading web server apache2
*
Now open your web browser and go to the public DNS name of your instance. Your application should be available to the world, running in production on your own virtual private server.
In this chapter, you learned how to set up a Linux server for hosting Rails applications. You installed and configured the Apache web server, the Phusion Passenger application server, and the PostgreSQL database server.
You also learned how to integrate the remote server automation tool Capistrano in your Rails application. You configured your Rails application for production and used Capistrano to deploy it to your instance.
With this done, you are well on your way to becoming a professional Rails developer!
3.16.76.138