Ruby on Rails Deploy Explained: Twelve Factor


This article is the second from our Ruby on Rails deploy explained series. As we defined in a title post there are two general approaches to Ruby on Rails deployment process: when the server knows much about the application and when it does not. The former approach is more traditional. It usually involves tools like Capistrano and eventually Ansible.

The latter approach is more applicable for platform-as-a-service hostings like Heroku. Heroku was a pioneer in it for Ruby on Rails. Thus, it implemented a kind of standard, which was called 12 factor.

12 factor is a way to organize a web application according to rules defined by Heroku. The 12-factor approach is aimed to maximize portability and minimize divergence between development and production.

To use Heroku, Dokku or any similar service, your application has to conform to 12 factor principles. In general, this brings in high portability to your application and reduces the knowledge needed to launch it.

So, let's take some simple steps to prepare your application to twelve factor.


12 factor suggests to keep config in environment variables. You can use dotenv or figaro for this. Econfig can be a good solution as it allows to store settings in the database (there is an option to edit them from admin panel) with a fallback to environment variables. But anyway, you will have to pass the database connection to the application as a setting. This is the setting that you always have.

Fortunately, Rails already does a good job about this, and since 4.1 it handles this perfectly. If an application has defined an environment variable DATABASE_URL, its settings override the ones in config/database.yml. So you shouldn't do anything about it.

For all other settings inside the application, you should read them as if they came from environment variables and only dotenv, foreman or figaro should know where they actually came from.


Don't forget to replace Sqlite with Postgres, in case you haven't done it yet. Sqlite is great but it's about file system and cannot be attached as a background service.

Processes, disposability and port binding

12 factor recommends to run your application as a plain Unix process. For Ruby on Rails, this basically means that you should take care of the application server. Such process should export everything via simple port/socket binding instead of relying on application server or serving files directly from the file system.

To do it, we will use a standard Procfile convention. Procfile is a way to declare which processes should be run by the application. The simplest Procfile for your application is:

web: ./bin/rails server thin -p $PORT -e ${RACK_ENV:-development}

If you have delayed job or sidekiq:

web: ./bin/rails server thin -p $PORT -e ${RACK_ENV:-development}
worker: ./bin/rake jobs:work
# or
worker: ./bin/sidekiq # assuming you prepared a binstub which is recommended

To export everything via port without relying on static serving assets, I suggest using rails_12factor gem. Just put it in Gemfile in production.

By default, Rails does not serve static assets in production. Instead, it assumes that they are served by using something like tryfiles Nginx directive. But we treat our application as a simple process that binds port and exposes all it has via that port. That's why, we need Rails to serve static files.

This also reduces dev-prod divergence, so that your application in production works closer to how it works on your development machine.


12 factor offers to treat logs as streams, not files. This means that you should direct logs to stdout, (almost) like it works in development. It is already done if you used rails_12factor gem.

You're done!

Now you are ready to install Dokku and use it. We'll explain it in the next article.