I've been using Heroku to deploy my Ruby on Rails apps but I always wanted to learn how it all works under the hood. Over the last couple of months, I decided to learn more about how to set up a server and deploy a Rails app to production. I've made this open-source project called Ansible Rails in order to consolidate my learning.
Ansible Rails is an Ansible playbook for easily deploying Ruby on Rails applications. It uses Vagrant to provision an environment where you can test your deploys. Ansistrano is used for finally deploying our app to staging and production environments.
Ansible Rails automates the following tasks -
- Installation of common packages
- Intall Ruby (via rbenv)
- Install Rails 6, Puma, Sidekiq
- SSH hardening
- Installing firewall (UFW)
- Redis
- Nodejs/Webpack/yarn
- Postgresql and another role that saves backups to S3
- Setup Nginx with some sensible config (thanks to nginxconfig.io)
- Install Certbot (for Letsencrypt SSL Certs)
- Deploying using Ansistrano
- Ansistrano 'hooks' are provided for performing the following tasks -
- Installing all our gems
- Precompiling assets
- Migrating our database (using run_once)
You can find the detailed setup and usage guide/documentation here - https://github.com/EmailThis/ansible-rails. But the next section contains a primer that will help you get started quickly.
Side note: If you haven't used Ansible before, don't worry, it is really easy to understand and get started with it. Simply put, Ansible is an open-source server automation tool. It helps you set up your servers easily. There's no need for you to SSH into each server to do the grunt work (e.g: Updating packages, installing depedencies etc). You can write a simple YAML file containing a bunch of tasks and then tell Ansible to perform those tasks on your server(s). You can read more about it here.
Getting Started
Step 1: Installation
git clone https://github.com/EmailThis/ansible-rails ansible-rails
cd ansible-rails
Step 2: Configuration
Open app-vars.yml
and change the following variables.
app_name: YOUR_APP_NAME // Replace with name of your app
app_git_repo: "YOUR_GIT_REPO" // e.g.: github.com/EmailThis/et
app_git_branch: "master" // branch that you want to deploy (e.g: 'production')
postgresql_db_user: "{{ deploy_user }}_postgresql_user"
postgresql_db_password: "{{ vault_postgresql_db_password }}" # from vault (see next section)
postgresql_db_name: "{{ app_name }}_production"
nginx_https_enabled: false # change to true if you wish to install SSL certificate
Step 3: Deploy!
vagrant up
If you don't want to use Vagrant. Change the inventories/development.ini
file and then run the following commands
ansible-playbook -i inventories/development.ini provision.yml
ansible-playbook -i inventories/development.ini deploy.yml
Documentation
For more information and documentation, please refer to the Github repo - https://github.com/EmailThis/ansible-rails
Questions, comments, suggestions?
Please let me know if you run into any issues or if you have any questions. I'd be happy to help. I would also welcome any improvements/suggestions by way of pull requests.
Shameless plug 🙈: Here's the app that I deployed using this tool. It is a simple bookmarking and 'read later' tool called EmailThis.me (think of it as a simpler alternative to Pocket that turns your email inbox into your reading list).
Let me know what you guys think about it 🙌🏻
Top comments (2)
Thanks for this write up, it touches a few points that i've been trying to get the hang of.
While reading your post, i kept wondering when i would choose what you suggested VS other options.
For instance, i just deployed a side project i'm working on to heroku via GitlabCI but the final product will be deployed on a VPS and so, reading your post made think that maybe your approach is more suitable for such cases where you have to set everything up yourself?
In my opinion, Heroku is the best option if you are just starting out or if you don't have the time/bandwidth for maintaining your VPS. I've used Heroku for many years and I have no complaints.
This approach of deploying to your own VPS is suggested only if you are willing to spend some time on devops (e.g: managing your server, upgrading packages, fixing Nginx config, etc). It is rewarding (but also a bit overwhelming) experience to understand how it all works under the hood. Ultimately, you have to decide if you are willing to split your time between developing your app's business logic and devops.