database.yml

17 views
Skip to first unread message

Bryan Liles

unread,
Oct 1, 2006, 8:56:05 AM10/1/06
to capis...@googlegroups.com
What is the best practice for managing database.yml?

Charles Brian Quinn

unread,
Oct 1, 2006, 10:37:31 AM10/1/06
to capis...@googlegroups.com
I can't speak for best practices, but personally, I use a task that creates it:

desc "Setup Database Configuration"
task :database_configuration_setup do

# generate database configuration
database_configuration = render :template => <<-EOF
# Deployment database.yml
login: &login
adapter: #{database}
username: #{database_username}

development:
database: #{application}_development
<<: *login

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

production:
database: #{application}_production
<<: *login

EOF

# put database configuration in shared config dir
put database_configuration, "#{deploy_to}/#{shared_dir}/config/database.yml"
end


This of course means I use variables for #{database} as the adapter,
and #{database_username} and so on -- that way it builds it for me.

I call this task in after_setup so that if I ever make changes to the
setup/configuration, I can just run setup on the box (or a new box) to
set it all up for me.

I used to keep the deployment specific database.yml and copy it over,
but this way I can use the variables and build it dynamically.

hope this helps, cheers,

--
Charles Brian Quinn
self-promotion: www.seebq.com
highgroove studios: www.highgroove.com
slingshot hosting: www.slingshothosting.com

Charles Brian Quinn

unread,
Oct 1, 2006, 10:38:52 AM10/1/06
to capis...@googlegroups.com
p.s. I forgot to mention that in my after_update_code task I relink it:

desc "Tasks to execute after code update"
task :after_update_code, :roles => [:app, :db] do
# relink shared deployment database configuration
run "ln -nfs #{deploy_to}/#{shared_dir}/config/database.yml
#{release_path}/config/database.yml"
# ....
# ....
end

Adam

unread,
Oct 1, 2006, 7:35:26 PM10/1/06
to Capistrano
Hey Bryan,
You will want to think twice about checking database.yml, with
passwords, into your svn repository. I know, I know... you can give a
good argument that if an intruder can actually get to the point where
they can read your svn repository (ie; log into your machine) then they
can already do enough damage. However, as an example, most auditors
when they check company compliance for Sarbanes-Oxley (known as SOX),
will forbid you to put a password in a change management repository
where it can be ready by any user who has access to the network. There
are other examples from a legal and technical angle as to why you
should not put passwords in an open environment.

Assuming you agree with this logic ;), you can run this from within
your rails app (when you first setup):

svn move config/database.yml config/database.example
svn propset svn:ignore "database.yml" config/
# at this point, edit your database.example so it has NO
passwords (and maybe even no logins for production?)
# if you already checked in a password, it will stay in SVN even
if you change the current file.
# at that point you should create a new password for your
production db.
svn commit -m 'Moving database.yml to database.example to provide
a template for anyone who checks out
the code, and ignore 'database.yml' in the future'
svn up


at this point your svn will be fine, but none of your applications
will work! For each developer, they can have their own database.yml
with their dev information. For your production servers, and assuming
you are using capistrano, you can add this to your capistrano.rake file
(or to your own recipe file) to do the following:

desc "create a shared/resources directory for common, non-svn files
(like database.yml)"
task :after_setup, :roles => [:app, :db, :web] do
run <<-CMD
mkdir -p -m 777 #{shared_path}/resources &&
mkdir -p -m 777 #{shared_db} &&
touch #{shared_path}/resources/database.yml
chmod 600 #{shared_path}/resources/database.yml
CMD
end

desc "create a symlink for the database.yml file for the current
project (since it isn't in source control)"
task :after_update_code, :roles => [:app, :db, :web] do
run <<-CMD
ln -nfs #{shared_path}/resources/database.yml
#{release_path}/config/database.yml
CMD
end


and then put the information you need for your production environment
in the #{shared_path}/resources/database.yml

It sounds complicated to setup, but once it is you won't have to touch
it or even think about it again until you rotate a production password.
If more than 1 person works on the project, this can also make
development easier.

Hope that wasn't *too* complicated!

Adam

Jason Perry

unread,
Oct 2, 2006, 8:44:09 AM10/2/06
to Capistrano
Hi Guys, I thought I might share part of my solution as well.

desc "Create config/database.yml in shared"
task :after_setup, :roles => [:app] do
# prompt user for password
set :db_password, Capistrano::CLI.password_prompt("DB password:")


database_configuration = render :template => <<-EOF

---
production:
adapter: mysql
database: myapp_production
host: gecko.fcit.usf.edu
username: myapp_user
password: <%= db_password %>
EOF

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

One thing I've been meaning to do--change this task to read in the
other settings from my local database.yml (assuming I can do that, I
haven't experimented with where cap is running from) and prompt for the
password only if its blank there, which is exactly how my db.yml is set
up. Seems DRYer to me to do it that way.

Hell, if that doesnt work, I could probably just set it up to copy over
the template database.yml and insert the password into that. Hrmm, that
might even be a better idea.

Reply all
Reply to author
Forward
0 new messages