Migrating an existing App to Heroku Celadon Cedar Stack

It’s currently not possible to do an automated migration from or to the “Heroku Celadon Cedar Stack”:http://devcenter.heroku.com/articles/cedar which “started in May”:http://blog.heroku.com/archives/2011/5/31/celadon_cedar/. The only help that you get from Heroku is this:

Migrating From Bamboo to Cedar

Before migrating to Bamboo, you should make sure your app runs on Ruby 1.9.2. If your app is not already deployed successfully to bamboo-mri-1.9.2, you should do that first, and then come back and try Cedar.

Once you’re sure your app is fully compatible with Ruby 1.9.2, create an app on the Cedar stack and push to it. Currently, stack:migrate does not work for moving apps to Cedar.

Since there seem to be no blogposts of how to do all the stuff with an existing application I will try to cover everything that I did to do the migration manually in this article.

h2. Cedar is different

If you are looking at the new stack you will notice that a lot has changed with Cedar. Most of the “Heroku CLI”:http://devcenter.heroku.com/categories/command-line has changed to reflect the new possibilites that come with the Cedar stack. Since Cedar introduces a new “way of handling processes on Heroku”:http://devcenter.heroku.com/articles/process-model, most of the commands are now streamlined with this:

# old
heroku console
heroku rake db:migrate
# new 
heroku run console
heroku run rake db:migrate

# have a look at running processes
heroku ps

# look at logs of different processes and tail the output
heroku logs --ps web -t

h3. Preparing the Migration

I started by cloning my current app from Heroku into another directory and creating a new Cedar app on Heroku:

git clone [email protected]:hamburg-on-ruby.git legacy
cd legacy
heroku create --stack cedar

h3. Adapting Cedar changes

The “docs for creating a Rails 3 app on Cedar”:http://devcenter.heroku.com/articles/rails3 reflect some of the changes that have been introduced with Cedar.

One of those is that PostgreSQL is now recommended for local development and you need to have the “pg-gem”:https://rubygems.org/gems/pg in your Gemfile. Otherwise you will get errors while running rake commands:

heroku run rake db:migrate

  Running rake db:migrate attached to terminal... up, run.1
  (in /app)
  rake aborted!
  no such file to load -- pg

Since I developed my app with SQLite3 and I don’t want to learn, install and manage ANOTHER Database I split up the database stuff for development, test and production:

# Gemfile
group :production do
  gem "pg"
end

group :development, :test do
  gem "sqlite3-ruby", :require => "sqlite3"
end

and exclude production dependencies from my local environment:

# put this into your .profile
alias bd="bundle --without=production"

It’s also recommended to serve Rails through “thin webserver”:https://rubygems.org/gems/thin and manage the application with “the Procfile manager foreman”:https://rubygems.org/gems/foreman:

# Gemfile
gem "foreman"
gem "thin"
# Procfile
web: bundle exec rails server thin -p $PORT
foreman start

After going through those chages you should be able to see your application on localhost:

open http://localhost:5000

h2. The migration process

If the application is running on your development machine you can start the core migration process by putting your legacy application into maintenance mode, so that no database changes will be made:

heroku maintenance:on
# stop worker, crons or whatever might be changing the db

h3. Database Migration

After you completely halted everything on your dyno, you can start dumping the database to your development machine (I thought it would be neat to do a direct migration from the legacy database to the new Cedar database, but I did not get it working). You need to install the “taps-gem”:http://devcenter.heroku.com/articles/taps in order to do any dumping. Taps will dump the database into your development database unless you provide an connection string to another database:

# use sqlite for dumping and do it into a separate file
heroku db:pull sqlite://dump.db

# mv the file to your Cedar application and push it
heroku db:push sqlite://dump.db

h3. Config variables

If you have custom config variables in your application it’s pretty easy to move them into the new environment:

# list all config values of the legacy app in console format
heroku config -s

# replace the newlines with whitespaces and
# append all the configuration variables of 
# your new Cedar app at the end or remove the
# ones that you do not want to migrate!

# add the list of values to your Cedar app
heroku config:add KEY=VALUE KEY2=VALUE2 [...]

h3. Installing addons

It’s also most likely that you want to use the same addons than in your legacy application:

# list your addons in the legacy app
heroku addons

# install all addons separately in the Cedar app
heroku addons:add apigee:basic
heroku addons:add cron:daily
[...]

h4. Sendgrid

If you are using “the Sendgrid Addon”:http://devcenter.heroku.com/articles/smtp#sending_email_from_rails you should be aware that the automatic configuration is not working anymore the Cedar Stack! You need to “configure it in your app”:http://devcenter.heroku.com/articles/smtp:

  # config/environments/production.rb
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.smtp_settings = {
    :address        => "smtp.sendgrid.net",
    :port           => "25",
    :authentication => :plain,
    :user_name      => ENV['SENDGRID_USERNAME'],
    :password       => ENV['SENDGRID_PASSWORD'],
    :domain         => ENV['SENDGRID_DOMAIN']
  }

h3. Switching domains

Before you do the last step, you should have a look if everything is up and running:

heroku open

If everything is fine, you can move all the domains from the legacy application to your new and shiny Cedar Stack application:

# list domains in legacy app
heroku domains

# and remove them
heroku domains:remove hamburg.onruby.de
heroku domains:remove onruby.de
[...]

# re-add them to Cedar application
heroku domains:add hamburg.onruby.de
heroku domains:add onruby.de
[...]

Looking at “the result”:http://onruby.de is quite disappointing, because nothing has changed for the user, but everything is new and shiny from the inside!

If you have any other pointers of what you need to do for migrating your application please feel free to add a comment!

13 thoughts on “Migrating an existing App to Heroku Celadon Cedar Stack

  1. Paul Sturgess

    Thanks for the write-up. I found I needed to run ‘heroku restart’ as the final step after adding the domains as I was getting an error H14.

  2. Pingback: Heroku Cedar Background Jobs for free! | ☠ nofail

  3. Jerry T

    Thanks for the write up! It’s very useful.

    You can actually skip the database migration step by just changing the DATABASE_URL of heroku config.
    heroku config:add DATABASE_URL=

    Hope that helps.

  4. umx

    Hello,

    I added a custom domain to my heroku app and it works well, however only on the top domain level. So, then when you click on any link on your website it opens up on it’s default subdomain like; appsubdomain.herokuapp.com

    I setted CNAME record according to instruction https://devcenter.heroku.com/articles/custom-domains but still, it doesn’t work.

  5. phoet Post author

    i think that you need to add the subdomains manually. perhaps it’s possible to use wildcards, but i did not test that.

    here is the configuration i use:

    > heroku domains
    Domain names for hamburg-on-ruby.herokuapp.com:
    http://www.onruby.de
    onruby.de
    hamburg.onruby.de

  6. Frans

    I’d be very careful using the “heroku config:add DATABASE_URL=”-approach, as afaik you’d be connecting to the database of another app in your brand new cedar-app, how the fuck are you going to remember that in two years?

    I just did it to test it out though, as nothing happened when I tried to push.

  7. Tom

    Great write up. I had a heroku problem where I accidentally deleted my heroku database, then tried to do heroku run rake db:migrate to recreate, but it failed, so I went with taps and pushed my local database to heroku and all is well. So, now my question is this: when I run migrations locally, do I have to run heroku run rake db:push, or should I be able to do heroku run rake db:migrate?

Comments are closed.