Chapter 15. Custom Deployment

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.

Virtual Private Servers

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).

Note

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.

Amazon AWS Setup

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.

Ubuntu Linux Setup

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.

Installing Ruby

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.

Installing Apache and Passenger

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.

Installing PostgreSQL

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.

Installing Build Tools

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.

Installing Gems

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

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.

Getting Started

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.

Configuration

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.

Database Setup

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: unicodedatabase: social_production
    pool: 5username: ubuntupassword:

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.

Secrets Setup

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.

Add to Git

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.

Deployment

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.

Adding a Virtual Host

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_nameDocumentRoot /var/www/social/current/publicSetEnv 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.

Summary

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!

Exercises

Q:

1. Make a small change to your application, such as updating the title of each page. Commit the change to your local Git repository, push the changes to GitHub, and then deploy the change to your instance.

Q:

2. Learn about other gems you can use to add features to your Rails applications easily. For example, you might want to allow users to upload images to your site instead of using a third-party image-hosting service. Hundreds of open source projects are available for adding this and other features to your application. Find one you like and try it out. If you find a bug, fix it and send the developer a pull request on GitHub.

Q:

3. Get to know the Ruby on Rails community and get involved. Follow Rails development on GitHub. Check out the official Ruby on Rails website and blog. Find out about Ruby and Rails conferences and try to attend; make yourself known at your local Ruby or Rails User Group.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.76.138