Multi stage environments for your Rails apps with Ansible
Here we'll tackle how to setup multi stage environments for your rails apps using Ansible and Capistrano.
We are gonna use this playbook to achieve it.
Provision your servers with Ansible
- Create a new server instance using Ubuntu 14.04 LTS on your favorite hosting provider (Linode, Digital Ocean, etc).
-
Create an SSH alias for your brand new server IP on your
~/.ssh/config
file.Host my-host-alias Hostname 192.0.2.0 User root IdentityFile ~/.ssh/id_rsa
Replace
my-host-alias
with the alias you'd like to use and192.0.2.0
with your server's IP. -
Add your SSH keys to the server.
$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@my-host-alias
-
Install Ansible on your local machine. If you are a mac user you might wanna use brew to do so.
$ brew install ansible
-
Clone my ansible-rails repo <3
$ git clone git@github.com:rebagliatte/ansible-rails-app.git $ cd ansible-rails-app
-
Copy the variable and inventory files for staging and production to the right locations and update them with your own settings.
$ cp -a docs/group_vars/. group_vars $ cp -a docs/inventories/. .
-
Make sure Ansible can access staging properly.
$ ansible -i staging -u root all -m ping
-
Run the playbook on staging.
$ ansible-playbook -i staging site.yml -t ruby,user,postgresql,nginx
The
-i
modifier specifies the inventory file you'll use. Possible values arestaging
andproduction
for this repo.
The-t
modifier specifies the tags you'll execute and their order. -
Your staging server is all set!!! Once you are ready you can run this over your production servers as well.
$ ansible-playbook -i production site.yml -t ruby,user,postgresql,nginx
Deploy your app with Capistrano
-
Create an app.
$ rails new my-app
-
Add the rails capistrano gems to your application's Gemfile.
gem 'puma' group :development do gem 'capistrano', '~> 3.1.0', require: false gem 'capistrano-bundler', '1.1.1', require: false gem 'capistrano-rails', '1.1.0', require: false gem 'capistrano3-puma', require: false end
-
Install the gems and capify the project.
$ bundle install $ bundle exec cap install
-
Alter your
Capfile
to require all the gems you just installed.# Load DSL and Setup Up Stages require 'capistrano/setup' # Includes default deployment tasks require 'capistrano/deploy' # Includes rails goodies require 'capistrano/bundler' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' require 'capistrano/puma'
-
Alter your
config/deploy.rb
.# config valid only for Capistrano 3.1 lock '3.2.1' set :application, 'my-app' set :repo_url, 'git@github.com:my-github-user/my-app.git' # Ask for a branch, default one 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, '/home/deploy/apps/my-app' # Default value for :log_level is :debug set :log_level, :info # Default value for :linked_files is [] set :linked_files, %w{config/database.yml} # Default value for linked_dirs is [] set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system} # Set ssh user set :user, 'deploy' set :ssh_options, { user: fetch(:user) } # For capistrano-puma set :puma_init_active_record, true # For capistrano-bundler set :bundle_path, -> { shared_path.join('vendor','bundle') } set :bundle_flags, '--deployment'
Make sure to replace
my-github-user
andmy-app
with your own settings. -
Alter
deploy/staging.rb
.application_master = '192.0.2.0' role :app, application_master role :web, application_master role :db, application_master set :rails_env, 'staging' set :host, 'my-app.com' set :keep_releases, 2
Replace
192.0.2.0
andmy-app.com
with your server's IP and host, and change:rails_env
to match the file you are altering.Do the same for your
deploy/production.rb
file. Create a
config/environments/staging.rb
file based onconfig/environments/production.rb
if you don't have one already in place.-
Make sure your
database.yml
has its staging and production environments in place and the credentials match the ones you specified on your Ansible variables.development: &default adapter: postgresql pool: 5 timeout: 5000 host: localhost encoding: unicode database: test: <<: *default database: min_messages: warning production: <<: *default database: username: password: staging: <<: *default database: username: password:
-
Copy this file to your servers.
$ scp config/database.yml deploy@my-host-alias:/home/deploy/apps/my-app/shared/config/database.yml
-
Let your servers access your repo by adding deploy keys for each one of them.
ssh deploy@my-host-alias ssh-keygen -t rsa cat ~/.ssh/id_rsa.pub
Copy your newly generated deploy keys (the output of the last command) and add them as deploy keys on your Github repo.
-
Deploy staging
$ cap staging deploy
All set!!! Once you are ready you can deploy production as well with
cap production deploy
.