Overview

We will be setting up a scalable Rails production environment using Ansible on DigitalOcean(or anywhere) which consists following layers

  • Load Balancer
    • Haproxy
  • Application Server(s)
    • Nginx
    • Ruby 2.1
    • Passenger
  • Database Server
    • PostgreSQL

All servers will be running Ubuntu 14.04 x64

Server Setup Schema

This setup will allow us to scale our environment horizontally so we can add more application servers to increase capacity. It can also protect from DDOS attacks by limiting connections.  

Ansible

Ansible is a radically simple IT automation system. It handles configuration-management, application deployment, cloud provisioning, ad-hoc task-execution, and multinode orchestration - including trivializing things like zero downtime rolling updates with load balancers. Read the documentation and more at http://ansible.com/  

What we need?

Components

  • HAProxy, which stands for High Availability Proxy, is a popular open source software TCP/HTTP Load Balancer and proxying solution which can be run on Linux, Solaris, and FreeBSD. Its most common use is to improve the performance and reliability of a server environment by distributing the workload across multiple servers (e.g. web, application, database). It is used in many high-profile environments, including: GitHub, Imgur, Instagram, and Twitter.[1]
  • Nginx is a very high performant web server / (reverse)-proxy. It has reached its popularity due to being light weight, relatively easy to work with and easy to extend (with add-ons / plug-ins). Thanks to its architecture, it is capable of handling a lot of requests (virtually unlimited), which - depending on your application or website load - could be really hard to tackle using some other, older alternatives.[2]
  • Passenger today has become the recommended server for Ruby on Rails applications. It is a mature, feature rich product which aims to cover necessary needs and areas of application deployment whilst greatly simplifying the set-up and getting-started procedures. It eliminates the traditional middleman server set up architecture by direct integration with Nginx (and Apache as well). It is also referred to as mod_rails.[2]

Creating Servers

Before creating the servers we have to add our SSH key to DigitalOcean. In this way our key will be added to authorized_keys automatically after the servers are created. To do this, go to your command line and type “cat ~/.ssh/id_rsa.pub” it will output your SSH key.

$ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCmKlx9a9LKeiipeyEtwYC/Kk3XiU8HgXOJsNtOCm9xdzSo7/3keT051eiD5CynsvjOGpFKiVf8IMuLzhl7kR3ghrRVsWvPCjQaYtzF3BTkHG3yoElnq+k+oQ/pO+KcFlS9z6oGWWGPfTNq7Mx3O+wBOSzeI7XP4O1eCAeRumu1IsZmMoYWS+VwxcUFD0AX6xNgxzE9AkZRnTVOfWDn9inMpBwYeWjlwfy3ODCha/gwmytah18j2YBrZlGI6C9cKlt/9/VN6yvTV4BVBhU1eD9i7WlIAFxubhM4a3lnT8Io0WNyJg5NEmzLxwK19qNVYGlDfdB6v0pLWVz8WwzNhljp mehmet@asus

Copy this key and go to SSH Keys on DigitalOcean, click to Add SSH Key button on top right of the screen. Paste it to Public SSH Key field, type a name whatever you want to.  All you have to do is select this key while creating a server. You can see Add SSH Keys section on the bottom of the screen. add-ssh-keys

Now create 4 servers with Ubuntu 14.04 x64 and any size you want. I’m going to create 4 smallest droplets(512MB) and name them as following;

  • loadbalancer
  • app1
  • app2
  • db

Playbook Configuration

Get the playbook if you haven’t yet. There are two playbooks in this repo. One is bootstrap.yml which handles basic bootstrapping of the servers like adding a sudo user, adding the public keys. Other one is cluster.yml, it installs and configures all of our environment.

1. Inventory Configuration

Open _hosts.example file with your favorite text editor. Change the IP address of servers from 0.0.0.0 to IPs of your DigitalOcean droplets.

2. Bootstrap Playbook Configuration

Open vars/bootstrap.yml and change the username field to anything you want. It will be our sudo user. Change the admin group if you wish.

3. Ping Hosts

Check your inventory configuration, you should see success messages;

$ ansible -m ping -i hosts.example all

0.0.0.0 | success >> { "changed": false, "ping": "pong" }
0.0.0.0 | success >> { "changed": false, "ping": "pong" }
0.0.0.0 | success >> { "changed": false, "ping": "pong" }

4. Run Bootstrap Playbook 

To run bootstrap.yml playbook go to command line and do the followings. We will run this playbook as root because we don’t have sudo user yet.

$ ansible-playbook bootstrap.yml -i hosts.example -u root

5. Common Variables Configuration

Open vars/common.yml. Change the variables as you wish.

6. Run Cluster Playbook

We will run this playbook as sudo user. In my case, my sysadmin username is “mehmet”. Run the following command to setup all of our servers;

$ ansible-playbook cluster.yml -i hosts.example -u mehmet

Conclusion

After all of these steps, now you have a scalable rails production environment. You can scale your app by adding more app servers. All you have to is add your new servers in hosts file under appservers group and run bootstrap and cluster playbooks again. It will configure your new servers, loadbalancer and database server.  If you have any questions feel free to drop a comment. 

References

  1. An Introduction to HAProxy and Load Balancing Concepts

2. How To Deploy Rails Apps Using Unicorn And Nginx on CentOS 6.5