Table of Contents
If you are already familiar with Heroku and Rails, reference the simplified Rails 4 on Heroku guide instead. For general information on how to develop and architect apps for use on Heroku, see Architecting Applications for Heroku.
For this guide you will need:
- Basic Ruby/Rails knowledge
- Locally installed version of Ruby, Rubygems, Bundler, and Rails 4+
- Basic Git knowledge
- A Heroku user account: Signup is free and instant
If you have questions about Ruby on Heroku, consider discussing it in the Ruby on Heroku forums.
Local Workstation Setup
Install the Heroku Toolbelt on your local workstation. This ensures that you have access to the Heroku command-line client, Foreman, and the Git revision control system. You will also need Ruby and Rails installed.
Once installed, you’ll have access to the
$ heroku command from your command shell. Log in using the email address and password you used when creating your Heroku account:
$ symbol before commands indicates they should be run on the command line, prompt, or terminal with appropriate permissions. Do not copy the
$ heroku login Enter your Heroku credentials. Email: email@example.com Password: Could not find an existing public key. Would you like to generate one? [Yn] Generating new SSH public key. Uploading ssh public key /Users/adam/.ssh/id_rsa.pub
Press enter at the prompt to upload your existing
ssh key or create a new one, used for pushing code later on.
Write your App
To run on Heroku your app must be configured to use the Postgres database, have all dependencies declared in your
Gemfile, and have the
rails_12factor gem in the production group of your
You may be starting from an existing app, if so upgrade to Rails 4 before continuing. If not, a vanilla Rails 4 app will serve as a suitable sample app. To build a new app make sure that you’re using the Rails 4.x using
$ rails -v. You can get the new version of rails by running,
$ gem install rails --no-ri --no-rdoc Successfully installed rails-4.1.0 1 gem installed
Then create a new app:
$ rails new myapp --database=postgresql
Once finished change your directory to the newly created Rails app
$ cd myapp
If you experience problems or get stuck with this tutorial, your questions may be answered in a later part of this document. Once you experience a problem try reading through the entire document and then going back to your issue. It can also be useful to review your previous steps to ensure they all executed correctly.
Note: If your
rails commands hang for any reason it may be a result of running
spring. You can stop spring by running
$ spring stop Spring stopped.
Rails 4 no longer has a static index page in production. When you’re using a new app, there will not be a root page in production, so we need to create one. We will first create a controller called
welcome for our home page to live:
$ rails generate controller welcome
Next we’ll add an index page.
<h2>Hello World</h2> <p> The time is now: <%= Time.now %> </p>
Now we need to have Rails route to this action. We’ll edit
config/routes.rb to set the index page to our new method:
config/routes.rb, on line 2 add:
You can verify that the page is there by running your server:
$ rails server
And visiting http://localhost:3000 in your browser. If you do not see the page, use the logs that are output to your server to debug.
Heroku integration has previously relied on using the Rails plugin system, which has been removed from Rails 4. To enable features such as static asset serving and logging on Heroku please add
rails_12factor gem to your
At the end of
gem 'rails_12factor', group: :production
$ bundle install
We talk more about Rails integration on our Ruby Support page.
We highly recommend using PostgreSQL during development. Maintaining parity between your development and deployment environments prevents subtle bugs from being introduced because of differences between your environments. Install Postgres locally now if it is not already on your system.
If you did not specify
postgresql while creating your app (using
--database=postgresql) you will need to add the
pg gem to your Rails project. Edit your
Gemfile and change this line:
You can get more information on why this change is needed and how to configure your app to run postgres locally see why you cannot use Sqlite3 on Heroku.
In addition to using the
pg gem, you’ll also need to ensure the
config/database.yml is using the
You will also need to remove the
username field in your
database.yml if there is one so:
This line tells rails that the database
myapp_development should be run under a role of
myapp. Since you likely don’t have this role in your database we will remove it. With the line removed, Rails will try to access the database as a user who is currently logged into the computer.
The development section of your
config/database.yml file should look something like this:
$ cat config/database.yml # PostgreSQL. Versions 8.2 and up are supported. # # Install the pg driver: # gem install pg # On OS X with Homebrew: # gem install pg -- --with-pg-config=/usr/local/bin/pg_config # On OS X with MacPorts: # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config # On Windows: # gem install pg # Choose the win32 build. # Install PostgreSQL and put its /bin directory on your path. # # Configure Using Gemfile # gem 'pg' # default: &default adapter: postgresql encoding: unicode # For details on connection pooling, see rails configuration guide # http://guides.rubyonrails.org/configuring.html#database-pooling pool: 5
Be careful here, if you omit the
sql at the end of
postgresql your application will not work.
Now re-install your dependencies (to generate a new
$ bundle install
Specify Ruby version in app
Rails 4 requires Ruby 1.9.3 or above. Heroku has a recent version of Ruby installed, however you can specify an exact version by using the
ruby DSL in your
Gemfile. For this guide we’ll be using Ruby 2.1.1 so add this to your
At the end of
You should also be running the same version of Ruby locally. You can verify by running
$ ruby -v. You can get more information on specifying your Ruby version on Heroku here.
Store your App in Git
Heroku relies on git, a distributed source control managment tool, for deploying your project. If your project is not already in git first verify that
git is on your system:
$ git --help usage: git [--version] [--help] [-c name=value] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p|--paginate|--no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] <command> [<args>] The most commonly used git commands are: add Add file contents to the index bisect Find by binary search the change that introduced a bug branch List, create, or delete branches
If you don’t see any output or get
command not found you will need to install it on your system, verify that the Heroku toolbelt is installed.
Once you’ve verified that git works, first make sure you are in your Rails app directory by running:
The output should look like this:
$ ls Gemfile Gemfile.lock README.rdoc Rakefile app bin config config.ru db lib log public test tmp vendor
Now run these commands in your Rails app directory to initialize and commit your code to git:
$ git init $ git add . $ git commit -m "init"
You can verify everything was committed correctly by running:
$ git status # On branch master nothing to commit, working directory clean
Now that your application is committed to git you can deploy to Heroku.
Deploy your application to Heroku
Make sure you are in the directory that contains your Rails app, then create an app on Heroku:
$ heroku create Creating warm-wave-1943... done, stack is cedar http://warm-wave-1943.herokuapp.com/ | firstname.lastname@example.org:warm-wave-1943.git Git remote heroku added
You can verify that the remote was added to your project by running
$ git config -e
If you see
fatal: not in a git directory then you are likely not in the correct directory. Otherwise you may deploy your code. After you deploy your code, you will need to migrate your database, make sure it is properly scaled and use logs to debug any issues that come up.
Deploy your code:
$ git push heroku master Initializing repository, done. -----> Ruby app detected -----> Compiling Ruby/Rails -----> Using Ruby version: ruby-2.1.1 -----> Installing dependencies using 1.5.2 Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment Fetching gem metadata from https://rubygems.org/.......... Fetching additional metadata from https://rubygems.org/.. Using json (1.8.1) Installing i18n (0.6.9) Installing rake (10.3.0) Installing builder (3.2.2) Installing minitest (5.3.3) Installing thread_safe (0.3.3) Installing mime-types (1.25.1) Installing erubis (2.7.0) Installing polyglot (0.3.4) Installing arel (188.8.131.5240414130214) Installing execjs (2.0.2) Installing coffee-script-source (1.7.0) Installing rack (1.5.2) Installing hike (1.2.3) Using bundler (1.5.2) Installing thor (0.19.1) Installing multi_json (1.9.2) Installing tilt (1.4.1) Installing rails_serve_static_assets (0.0.2) Installing rails_stdout_logging (0.0.3) Installing sass (3.2.19) Installing rdoc (4.1.1) Installing tzinfo (1.1.0) Installing uglifier (2.5.0) Installing treetop (1.4.15) Installing coffee-script (2.2.0) Installing rack-test (0.6.2) Installing rails_12factor (0.0.2) Installing sprockets (2.11.0) Installing sdoc (0.4.0) Installing activesupport (4.1.0) Installing mail (2.5.4) Installing activemodel (4.1.0) Installing jbuilder (2.0.6) Installing actionview (4.1.0) Installing activerecord (4.1.0) Installing actionpack (4.1.0) Installing sprockets-rails (2.1.3) Installing actionmailer (4.1.0) Installing railties (4.1.0) Installing coffee-rails (4.0.1) Installing jquery-rails (3.1.0) Installing turbolinks (2.2.2) Installing sass-rails (4.0.3) Installing rails (4.1.0) Installing pg (0.17.1) Your bundle is complete! Gems in the groups development and test were not installed. It was installed into ./vendor/bundle Post-install message from rdoc: Depending on your version of ruby, you may need to install ruby rdoc/ri data: <= 1.8.6 : unsupported = 1.8.7 : gem install rdoc-data; rdoc-data --install = 1.9.1 : gem install rdoc-data; rdoc-data --install >= 1.9.2 : nothing to do! Yay! Bundle completed (48.17s) Cleaning up the bundler cache. -----> Preparing app for Rails asset pipeline Running: rake assets:precompile I, [2014-04-17T17:54:07.273555 #1263] INFO -- : Writing /tmp/build_8945fb34-0238-41d7-a2fd-4402581a95fe/public/assets/application-10faafa06109fa14582542ac1852f5c5.js I, [2014-04-17T17:54:07.338617 #1263] INFO -- : Writing /tmp/build_8945fb34-0238-41d7-a2fd-4402581a95fe/public/assets/application-9cc0575249625b8d8648563841072913.css Asset precompilation completed (11.26s) Cleaning assets Running: rake assets:clean -----> WARNINGS: No Procfile detected, using the default web server (webrick) https://devcenter.heroku.com/articles/ruby-default-web-server -----> Discovering process types Procfile declares types -> (none) Default types for Ruby -> console, rake, web, worker -----> Compressing... done, 21.9MB -----> Launching... done, v6 http://warm-wave-1943.herokuapp.com/ deployed to Heroku To email@example.com:warm-wave-1943.git * [new branch] master -> master
It is always a good idea to check to see if there are any warnings or errors in the output. If everything went well you can migrate your database.
Migrate your database
If you are using the database in your application you need to manually migrate the database by running:
$ heroku run rake db:migrate
Any commands after the
heroku run will be executed on a Heroku dyno.
Visit your application
You’ve deployed your code to Heroku. You can now instruct Heroku to execute a process type. Heroku does this by running the associated command in a dyno - a lightweight container which is the basic unit of composition on Heroku.
Let’s ensure we have one dyno running the
web process type:
$ heroku ps:scale web=1
You can check the state of the app’s dynos. The
heroku ps command lists the running dynos of your application:
$ heroku ps === web (1X): `bin/rails server -p $PORT -e $RAILS_ENV` web.1: starting 2014/04/17 12:54:20 (~ 3s ago)
Here, one dyno is running.
We can now visit the app in our browser with
$ heroku open Opening warm-wave-1943... done
You should now see the “Hello World” text we inserted above.
Heroku gives you a default web url for simplicty while you are developing. When you are ready to scale up and use Heroku for production you can add your own Custom Domain.
View the logs
If you run into any problems getting your app to perform properly, you will need to check the logs.
You can view information about your running app using one of the logging commands,
$ heroku logs 2014-04-17T17:52:41.286751+00:00 heroku[api]: Enable Logplex by firstname.lastname@example.org 2014-04-17T17:52:41.286873+00:00 heroku[api]: Release v2 created by email@example.com 2014-04-17T17:52:54+00:00 heroku[slug-compiler]: Slug compilation started 2014-04-17T17:54:19.695689+00:00 heroku[api]: Release v3 created by firstname.lastname@example.org 2014-04-17T17:54:20.047893+00:00 heroku[api]: Deploy 4a37583 by email@example.com 2014-04-17T17:54:19.695584+00:00 heroku[api]: Set DATABASE_URL config vars by firstname.lastname@example.org 2014-04-17T17:54:19.214087+00:00 heroku[api]: Scale to web=1 by email@example.com 2014-04-17T17:54:19.797989+00:00 heroku[api]: Attach HEROKU_POSTGRESQL_JADE resource by firstname.lastname@example.org 2014-04-17T17:54:19.798073+00:00 heroku[api]: Release v4 created by email@example.com 2014-04-17T17:54:19.946728+00:00 heroku[api]: Set LANG, RAILS_ENV, RACK_ENV, SECRET_KEY_BASE config vars by firstname.lastname@example.org 2014-04-17T17:54:19.946728+00:00 heroku[api]: Release v5 created by email@example.com 2014-04-17T17:54:20+00:00 heroku[slug-compiler]: Slug compilation finished 2014-04-17T17:54:22.006939+00:00 heroku[api]: Scale to web=1 by firstname.lastname@example.org 2014-04-17T17:54:20.048071+00:00 heroku[api]: Release v6 created by email@example.com 2014-04-17T17:54:24.109164+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 18367 -e production`
You can also get the full stream of logs by running the logs command with the
--tail flag option like this:
$ heroku logs --tail
Dyno sleeping and scaling
Having only a single web dyno running will result in the dyno going to sleep after one hour of inactivity. This causes a delay of a few seconds for the first request upon waking. Subsequent requests will perform normally.
To avoid this, you can scale to more than one web dyno. For example:
$ heroku ps:scale web=2
For each application, Heroku provides 750 free dyno-hours. Running your app at 2 dynos would exceed this free, monthly allowance, so let’s scale back:
$ heroku ps:scale web=1
Heroku allows you to run commands in a one-off dyno - scripts and applications that only need to be executed when needed - using the
heroku run command. Use this to launch a Rails console process attached to your local terminal for experimenting in your app’s environment:
$ heroku run rails console irb(main):001:0> puts 1+1 2
Rake can be run as an attached process exactly like the console:
$ heroku run rake db:migrate
By default, your app’s web process runs
rails server, which uses Webrick. This is fine for testing, but for production apps you’ll want to switch to a more robust webserver. On Cedar, we recommend Unicorn as the webserver. Regardless of the webserver you choose, production apps should always specify the webserver explicitly in the
First, add Unicorn to your application
At the end of
$ bundle install
Now you are ready to configure your app to use Unicorn.
Create a configuration file for Unicorn at
$ touch config/unicorn.rb
Now we’re going to add Unicorn specific configuration options, that we explain in detail in Heroku’s Unicorn documentation:
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
This default configuration assumes a standard Rails app with Active Record. You should get acquainted with the different options in the official Unicorn documentation.
Finally you will need to tell Heroku how to run your Rails app by creating a
Procfile in the root of your application directory.
Change the command used to launch your web process by creating a file called Procfile and entering this:
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
Note: The case of
Procfile matters, the first letter must be uppercase.
RACK_ENV to development in your environment and a
PORT to connect to. Before pushing to Heroku you’ll want to test with the
RACK_ENV set to production since this is the enviroment your Heroku app will run in.
$ echo "RACK_ENV=development" >> .env $ echo "PORT=3000" >> .env
You’ll also want to add
.env to your
.gitignore since this is for local enviroment setup.
$ echo ".env" >> .gitignore $ git add .gitignore $ git commit -m "add .env to .gitignore"
Test your Procfile locally using Foreman:
$ gem install foreman
You can now start your web server by running
$ foreman start 18:24:56 web.1 | I, [2013-03-13T18:24:56.885046 #18793] INFO -- : listening on addr=0.0.0.0:5000 fd=7 18:24:56 web.1 | I, [2013-03-13T18:24:56.885140 #18793] INFO -- : worker=0 spawning... 18:24:56 web.1 | I, [2013-03-13T18:24:56.885680 #18793] INFO -- : master process ready 18:24:56 web.1 | I, [2013-03-13T18:24:56.886145 #18795] INFO -- : worker=0 spawned pid=18795 18:24:56 web.1 | I, [2013-03-13T18:24:56.886272 #18795] INFO -- : Refreshing Gem list 18:24:57 web.1 | I, [2013-03-13T18:24:57.647574 #18795] INFO -- : worker=0 ready
Looks good, so press Ctrl-C to exit and you can deploy your changes to Heroku:
$ git add . $ git commit -m "use unicorn via procfile" $ git push heroku master
ps, you’ll see the web process uses your new command specifying Unicorn as the web server
$ heroku ps === web (1X): `bundle exec unicorn -p $PORT -c ./config/unicorn.rb` web.1: starting 2014/04/17 12:55:33 (~ 1s ago)
The logs also reflect that we are now using Unicorn:
$ heroku logs
Rails Asset Pipeline
There are several options for invoking the Rails asset pipeline when deploying to Heroku. For general information on the asset pipeline please see the Rails 3.1+ Asset Pipeline on Heroku Cedar article.
config.assets.initialize_on_precompile option has been removed is and not needed for Rails 4. Also, any failure in asset compilation will now cause the push to fail. For Rails 4 asset pipeline support see the Ruby Support page.
If you push up your app and it crashes (
heroku ps shows state
crashed), check your logs to find out what went wrong. Here are some common problems.
Runtime dependencies on development/test gems
If you’re missing a gem when you deploy, check your Bundler groups. Heroku builds your app without the
test groups, and if you app depends on a gem from one of these groups to run, you should move it out of the group.
One common example using the RSpec tasks in your
Rakefile. If you see this in your Heroku deploy:
$ heroku run rake -T Running `bundle exec rake -T` attached to terminal... up, ps.3 rake aborted! no such file to load -- rspec/core/rake_task
Then you’ve hit this problem. First, duplicate the problem locally:
$ bundle install --without development:test â¦ $ bundle exec rake -T rake aborted! no such file to load -- rspec/core/rake_task
Now you can fix it by making these Rake tasks conditional on the gem load. For example:
begin require "rspec/core/rake_task" desc "Run all examples" RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = %w[--color] t.pattern = 'spec/**/*_spec.rb' end rescue LoadError end
Confirm it works locally, then push to Heroku.
You now have your first application deployed to Heroku. The next step is to deploy your own application. If you’re interested in reading more you can read more about Ruby on Heroku at the Dev Center.