2

I am trying to deploy a Rails application with Capistrano. I got Capistrano more or less configured. I know it works since I already deployed another app which used SQLite as database. Now, the current one uses Postgresql and I can't figure out why Capistrano doesn't get through authentication. The error which shows up when capstrano tries to exec bundle exec rake db:migrate is the following:

PG::ConnectionBad: FATAL:  password authentication failed for user 'nameofrailsapplication'

Currently I'm trying this configuration on the server:

/etc/postgresql/9.3/main/pg_hba.conf

# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5

I fiddled around with md5 and trust but instead of the ConnectionBad error I'm getting a password error. Since I don' want Capistrano to interactively ask for a password at this point, md5 didn't get me very far.

My local config:

Capfile

require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/migrations'
require 'capistrano/postgresql'
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

The capistrano/postgresql gem seems to do it's job well, within the deploy messages I can see that it does indeed take the database name and creates a password which gets passed on to the server. To be safe I configured the database name inside deploy.rb:

from config/deploy.rb:

 # config valid only for Capistrano 3.1
lock '3.2.1'

set :application, "nameofrailsapplication"
set :pg_database, "nameofrailsapplication"
set :repo_url, "git@bitbucket.org:gituser/repo-name.git"

set :deploy_to, "/var/www/#{fetch(:application)}"
set :deploy_user, "deployers"

# Default value for :linked_files is []
set :linked_files, %w{config/database.yml}

# Default value for linked_dirs is []
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}

I suspect that the fact that the deploy_user is different then the postgresql user (same as database name) might cause some trouble here. The system user deployers does not exist in the database, nor does the database user on the system.

config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  pool: 5

development:
  <<: *default
  database: nameofrailsapplication_development
test:
  <<: *default
  #database: nameofrailsapplication_test
  database: nameofrailsapplication_test

production:
  <<: *default
  database:nameofrailsapplication
  username: nameofrailsapplication
  password: <%= ENV['NAME-OF-RAILS-APPLICATION_DATABASE_PASSWORD'] %>

Last thing I should probably mention is that I am also using the figaro gem, which copies the database.yml over to the server. For this purpose I run the following capistrano task:

namespace :figaro do
  desc "SCP transfer figaro configuration to the shared folder"
  task :setup do
    on roles(:app) do
      upload! "config/application.yml","#{shared_path}/application.yml", via: :scp
    end
  end

  desc "Symlink application.yml to the release path"
  task :symlink do
    on roles(:app) do
      execute "ln -sf #{shared_path}/application.yml #{current_path}/config/application.yml"
    end
  end
end
after "deploy:started", "figaro:setup"
after "deploy:symlink:release", "figaro:symlink"

Any suggestion greatly appreciated!

Edit 1: I set up ssh keys correctly on git and the server.

Edit 2: I can log into the DB as 'nameofrailsapplication' locally from the without any problem.

loxosceles
  • 347
  • 5
  • 21

2 Answers2

2

Actually the problem is really simple. The environment variable you are using in your database.yml configuration is not available for capistrano. There is a similar question here.

Capistrano executes remote commands via SSHKit. In the documentation of SSHKit it's mention that:

It's often a problem that programmatic SSH sessions don't have the same environment variables as interactive sessions.

You have different options to set the environment to the login shell SSHKit uses:

  1. Add your environment variables to /etc/environment. Please consider, that this variable is accessible to all everyone on the remote system. Maybe it's not a save place to store passwords.

  2. Set the variables in ~/.ssh/environment and activate PermitUserEnvironment in your /etc/ssh/sshd_config. The variables are only visible to a specific user, but they aren't to the rails application.

  3. Use the functionality of shared and linked files of Capistrano. Create a database.yml and secrets.yml in public/config/. I think this is the simplest and safest option.

Community
  • 1
  • 1
Robin
  • 8,162
  • 7
  • 56
  • 101
0

I found the solution by myself finally, actually really simple. I kind of took for granted that the capistrano/postgresql plugin was in charge of managing the whole create-user-and-login business, so it didn't cross my mind that I should probably take care of things on the server side myself.

Anyway, what I did was peeking into the database file on the server (which was created by capistrano), retrieving the capistrano-generated password and finally logging into the postgres user to change the railsuser password to the one in the file. Solved.

loxosceles
  • 347
  • 5
  • 21