I spent hours today trying different ways of quickly and reproducibly provisioning a Mac for Rails + Postgresql development that could be deployed to Heroku. What follows is, believe it or not, the easiest method I came up with.
This is a cheatsheet, not a tutorial. I’m not going into much depth on what each command does, but if you’re just looking for a list of commands to get running quickly, you’re at the right place.
I tested these instructions against a stock installation of OS X Mavericks 10.9 in VMWare Fusion that had been patched up to 10.9.4 with Software Update. Mavericks 10.9.4 ships with ruby 2.0.0p451.
This cheatsheet was compiled with information from https://devcenter.heroku.com/articles/getting-started-with-rails4 and other sources.
• First, create an account on Heroku, if you don’t have one already.
• Trigger the OS to install Developer Tools if you don’t already have them:
$ git (Click Install) (Agree to license agreement)
Installing just the Developer Tools is faster than installing Xcode if you don’t have/need it.
• Visit this page in Safari:
• Click “Download Heroku Toolbelt for Mac OS X” and run the installer pkg file that it downloads.
• Install Homebrew:
$ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)" $ brew doctor
• Log in to Heroku:
$ heroku login (Enter Heroku email) (Enter Heroku password)
• Install postgresql:
$ brew install postgresql
• Install pg (postgresql) gem:
$ sudo ARCHFLAGS="-arch x86_64" gem install pg
• Start postgresql:
$ postgres -D /usr/local/var/postgres &
• Install Bundler:
$ sudo gem install bundler
• Install Rails:
$ sudo gem install rails --no-ri --no-rdoc (When warned about conflicting rails executable, allow overwrite)
• Create a new postgresql-backed Rails app:
$ rails new myapp -d postgresql
• Create a barebones ‘welcome’ route in the app:
$ cd myapp $ rails generate controller welcome
• Create app/views/welcome/index.html/erb with the editor of your choice, and insert the following content:
<h2>Hello World</h2> <p> The time is now: <%= Time.now %> </p>
• Edit config/routes.rb and uncomment this line:
• Add this line to the end of Gemfile:
gem 'rails_12factor', group: :production
• Run Bundler to get the rails_12factor gem installed (required by Heroku):
$ bundle install
• Create a default database named after your username (a convenience for if you want to use a postgresql GUI like PG Commander later):
• Create dev and test databases for the Rails app:
$ createdb myapp_development $ createdb myapp_test
• Edit config/database.yml and change the “production” section at the bottom to read like this:
production: url: <%= ENV['DATABASE_URL'] %>
Delete the database, username, and password lines from this section. You can delete the line that begins with << too.
• At this point you should be able to run the app locally on the built-in server:
$ rails server (visit url http://localhost:3000/) (^C to stop the server)
• Create a git repo for the project:
$ git init $ git add . $ git commit -m "init"
• Create a Heroku app:
$ heroku create
Heroku will automatically assign your app a name consisting of a couple of words and a number.
• If you already have an SSH keypair, you can upload the public key through the Heroku dashboard, then, on your Mac, use ssh-add to make the private key available to ssh-agent.
If you don’t already have an SSH keypair, or would rather use a new one, let Heroku generate one:
$ heroku keys:add (it asks if you want to generate one, say yes)
• Push git repository to Heroku:
$ git push heroku master (if you get a warning that the authenticity of the host cannot be established, enter yes to continue)
• Confirm your app is now running on Heroku:
$ heroku open
At this point, Heroku is running the app on webrick, which is not suitable for production.
• To switch to the unicorn web server, add this line to the end of Gemfile:
$ bundle install
• Create config/unicorn.rb with the following content (watch out for word-wrapping on the blog here):
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3) timeout 15 preload_app true before_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn master intercepting TERM and sending myself QUIT instead' Process.kill 'QUIT', Process.pid end defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! end after_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT' end defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end
• Inform Heroku that you wish to use unicorn by creating a file called Procfile with this content:
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
• To test with the unicorn server locally, install Foreman:
$ sudo gem install foreman (answer yes if it asks if you want to overwrite the existing executable)
• You can now start the unicorn web server with:
$ foreman start
Note that unicorn runs by default on port 5000 instead of webrick’s port 3000, so to test, visit http://localhost:5000/
• Stop unicorn with ^C.
• Commit changes to git repo:
$ git add . $ git commit -m "added unicorn"
• Deploy to Heroku again:
$ git push heroku master
• Verify that Heroku is still serving a working app:
$ heroku open
• If you’d like extra confirmation that the app is now running atop unicorn, the server log should show something that looks like unicorn output:
$ heroku logs
And it’s just THAT EASY. ;)