Capistrano and database.yml

May 27, 2008

Finally have a good way of working with Capistrano and database.yml. Here’s what I did …

Fundamentals

Generally a Rails application will be run on at least one server and developed on many machines. The database configuration will not be the same on all the machines. In addition the database configuration on the server should be secure.

Remove database.yml from the Repository

Added config/database.yml to projects .gitignore file

Create database.yml.example

This file helps developers connect to there local database. Mine is now

base: &base
  user: root
  password: '' # only keep in here for dev machines
  adapter: mysql
  encoding: utf8
  # socket: /var/run/mysqld/mysql.sock # ubuntu
  socket: /tmp/mysql.sock # leopard
  username: #{user}
  password: #{password}

development:
  database: {appname}_dev
  <<: *base

test:
  database: {appname}_test
  <<: *base

Use Capistrano to create database.yml on the Server

This is based on this blog entry

Here we create a couple of tasks under the :db namespace to create a database configuration using the template in the ERB block. This will be populated with variables in the rest of the deployment recipe, and will prompt for a password for the database. The actual configuration will be created in the #{shared_path}/config/database.yml, so if you can ssh into the server you can look at it.

Anyhow this seems to be working fine on my boxes, and now no database passwords are in the source control tree.

#############################################################
#	Database.yml
#############################################################

require 'erb'

before "deploy:setup", :db
after "deploy:update_code", "db:symlink"

namespace :db do
  desc "Create database yaml in shared path"
  task :default do
    db_config = ERB.new <<-EOF
    base: &base
      adapter: mysql
      socket: /var/run/mysqld/mysql.sock
      username: #{user}
      password: #{password}

    development:
      database: #{application}_dev
      <<: *base

    test:
      database: #{application}_test
      <<: *base

    production:
      database: #{application}_prod
      <<: *base
    EOF

    run "mkdir -p #{shared_path}/config"
    put db_config.result, "#{shared_path}/config/database.yml"
  end

  desc "Make symlink for database yaml"
  task :symlink do
    run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
  end
end