Sometimes ago I had to deploy a Rails app on Heroku to mirror the production hosting service as close as possible.
So I signed up for an account on Heroku and installed the heroku gem which allows to drive your account from the command-line.
After that, I had a running dummy app online with only two commands. Just awesome! That’s so much simpler than deploying from scratch on a dedicated server that you maintain by yourself. For sure that’s much more expansive too and you have to use their add-ons if you need some services. Some of these add-ons are free but not all.
Nonetheless there are some gotchas you need to know if you want to use Heroku without having any trouble or hours lost googling.
That’s why I’m going to show you some steps to be able to use Heroku hosting effectively and quickly.
First of all you need to sign up for an account. You like simple forms? Here’s one, you only have to enter your email address. You’ll get a confirmation email and then you’re good to go!
Some of you maybe know that I’m a command-line guy, I love my shell and love to be able to do everything with it.
Heroku has score here because they provide a command-line tool available as a Gem. This command-line tool gives you the power to do pretty much everything you can think of on Heroku right from your shell. Once again, awesome!
To install this tool, you have to use rubygems:
$ gem install heroku
Then, if your using rbenv, don’t forget to rehash:
$ rbenv rehash
You should now be able to use the command-line tool:
$ heroku -v
heroku-gem/2.28.10 (x86_64-darwin11.4.0) ruby/1.9.3
Next step is to authenticate your client on Heroku and gain access to your account:
$ heroku login
Enter your Heroku credentials.
Email: nico@bounga.org
Password (typing will be hidden):
Authentication successful.
You’ll maybe ask if you want to generate a new RSA key and upload it to Heroku. You can safely answer yes.
You’re now ready to play with Heroku.
Now you need to create a new “app” on Heroku to host your Rails app.
Go to you Rails app folder to create a new Heroku stack:
$ cd ~/Sites/my_rails_app
$ heroku create
Creating sheltered-scrubland-4680... done, stack is cedar
http://sheltered-scrubland-4680.herokuapp.com/ | git@heroku.com:sheltered-scrubland-4680.git
You got three important info back:
All you have to do to deploy is to push your code to the Git repo provided by Heroku. If your code is already managed by Git that’s fine, if it doesn’t be sure to git init
and git commit
your code.
So let’s push our code:
$ git push git@heroku.com:sheltered-scrubland-4680.git master
Your code is now up-to-date on Heroku and the webserver should have restart.
One of the first and recurrent thing you’ll need to do is migrate your database:
$ heroku run rake db:migrate --app sheltered-scrubland-4680
This will connect to your remote instance through SSH and run the given task. Be sure to always use the --app
to tell which app you want to run the command on.
Let’s say now you want to use a remote Rails console to check your remote data:
$ heroku run console
Wanna see logs ?
$ heroku run logs --app sheltered-scrubland-4680
Need to see if process are running?
$ heroku run ps --app sheltered-scrubland-4680
By default Heroku provides you no add-on at all. You have to enable those you need. You have for example a free 5Mb postgresql database available.
$ heroku addons --app sheltered-scrubland-4680
No addons for sheltered-scrubland-4680
You can get a list of all available add-ons:
$ heroku addons:list --app sheltered-scrubland-4680
You should check Heroku add-on docs to know what each does exactly.
Let’s say you want to use the free Postgresql 5Mb database:
$ heroku addons:add shared-database:5mb --app sheltered-scrubland-4680
Adding shared-database:5mb to sheltered-scrubland-4680... done, v2 (free)
Use `heroku addons:docs shared-database:5mb` to view documentation
You’re the only one to know what you need in your stack but for the sack of example I’ll show you the stack I used on my project.
$ heroku addons --app sheltered-scrubland-4680
=== sheltered-scrubland-4680 Configured Add-ons
amazon_rds
blitz:250
logentries:tryit
memcachier:dev
scheduler:standard
sendgrid:starter
ssl:endpoint
This add-on allow you to use your remote Amazon MySQL instance. To do this you need to enable this add-on and set an environment variable on your Heroku instance. Heroku doesn’t use your config/database.yml
but creates it from the configuration you defined for your DB using environment variable.
Here is how you define env variable for Amazon RDS:
$ heroku config:set DATABASE_URL="mysql2://user:pass@foo.ce1mkunew0xe.us-east-1.rds.amazonaws.com/db_name" --app sheltered-scrubland-4680
Then enable the addon and your app will use the remote Amazon RDS:
$ heroku addons:add amazon_rds --app sheltered-scrubland-4680
Pro-tip for those who want to connect to their Amazon RDS through SSL: Be sure to download the Amazon RDS SSL Cert and put it in your app tree. In my case I’ve put it in config/mysql-ssl-ca-cert.pem
and then updated the DATABASE_URL variable to enabled SSL connection:
$ heroku config:set DATABASE_URL="mysql2://user:pass@foo.ce1mkunew0xe.us-east-1.rds.amazonaws.com/db_name?sslca=/app/config/mysql-ssl-ca-cert.pem" --app sheltered-scrubland-4680
Blitz is an add-on to simulate high user concurrency on your app. This is really useful on staging server when you need to know where are the bottlenecks. This is a good way to improve your app speed and estimate how much users you can handle in a given configuration.
$ heroku addons:add blitz:250 --app sheltered-scrubland-4680
Log entries is a nicer way to read your app logs within a web interface which live updates. You have nice graphs to tell you the amount of data stored or indexed by day, …
$ heroku addons:add logentries:tryit --app sheltered-scrubland-4680
This is a free development addon if you stick to 25Mb of memory. It allows you to easily add a memcache server to your instance that you can next use through Dalli gem.
$ heroku addons:add memcachier:dev --app sheltered-scrubland-4680
Works seamlessly with Rails.cache
.
Only one config line to use it, so for example in config/environments/production.rb
:
config.cache_store = :dalli_store, {expires_in: 1.day, compress: true}
Scheduler is kind of hack from Heroku because they don’t allow you to play with cronjobs on your instance. As an alternate way, you can define commands to be call on given period. So the best thing to do is to create Rake tasks in your project and call them from Scheduler.
Heroku Scheduler GUI is provided to define commands to be called and their period.
$ heroku addons:add scheduler:standard --app sheltered-scrubland-4680
Heroku doesn’t handle email sending by itself, there’s no local SMTP or something. To easily scale emails delivering and provide real-time analytics Heroku offers to use an add-on called Sendgrid:
No headaches here, all you have to do is enable the add-on and add some lines of config in your production.rb:
$ heroku addons:add sendgrid:starter --app sheltered-scrubland-4680
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com'
}
ActionMailer::Base.delivery_method = :smtp
If you need SSL for your web app, this is the add-on you need to enable:
$ heroku addons:add ssl:endpoint --app sheltered-scrubland-4680
then you can add your SSL certificates to your instance using:
$ heroku certs:add PEM KEY --app sheltered-scrubland-4680
If you need to list installed certs:
$ heroku certs --app sheltered-scrubland-4680
Last thing I can’t forget is the trick to be able to load fixture on your remote instance.
I really like to use fixtures to feed my staging DB every time I need a clean and usable state. For some odd reasons, Heroku engineer Richard Schneeman helps me to track, recent version of Rails (3.2.6 in my case) has introduced a bug in how database is initialized.
So I ended-up spending some days wondering why this wasn’t working due to a:
Connecting to database specified by DATABASE_URL rake aborted! database configuration does not specify adapter
It was really frustrating to see all tasks working well, website instance was running too. The only thing that wasn’t working was fixtures loading…
But luckily I have a fix for you! This bug seems to be fixed in Rails 4.0 but for the moment I stick to 3.2.X.
All you have to do is to create an initializer which will properly set ORM config:
ActiveRecord::Base.configurations = Rails.application.config.database_configuration
I hope this quick introduction to Heroku hosting stack will help with your first deployments and most important that it will prevent you wasting time in strange bug and doc digging!
Synbioz Team.