The Ultimate Guide to Configuring a Rails App on Amazon EC2 with Chef: Part 2

  • 14034 views
  • 9 min
  • Jun 06, 2018
Yaroslav B.

Yaroslav B.

Ruby/JS Developer

Daryna P.

Daryna P.

Copywriter

Dmytro H.

Dmytro H.

Backend Development Lead

Share

This is the second part of our in-depth guide devoted to configuring Rails app on Amazon EC2 with Chef. In the previous part, you’ve learned the basic concepts of Infrastructure as Code and main components of the Chef repository. You’ve also started to describe the basic configuration for your server such as configurations for data bags and environment.

In this part, we show you how to write your own cookbooks. Besides, we explain the wrapper-cookbook notion using scripts for installing and configuring the PostgreSQL database and other software necessary for the correct operation of server and the application on it. Here we go.

Base setup

We’ll start with the basic components:

  • Hostname
  • Project attributes
  • Users groups
  • Sudo privilege

Hostname

This site cookbook will set the hostname for our server. To do this, use the ready cookbook chef_hostname.

Then, write a wrapper cookbook for this task.

Wrapper cookbooks

Put simply, a wrapper cookbook is the simplest type of cookbook; it includes recipes from other cookbooks and defines default attributes.

A wrapper cookbook is structured as follows:

Let’s specify the dependency on the chef_hostname cookbook in the Berksfile.

Next, create a directory with the cookbook.

Describe the additional information about the cookbook in metadata.rb. Here you should define the name, version, and dependencies of the cookbook on other cookbooks. You can also add information about the author and so on. You can find more information about metadata in the Chef documentation.

Now create a default recipe for the cookbook.

This recipe sets the hostname of our server to the name of the node.

Project attributes

We need to create the cookbook that will contain project-specific attributes for the current project. These attributes often used while writing other cookbooks: the name of the project, the repository where the project is, and so on.

Let’s create default attributes for the cookbook.

Then we’ll define the attributes in which the project name and a link to the Github repository will be stored.

In this tutorial, we’ll be using the ready-made Spree app.

These attributes will be accessible through the node object such as node ['project'] ['name'].

Users and groups

We need to create users and groups such as deployer. To do this, we’ll employ the users cookbook.

Add dependencies for the users cookbook in the Berksfile.

Then create a directory for the сookbook:

and set the following metadata:

Next, create a directory with the system attributes for the cookbook.

This file describes the information needed for the system users of the project. System users are users who install and configure processes for certain software. We recommend connecting the distinct user for each installed software to minimize damage in case you detect vulnerabilities in a certain package or if a malefactor gets access rights of the owner of this package.

Now create a recipe.

Describe the installation of system groups and users in this recipe:

After that, describe the behavior for creating groups and users from data bags:

Finally, aggregate all the described recipes into the single recipe that will be launched by default for this cookbook.

Sudo privilege

Now we’ll install sudo on our machine. To do this, use the sudo cookbook.

Add the following dependency to the Berksfile:

Create a cookbook and set the metadata for it.

We want all users whose group box contains the sudo value as well as the groups containing wheel and sysadmin groups in their group box to have sudo privileges.

Let’s create a default recipe for the cookbook.

Then specify the following:

Once we’ve described the basic cookbooks, we’ll create a role called setup that aggregates these cookbooks.

In this role, write basic information such as the name and description. Then, install cookbooks from the current setup role in the run list.

Next, specify this role in the node of your YOUR_IP_ADDRESS.json server.

Database setup

At this point, we’ll describe the configurations for installing and configuring the database and its components on the server. We recommend using PostgreSQL as the main database.

PostgreSQL database

To install and configure PostgreSQL on the server, use postgresql_lwrp. Also, use the locale cookbook to determine the default system locale.

Here are step-by-step instructions:

  1. Initialize the main database cluster for PostgreSQL version 9.6.
  2. Create a PostgreSQL superuser (deployer) and a postgresql user for your project.
  3. Create a PostgreSQL database for the project.

Now let’s add the necessary dependencies in the Berksfile.

Finally, create a cookbook.

To make it more convenient to support this setup in future, set the following attributes in app-attributes:

  1. Default locales
  2. PostgreSQL version
  3. PostgreSQL users
  4. PostgreSQL databases

The PostgreSQL hash function has the signature format $password$username. For example, if the username was deployer and the password was spree-app, then the command to generate the password would look like this:

On Linux:

On macOS:

Replace the the stubbed value ‒ PASSWORD ‒ for each user with the result of this command.

Next, describe metadata cookbooks.

Define the default attributes for the cookbooks.

Before you determine the behavior for the tasks described above, create a default recipe and connect the dependencies at the beginning of the file. You also need to define variables with which you’ll work in the default recipe.

1. Initialize the main database cluster for PostgreSQL version 9.6.

Define the configurations for the client’s authentication for the main cluster called as pg_hba.

Now, initialize the main cluster.

2. Create a PostgreSQL superuser named deployer and also a PostgreSQL user for the project.

Let’s use the variables described above to create a PostgreSQL user and a PostgreSQL database with the user’s name:

3. Create a PostgreSQL database for the project by applying the variables listed above.

Then put the cookbook you’ve created into the database role:

Define the necessary information about the role in roles/database.rb.

Finally, add this role to run_list in nodes/YOUR_IP_ADDRESS.json.

Web setup

Let’s proceed to configuring the software necessary for the correct operation of the web component of the application. To do this, you’ll need to install:

  • Ruby
  • Node.js
  • Imagemagick
  • Redis
  • Nginx

Installing Ruby

To install Ruby, you need the chef_rvm cookbook.

Add the necessary dependencies in the Berksfile.

After that, put the attributes such as versions (all versions you need to install) and default (the default version) in site-cookbooks/app-attributes/attributes/default.rb.

Now create a cookbook.

Then set the metadata for the cookbook.

To install rvm, you need to add a gpg2 key. To do this, create a recipe that will add a gpg2 key to your machine. You can read more information about gpg2 keys here.

Now create a recipe for installing Ruby.

Describe the installation of all necessary versions of Ruby in this recipe.

Next, create a default cookbook for the recipe.

In this cookbook, you need to aggregate the created recipes in the required order.

Install Node.js

We’ll use Node.js as the environment for JavaScript runtime execution. Node.js allows you to use Coffeescript and the asset pipeline in your Rails application, which combines and minimizes your JavaScript to ensure a faster production environment. To install the node from the official prebuilt binaries, use nodejs.

Add dependencies in the Berksfile.

Next, put the version (version of Node.js) and checksum attributes in site-cookbooks/app-attributes/attributes/default.rb.

Now create a cookbook.

Then set the cookbook metadata.

Create default attributes for the cookbook.

Next, you need to specify that you’ll use the binary installation method.

Create a default recipe for the cookbook.

Connect an external cookbook for installation of Node.js.

Installing ImageMagick

Use carrierwave to process downloaded files and perform image operations on the server side. Carrierwave hinges on mini_magick, which in turn is based on ImageMagick. Therefore, you should install ImageMagick. Use the imagemagick cookbook to do this.

Add dependencies in the Berksfile.

Create a cookbook.

Set the metadata for the cookbook.

Create a default recipe for the cookbook.

Then describe the installation of the cookbook.

Installing Redis

You need to apply Sidekiq for background processing for Ruby. Sidekiq uses Redis as a repository. To install Redis, use the chef-redis cookbook.

Add dependencies in the Berksfile.

Create a cookbook.

Set the metadata for the cookbook.

Create default attributes for the cookbook.

Then set the maxmemory for Redis.

Create a default recipe for the cookbook.

Connect an external cookbook to install Redis.

Installing Nginx

We’ll use Nginx as the web server for the application. To install Nginx, use the nginx cookbook.

First, add dependencies in the Berksfile.

Before you start to install and configure Nginx, create a system user. Later, this system user will be tied to Nginx. To create a user, add the following code to the attributes of system users:

Next, include this user in the recipe for installing system users.

Then create a cookbook.

Set the metadata for the cookbook.

After that, put the version (version of Nginx) and checksum attributes in site-cookbooks/app-attributes/attributes/default.rb.

Create default attributes for the cookbook.

Set attributes for Nginx:

We’ll buffer all requests and responses between the client and the Rails application through Puma. To do this, set the path to puma.sock, which will be located in the project directory. Since the path to the project is necessary for the deployment and other components depending on the deployment, we’ll create default attributes for the app-deploy cookbook for future use. We’ll describe the app-deploy cookbook later.

Set the metadata for the app-deploy cookbook.

You also need to create the default attributes.

In the default cookbooks, describe the basic information about the project deployment including the username and group on whose behalf you’ll be deploying. You also need to describe the path to the directory in which you’ll put the app.

After that, add this cookbook to the dependencies.

Now you can start creating a default recipe for the cookbook.

Connect an external cookbook and describe the installation of Nginx.

We recommend putting the Nginx configuration into a separate template that’s tied to a specific environment. In our case, this is dev.erb.

Create the templates directory and the Nginx configuration file for the environment.

Then write the configurations.

We recommend learning how to configure Nginx here.

Now you can collect all these recipes in a role called web for future use in the node of the server.

Next, describe basic information about the role and its run list.

Then add this role to the run_list of the nodes/YOUR_IP_ADDRESS.json node.

Now you already know how to write your own cookbooks. In the next part of our guide, we’ll end writing the cookbooks with configurations for the server security and for monitoring server processes. We’ll apply all configurations written earlier to deploy the Spree application on Ruby on Rails to the previously set up EC2.

Check out the third part of our tutorial.

CONTENTS

Authors:

Yaroslav B.

Yaroslav B.

Ruby/JS Developer

Daryna P.

Daryna P.

Copywriter

Dmytro H.

Dmytro H.

Backend Development Lead

Be the first user to rate this article!

Nay
So-so
Not bad
Good
Wow
0 rating, average 0 out of 5

Share article with

Comments (0)

There are no comments yet

Leave a comment

Subscribe via email and know it all first!