Comprehensive Ansible-Based Rails Deployment with AWS EC2
Comprehensive Ansible-Based Rails Deployment Tutorial with AWS EC2

A step-by-step guide for deploying a Rails application using Ansible, Docker, Nginx, and AWS EC2.

Project Overview

This guide covers deploying a Ruby on Rails application using Ansible, Docker, Docker Compose, and Nginx. We will automate the setup using Ansible playbooks, configure Docker and Docker Compose for Rails, and set up Nginx as a reverse proxy on an AWS EC2 instance.

AWS EC2 Setup

Step 1: Launch an EC2 Instance

Follow these steps to set up an EC2 instance on AWS:

  • Log in to the AWS Management Console.
  • Navigate to the EC2 Dashboard and click on “Launch Instance.”
  • Select an Amazon Machine Image (AMI), such as “Ubuntu Server 20.04 LTS.”
  • Choose an instance type (e.g., t2.micro for testing purposes).
  • Configure the instance’s security group to allow SSH (port 22) and HTTP (port 80) access.
  • Launch the instance and download the .pem key file for SSH access.

Step 2: Configure Security Group

Ensure that the EC2 instance’s security group has the following rules:

Type Protocol Port Range Source
SSH TCP 22 0.0.0.0/0 (or restrict to your IP for security)
HTTP TCP 80 0.0.0.0/0

Step 3: SSH into EC2 Instance

Once the instance is running, SSH into it using the downloaded .pem key:

# Replace "your-key.pem" and "ec2-user@your-ec2-ip" with your key and instance IP
$ ssh -i "your-key.pem" ubuntu@your-ec2-ip

Environment Setup

Step 1: Install Ansible on Local Machine

First, install Ansible on your local machine. This allows you to run playbooks that automate deployment tasks on the remote server.

# Update package lists
$ sudo apt update

# Install Ansible
$ sudo apt install ansible -y

For more information, visit the Ansible Installation Guide.

Step 2: Configure SSH Access

Ensure you have SSH access to the target server. Generate an SSH key and copy it to the server:

# Generate SSH key (if not already created)
$ ssh-keygen -t rsa -b 4096

# Copy SSH key to the server
$ ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@your_server_ip

Setting Up Inventory and Group Variables

Inventory File

Create an inventory file that lists your servers under the [rails_servers] group:

[rails_servers]
your_ec2_ip ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/your-key.pem

Group Variables

Create a file named group_vars/rails_servers.yml to define server-specific settings:

# Git repository details
git_repo_url: "https://your-username:your-password@github.com/your-username/your-repo.git"

# Application directory
app_directory: "/home/ubuntu/current"

# Database credentials
db_username: "postgres"
db_password: "secure_password"

# Server configuration
server_name: "your-server-name-or-ip"

Roles and Playbooks

Playbook Structure

Set up the directory structure for your Ansible project:

ansible_project/
├── group_vars/
│   └── rails_servers.yml
├── inventory
├── rails_deploy.yml
├── roles/
    ├── deploy_rails_app/
    │   └── tasks/
    │       └── main.yml
    ├── setup_docker/
    │   └── tasks/
    │       └── main.yml
    └── setup_docker_compose/
        └── tasks/
            └── main.yml

Docker and Docker Compose Setup

Dockerfile for Rails Application

Create a Dockerfile in your Rails application directory to build a container image for the Rails app.

# Use an official Ruby runtime as a parent image
FROM ruby:3.2

# Set working directory in the container
WORKDIR /app

# Install dependencies
RUN apt-get update -qq && apt-get install -y \
  nodejs \
  npm

# Install Yarn for JavaScript dependencies
RUN npm install --global yarn

# Copy Gemfile and install gems
COPY Gemfile* ./
RUN bundle install

# Copy the rest of the application code
COPY . .

# Install JavaScript dependencies
RUN yarn install

# Expose port 3000 for the Rails app
EXPOSE 3000

# Default command to run Rails
CMD ["bin/dev"]

docker-compose.yml Configuration

Create a docker-compose.yml file to manage the Rails and Nginx services.

version: '3'

services:
  web:
    build: .
    command: bin/dev
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
    environment:
      - DATABASE_USERNAME=postgres
      - DATABASE_PASSWORD=secure_password

  db:
    image: postgres:13
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: secure_password
    volumes:
      - postgres_data:/var/lib/postgresql/data

  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - web

volumes:
  postgres_data:

Nginx Configuration

Create an nginx.conf file to configure Nginx as a reverse proxy:

worker_processes 1;

events { worker_connections 1024; }

http {
    server {
        listen 80;

        location / {
            proxy_pass http://web:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

Executing the Playbook

Run the playbook to deploy the Rails application to your EC2 instance:

$ ansible-playbook rails_deploy.yml -i inventory

Command Table with Detailed Explanations

Command Description
ansible-inventory --list -i inventory List all hosts in the inventory file to verify setup.
ansible all -m ping -i inventory Ping all servers in the inventory to test connectivity.
ansible-playbook rails_deploy.yml -i inventory Run the deployment playbook on all specified servers.
docker-compose up -d Run Docker Compose to start services in detached mode.
docker ps List all active Docker containers to verify deployment.

Common Questions & Answers

Why use Ansible roles?

Ansible roles allow you to organize tasks, variables, and templates into modular, reusable components, making it easier to manage and maintain your playbooks.

How do I securely manage sensitive data?

Use ansible-vault to encrypt files containing sensitive information, such as passwords or API keys, to keep them secure.

Best Practices

  • Use ansible-vault for sensitive data.
  • Keep your Dockerfiles and Ansible roles modular.
  • Use environment variables for configuration flexibility.
  • Test with --check flag to ensure safety before deploying.

© 2024 Your Name or Company

Scroll to Top