All Projects → EmailThis → Ansible Rails

EmailThis / Ansible Rails

Ruby on Rails deployment using Ansible - with Lets Encrypt, Sidekiq, PostgreSQL, nginx & puma

Programming Languages

ruby
36898 projects - #4 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to Ansible Rails

Ansipress
AnsiPress - Simple L(Linux) E(NGINX) M(MariaDB) P(PHP7) Shared Hosting Setup
Stars: ✭ 184 (-7.54%)
Mutual labels:  automation, ansible, letsencrypt, nginx
Ansible Rails
Ansible: Ruby on Rails Server
Stars: ✭ 317 (+59.3%)
Mutual labels:  ansible, rails, deployment
Lobsters Ansible
Ansible playbook for lobste.rs
Stars: ✭ 56 (-71.86%)
Mutual labels:  ansible, rails, nginx
Swarmlet
A self-hosted, open-source Platform as a Service that enables easy swarm deployments, load balancing, automatic SSL, metrics, analytics and more.
Stars: ✭ 373 (+87.44%)
Mutual labels:  ansible, deployment, letsencrypt
Ansiblecm
A Docker based Ansible control machine for running playbooks in a consistent environment.
Stars: ✭ 26 (-86.93%)
Mutual labels:  automation, ansible, deployment
Nginx Le
Nginx with automatic let's encrypt (docker image)
Stars: ✭ 475 (+138.69%)
Mutual labels:  automation, letsencrypt, nginx
Rundeck
Enable Self-Service Operations: Give specific users access to your existing tools, services, and scripts
Stars: ✭ 4,426 (+2124.12%)
Mutual labels:  automation, ansible, deployment
Docker Rails
Dockerize Rails 6 with ActionCable, Webpacker, Stimulus, Elasticsearch, Sidekiq
Stars: ✭ 856 (+330.15%)
Mutual labels:  sidekiq, rails, deployment
Rhcsa8env
This is a RHCSA8 study environment built with Vagrant/Ansible
Stars: ✭ 108 (-45.73%)
Mutual labels:  automation, ansible, deployment
Bunkerized Nginx
🛡️ Make your web services secure by default !
Stars: ✭ 2,361 (+1086.43%)
Mutual labels:  nginx, letsencrypt
Dellemc Openmanage Ansible Modules
Dell EMC OpenManage Ansible Modules
Stars: ✭ 169 (-15.08%)
Mutual labels:  automation, ansible
Deploy
Ansible role to deploy scripting applications like PHP, Python, Ruby, etc. in a capistrano style
Stars: ✭ 2,141 (+975.88%)
Mutual labels:  ansible, deployment
Ansible Raspi Playbooks
Playbooks for setup and updating of raspberry pi projects.
Stars: ✭ 162 (-18.59%)
Mutual labels:  automation, ansible
Netbox As Ansible Inventory
Ansible dynamic inventory script for Netbox.
Stars: ✭ 161 (-19.1%)
Mutual labels:  automation, ansible
Lets Nginx
Push button, get TLS
Stars: ✭ 171 (-14.07%)
Mutual labels:  letsencrypt, nginx
Terrible
An Ansible playbook that apply the principle of the Infrastructure as Code on a QEMU/KVM environment.
Stars: ✭ 161 (-19.1%)
Mutual labels:  automation, ansible
Ansible Collection Hardening
This Ansible collection provides battle tested hardening for Linux, SSH, nginx, MySQL
Stars: ✭ 2,543 (+1177.89%)
Mutual labels:  ansible, nginx
Nginx Proxy Automation
Automated docker nginx proxy integrated with letsencrypt.
Stars: ✭ 2,302 (+1056.78%)
Mutual labels:  letsencrypt, nginx
Aenigma
The | state-of-the-art | secure-by-default | one-touch-deployed | XMPP server for everyone.
Stars: ✭ 160 (-19.6%)
Mutual labels:  automation, letsencrypt
Guacamole Install Rhel 7
Apache Guacamole installation bash script for RHEL 7 and CentOS 7 including options for Nginx, HTTPS, SSL, LDAP, Let's Encrypt certificates and more
Stars: ✭ 174 (-12.56%)
Mutual labels:  letsencrypt, nginx

Ansible Rails

Ansible Rails Promo Image

Ansible Rails is a 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.

While this is meant to work out of the box, you can tweak the files in the roles directory in order to satisfy your project-specific requirements.

Shameless plug: If you're looking for a simple bookmarking tool, try EmailThis.me - a simpler alternative to Pocket that helps you save ad-free articles and web pages to your email inbox.


What does this do?

  • Configure our server with some sensible defaults
  • Install required/useful packages. See notes below for more details.
  • Auto upgrade all installed packages (TODO)
  • Create a new deployment user (called 'deploy') with passwordless login
  • SSH hardening
    • Prevent password login
    • Change the default SSH port
    • Prevent root login
  • Setup UFW (firewall)
  • Setup Fail2ban
  • Install Logrotate
  • Setup Nginx with some sensible config (thanks to nginxconfig.io)
  • Certbot (for Let's encrypt SSL certificates)
  • Ruby (using Rbenv).
    • Defaults to 2.6.6. You can change it in the app-vars.yml file
    • jemmaloc is also installed and configured by default
    • rbenv-vars is also installed by default
  • Node.js
    • Defaults to 12.x. You can change it in the app-vars.yml file.
  • Yarn
  • Redis (latest)
  • Postgresql.
    • Defaults to v12. You can specify the version that you need in the app-vars.yml file.
  • Puma (with Systemd support for restarting automatically) See Puma Config section below
  • Sidekiq (with Systemd support for restarting automatically)
  • Ansistrano hooks for performing the following tasks -
    • Installing all our gems
    • Precompiling assets
    • Migrating our database (using run_once)

Getting started

Here are the steps that you need to follow in order to get up and running with Ansible Rails.

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. Additionally, please review the app-vars.yml and see if there is anything else that you would like to modify (e.g.: install some other packages, change ruby, node or postgresql versions etc.)

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. Storing sensitive information

Create a new vault file to store sensitive information

ansible-vault create group_vars/all/vault.yml

Add the following information to this new vault file

vault_postgresql_db_password: "XXXXX_SUPER_SECURE_PASS_XXXXX"
vault_rails_master_key: "XXXXX_MASTER_KEY_FOR_RAILS_XXXXX"

Step 4. Deploy

Now that we have configured everything, lets see if everything is working locally. Run the following command -

vagrant up

Now open your browser and navigate to 192.168.50.2. You should see your Rails application.

If you don't wish to use Vagrant, clone this repo, modify the inventories/development.ini file to suit your needs, and then run the following command

ansible-playbook -i inventories/development.ini provision.yml

To deploy this app to your production server, create another file inside inventories directory called production.ini with the following contents. For this, you would need a VPS. I've used DigitalOcean and Vultr in production for my apps and both these services are top-notch.

[web]
192.168.50.2 # replace with IP address of your server.

[all:vars]
ansible_ssh_user=deployer
ansible_python_interpreter=/usr/bin/python3

Additional Configuration

Installing additional packages

By default, the following packages are installed. You can add/remove packages to this list by changing the required_package variable in app-vars.yml

    - curl
    - ufw
    - fail2ban
    - git-core
    - apt-transport-https
    - ca-certificates
    - software-properties-common
    - python3-pip
    - virtualenv
    - python3-setuptools
    - zlib1g-dev 
    - build-essential 
    - libssl-dev 
    - libreadline-dev 
    - libyaml-dev 
    - libxml2-dev 
    - libxslt1-dev 
    - libcurl4-openssl-dev
    - libffi-dev 
    - dirmngr 
    - gnupg
    - autoconf
    - bison
    - libreadline6-dev
    - libncurses5-dev
    - libgdbm5 
    - libgdbm-dev
    - libpq-dev # postgresql client
    - libjemalloc-dev # jemalloc

Enable UFW

You can enable UFW by adding the role to provision.yml like so -

roles:
    ...
    ...
    - role: ufw
      tags: ufw

Then you can set up the UFW rules in app-vars.yml like so -

ufw_rules:
  - { rule: "allow", proto: "tcp", from: "any", port: "80" }
  - { rule: "allow", proto: "tcp", from: "any", port: "443" }

Enable Certbot (Let's Encrypt SSL certificates)

Add the role to provision.yml

roles:
    ...
    ...
    - role: certbot
      tags: certbot

Add the following variables to app-vars.yml

nginx_https_enabled: true

certbot_email: "[email protected]"
certbot_domains:
  - "domain.com"
  - "www.domain.com"

PostgreSQL Database Backups

By default, daily backup is enabled in the app-vars.yml file. In order for this to work, the following variables need to be set. If you do not wish to store backups, remove (or uncomment) these lines from app-vars.yml.

aws_key: "{{ vault_aws_key }}" # store this in group_vars/all/vault.yml that we created earlier
aws_secret: "{{ vault_aws_secret }}"

postgresql_backup_dir: "{{ deploy_user_path }}/backups"
postgresql_backup_filename_format: >-
  {{ app_name }}-%Y%m%d-%H%M%S.pgdump
postgresql_db_backup_healthcheck: "NOTIFICATION_URL (eg: https://healthcheck.io/)" # optional
postgresql_s3_backup_bucket: "DB_BACKUP_BUCKET" # name of the S3 bucket to store backups
postgresql_s3_backup_hour: "3"
postgresql_s3_backup_minute: "*"
postgresql_s3_backup_delete_after: "7 days" # days after which old backups should be deleted

Puma config

Your Rails app needs to have a puma config file (usually in /config/puma.rb). Here's a sample -

threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count

port ENV.fetch("PORT") { 3000 }

rails_env = ENV.fetch("RAILS_ENV") { "development" }
environment rails_env

if %w[production staging].member?(rails_env)
    app_dir = ENV.fetch("APP_DIR") { "YOUR_APP/current" }
    directory app_dir

    shared_dir = ENV.fetch("SHARED_DIR") { "YOUR_APP/shared" }

    # Logging
    stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
    
    pidfile "#{shared_dir}/tmp/pids/puma.pid"
    state_path "#{shared_dir}/tmp/pids/puma.state"
    
    # Set up socket location
    bind "unix://#{shared_dir}/sockets/puma.sock"
    
    workers ENV.fetch("WEB_CONCURRENCY") { 2 }
    preload_app!

elsif rails_env == "development"
    plugin :tmp_restart
end

Motivation

I use Heroku to deploy my Rails apps. It makes deployment really easy and I've got no complaints. However, 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. This project is a consolidation of my learnings.


Credits


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.

Bharani
Founder @ EmailThis.me

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].