Skip to content

Instantly share code, notes, and snippets.

@caalberts
Last active December 31, 2023 21:04
Show Gist options
  • Save caalberts/99ed3e33385ee2b3bff0f881452079cd to your computer and use it in GitHub Desktop.
Save caalberts/99ed3e33385ee2b3bff0f881452079cd to your computer and use it in GitHub Desktop.
Ansible Playbook to Deploy Rails to AWS
---
# Deploy rails app from localhost to remote servers
- name: Set up AWS infrastructure
hosts: localhost
connection: local
roles:
- setup_aws
- name: Package app
hosts: localhost
vars:
root_dir: ..
roles:
- package_app
- name: Install ruby & nginx
hosts: web
gather_facts: yes
roles:
- install_ruby
- role: install_nginx
become: yes
- name: Boot application
hosts: web
serial: 1
gather_facts: yes
roles:
- role: webserver
environment:
RAILS_HOST: "{{ RAILS_HOST }}"
SECRET_KEY_BASE: "{{ SECRET_KEY_BASE }}"
DB_NAME: "{{ DB_NAME }}"
DB_USERNAME: "{{ DB_USERNAME }}"
DB_PASSWORD: "{{ DB_PASSWORD }}"
DB_HOST: "{{ hostvars.localhost.rds.instance.endpoint }}"
- name: Setup load balancing
hosts: localhost
roles:
- role: setup_elb
---
# Install nginx on EC2 and copy configuration
# Place nginx.conf in ../files/nginx.conf
- name: install nginx
yum: name=nginx state=present
# check for the existence of nginx.conf
- name: stat nginx.conf
stat: path=/etc/nginx/nginx.conf
register: nginx_conf_stat
- name: Move nginx.conf to nginx.conf.backup
command: mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
when: nginx_conf_stat.stat.exists
- name: copy nginx.conf
copy: src=nginx.conf dest=/etc/nginx/nginx.conf
- name: stat /etc/nginx/servers
stat: path=/etc/nginx/servers
register: servers_stat
- name: Assures /etc/nginx/servers dir exists
file: path=/etc/nginx/servers state=directory
---
# Role to install ruby and node using rvm on EC2
---
- name: Update yum
shell: bash -lc 'sudo yum -y update'
- name: Update gpg
shell: bash -lc 'gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3'
- name: Download rvm
shell: bash -lc '\curl -sSL https://get.rvm.io | bash -s stable'
- name: Install ruby 2.3.0
shell: bash -lc 'source /home/ec2-user/.rvm/scripts/rvm && rvm install 2.3.0'
- name: Install bundler
shell: bash -lc 'gem install bundler'
- name: Install postgres client
become: yes
yum: name=postgresql-devel state=present
- name: Download nodejs
become: yes
shell: bash -lc 'curl -sSL https://rpm.nodesource.com/setup_4.x | bash - && yum -y install nodejs'
---
# Role to package rails app for production
- name: Bundle install
command: bin/bundle install --local
args:
chdir: "{{root_dir}}"
- name: Precompile assets
command: bin/rake assets:precompile
args:
chdir: "{{root_dir}}"
- name: Package into a tar
command: tar zcf /tmp/app_name.tgz .
args:
chdir: "{{root_dir}}"
---
# Set up AWS infrastructure
- name: Gather VPC facts
ec2_vpc_subnet_facts:
region: "{{ aws_region }}"
register: vpc_facts
- name: Create EC2 security groups
ec2_group:
name: AppServer
description: SSH, rails, 8080
region: "{{ aws_region }}"
vpc_id: "{{ vpc_facts.subnets[0].vpc_id }}"
state: present
rules:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: 0.0.0.0/0
register: AppServerGroup
- name: Create RDS security group
ec2_group:
name: RDS
description: PostgreSQL
region: "{{ aws_region }}"
vpc_id: "{{ vpc_facts.subnets[0].vpc_id }}"
state: present
rules:
- proto: tcp
from_port: 5432
to_port: 5432
cidr_ip: 172.0.0.0/8
register: RDSGroup
- name: Enforce EC2 instances
ec2:
key_name: "{{ key_name }}"
instance_type: "{{ ec2_instance_type }}"
image: "{{ ec2_image }}"
group_id: "{{ AppServerGroup.group_id }}"
region: "{{ aws_region }}"
vpc_subnet_id: "{{ item.id }}"
instance_tags:
zone: "{{ item.availability_zone }}"
wait: yes
assign_public_ip: yes
exact_count: 1
count_tag:
zone: "{{ item.availability_zone }}"
with_items: "{{ vpc_facts.subnets }}"
- name: Get EC2 facts
ec2_remote_facts:
region: "{{ aws_region }}"
filters:
instance-state-name: running
register: ec2_facts
- name: Add IP to ec2_hosts group
add_host: hostname={{ item.public_dns_name }} groups=web
with_items: "{{ ec2_facts.instances }}"
- name: Create EC2 LB
ec2_elb_lb:
name: "{{ elb_name }}"
region: "{{ aws_region }}"
zones: "{{ aws_zone }}"
state: present
security_group_ids: "{{ AppServerGroup.group_id }}"
health_check:
ping_protocol: http
ping_port: 80
ping_path: "/ping"
response_timeout: 5
interval: 30
unhealthy_threshold: 2
healthy_threshold: 2
listeners:
- protocol: http
load_balancer_port: 80
instance_port: 80
proxy_protocol: true
register: elb
- name: Create PostgreSQL on RDS
rds:
command: create
instance_name: "{{ DB_NAME }}"
region: "{{ aws_region }}"
vpc_security_groups: "{{ RDSGroup.group_id }}"
db_engine: postgres
size: 5
instance_type: db.t2.micro
db_name: "{{ DB_NAME }}"
username: "{{ DB_USERNAME }}"
password: "{{ DB_PASSWORD }}"
wait: yes
wait_timeout: 1000
register: rds
- name: Add RDS endpoint to db group
add_host: hostname={{ rds.instance.endpoint }} groups=db
---
# Register EC2 to loadbalancer
- name: Get EC2 facts
ec2_remote_facts:
region: "{{ aws_region }}"
register: ec2_facts
- name: Add EC2 instances to ELB
ec2_elb:
ec2_elbs: "{{ elb_name }}"
region: "{{ aws_region }}"
instance_id: "{{ item.id }}"
state: present
with_items: "{{ ec2_facts.instances }}"
---
# Start rails server
- name: Stop running server
shell: bash -lc '(cat /home/ec2-user/app_name/tmp/unicorn.pid | xargs kill) || true'
- name: Clean directory
become: yes
file: path=/home/ec2-user/app_name state=absent
- name: Ensure directory exists
file: path=/home/ec2-user/app_name state=directory
- name: Copy and unpack app
unarchive: src=/tmp/app_name.tgz dest=/home/ec2-user/app_name
- name: Boot app in '{{rails_env}}'
shell: bash -lc 'rails server -e {{rails_env}}'
args:
chdir: /home/ec2-user/app_name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment