Capistrano - can't deploy my database.yml - ruby

When I try to deploy my app with capistrano, I'll get this error:
failed: "sh -c 'cp
/var/www/my_app/releases/20120313115055/config/database.staging.yml
/var/www/my_app/releases/20120313115055/config/database.yml'" on
IP_ADDR
My database.yml ie empty, database.staging.yml:
production:
adapter: mysql2
encoding: utf8
reconnect: false
database: my_db
pool: 15
username: my_user_name
password: my_pass
host: localhost
in the /confing/deploy are files "production" "staging"
What am I missing here/where should I look for a failure? The credentials to database on the server should be right.
EDIT - here is my deploy
set :application, "my_app"
set :repository, "https://IP_ADDR/svn/my_app"
set :scm, :subversion
set :scm_username, 'my_name'
set :scm_password, 'my_pass'
default_run_options[:pty] = true
set :user, "my_name"
set :domain, 'IP_ADDR'
set :deploy_to, "/var/www/my_app"
set :use_sudo, false
set :deploy_via, :remote_cache
#set :keep_releases, 1
set :rails_env, 'production'
role :web, domain
role :app, domain
role :db, domain, :primary => true # This is where Rails migrations will run
namespace :deploy do
task :build_gems, :roles => :app do
desc "Building gems"
run "cd #{release_path} && bundle install --deployment"
end
task :migrations do
desc "Migrating database"
run "cd #{release_path} && rake db:migrate RAILS_ENV=production"
end
[:start, :stop].each do |t|
desc "#{t} task is a no-op with passenger"
task t, :roles => :app do ; end
end
desc "Restarting passenger with restart.txt"
task :restart, :roles => :app, :except => { :no_release => true } do
run "touch #{release_path}/tmp/restart.txt"
end
after "deploy:update_code", "deploy:build_gems", "db:copy_configuration", "config:copy", "deploy:migrations", "deploy:cleanup"
after "deploy:update", "bluepill:copy_config", "bluepill:restart"
end
namespace :db do
task :copy_configuration do
run "cp #{release_path}/config/database.staging.yml #{release_path}/config/database.yml"
end
end
namespace :config do
task :copy do
run "cp #{release_path}/config/config.staging.yml #{release_path}/config/config.yml"
end
end
namespace :bluepill do
desc "Restart bluepill process"
task :restart, :roles => [:app] do
run "#{release_path}/script/delayed_job stop"
sudo "/etc/init.d/bluepill.sh restart"
end
#desc "Load bluepill configuration and start it"
##task :start, :roles => [:app] do
# sudo "/etc/init.d/bluepill.sh start"
#end
desc "Prints bluepills monitored processes statuses"
task :status, :roles => [:app] do
sudo "bluepill status"
end
desc "Copy config"
task :copy_config, :roles => [:app] do
run "cp #{release_path}/config/bluepill/configuration.rb /srv/script/bluepill.rb"
end
end
The problem:
cp: cannot stat `/var/www/my_app/releases/20120313144907/config/database.staging.yml': No such file or directory

I'm not sure how to solve your problem. It looks like database.staging.yml is not being deployed, so there's nothing for it to copy over.
I think there's a better workflow, though. Things like settings and database configs do not typically change between deployments, so those things can go in the shared folder of all the capistrano releases. Typically, you don't want your database.yml to be in your repo either since it's sensitive information. You can satisfy both of these things by excluding config/database.yml in your .gitignore.
This requires you to do a one time set up on your servers. You need create a database.yml at your_app_path/shared/config. Shared is a sibling to current and releases.
Your deploy.rb should have a task that symlinks the newly deployed release's database.yml to the on in the shared directory. Like this:
before "deploy:assets:precompile" do
run ["ln -nfs #{shared_path}/config/settings.yml #{release_path}/config/settings.yml",
"ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml",
"ln -fs #{shared_path}/uploads #{release_path}/uploads"
].join(" && ")
end
This means that your repo will contain no database.yml files. Since they are probably already in your repo. You'll have to git rm them, commit. Add them to the .gitignore and commit that.

In Capistrano 3, linking files is built-in. John's answer is simply:
In the shared/ folder create config/database.yml
In config/deploy.rb use this line
set :linked_files, fetch(:linked_files, []).push('config/database.yml')
This does what John was saying.

If you don't need to "reference application objects or methods"(1) during precompile then you might be OK with setting config.assets.initialize_on_precompile to false in config/application.rb

Related

Capistrano deploy.rb can't access task defined in stage file

I'm trying to put together a capistrano recipe for my app that basically clones the git repo locally, does some build processing and then rsyncs to the remote server.
I have 2 environments - dev and prod:
deploy.rb
deploy/dev.rb
deploy/prod.rb
I'm getting this error:
$ cap dev deploy
(Backtrace restricted to imported tasks)
cap aborted!
Don't know how to build task 'stop_server'
Tasks: TOP => dev
(See full trace by running task with --trace)
Why does the deploy not know how to build task stop_server if it's in the same namespace (deploy) in dev.rb?
Capfile
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
#require 'capistrano/deploy' # COMMENTED OUT B/C I'M TRYING TO BUILD LOCALLY INSTEAD OF DOING A GIT CLONE ON THE REMOTE SERVER
# Load custom tasks from `lib/capistrano/tasks' if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
deploy.rb
# config valid only for current version of Capistrano
lock '3.3.5'
set :repo_url, 'mygiturl'
# Default value for :pty is false
set :pty, true
set :deploy_dir, Dir.pwd
set :tmp_dir, "#{fetch(:deploy_dir)}/tmp"
set :output_dir, "#{fetch(:deploy_dir)}/output"
namespace :deploy do
desc 'Kick off the deploy'
task :init do
invoke 'deploy:create_tmp_dir'
end
... other tasks...
after :create_tmp_dir, :fetch_code
after :fetch_code, :build
after :build, :move_output
after :move_output, :stop_server
end
desc 'Deploy a new release'
task :deploy do
invoke 'deploy:init'
end
dev.rb
role :app, fetch(:application)
role :web, fetch(:application)
role :db, fetch(:application)
set :application, 'myapp'
set :env, 'dev'
set :ip, '123.456.78.901'
set :user, 'myuser'
set :deploy_to, '/var/www/myapp'
set :ssh_options, {
user: fetch(:user),
keys: %w(~/.ssh/id_rsa),
forward_agent: true,
auth_methods: %w(publickey),
port: 22
}
namespace :deploy do
desc "Stops the node forever server"
task :stop_server do
on roles(:app) do
puts '**** STOPPING THE NODE SERVER *****'
execute 'sudo /etc/init.d/myapp stop; true' # The "; true" ignores any error that may occur if there is no forever process running
end
end
desc "Restarts the forever server"
task :start_server do
on roles(:app) do
puts '**** STARTING THE NODE SERVER *****'
execute 'sudo /etc/init.d/myapp start'
end
end
end
The problem is that Capistrano initializes by loading deploy.rb first; then it loads dev.rb.
At the time that Capistrano parses this line:
after :move_output, :stop_server
It does not know what :stop_server refers to (since it hasn't loaded dev.rb yet). Hence the error message you are seeing:
Don't know how to build task 'stop_server'
One easy workaround is to declare an empty :stop_server task in deploy.rb.
namespace :deploy do
# "stub" the task, to be defined later in dev.rb
task :stop_server
after : move_output, :stop_server
end
Then when Capistrano later loads dev.rb, the real implementation of :stop_server will get slotted in.
Now when you run cap dev deploy you should get the desired result.

Capistrano 3 change ssh_options inside task

I trying to run capistrano v.3 task in same stage with diferent ssh_options.
my production.rb say:
set :stage, :production
set :user, 'deploy'
set :ssh_options, { user: 'deploy' }
With this configuration capistrano connect with user deploy which is correct for the rest of taks. But I need connect it for one specific task with an_other_user wich is well configured in server.
Then my recipe say:
...
tasks with original user
...
task :my_task_with_an_other_user do
set :user, 'an_other_user'
set :ssh_options, { user: 'an_other_user' }
on roles(:all) do |host|
execute :mkdir, '-p', 'mydir'
end
end
...
other tasks with original user
...
When execute:
cap production namespace:my_task_with_an_other_user
capistrano make ssh conexion with original :user "deploy" (the user declared in production.rb).
How can I change the user and/or ssh_options it inside task?
Capistrano 3
I had hard time finding out a solution. But the solution is much nicer than version 2. Cap team has done a great job. Make sure you have updated Capistrano to 3.2.x+ Here's the trick:
# in config/deploy/production.rb, or config/deploy/staging.rb
# These roles are used for deployment that works with Cap hooks
role :app, %w{deploy#myserver.com}
role :web, %w{deploy#myserver.com}
role :db, %w{deploy#myserver.com}
# Use additional roles to run side job out side Capistrano hooks
# 'foo' is another ssh user for none-release purpose tasks (mostly root tasks).
# e.g. user 'deploy' does not have root permission, but 'foo' has root permission.
# 'no_release' flag is important to flag this user will skip some standard hooks
# (e.g. scm/git/svn checkout )
role :foo_role, %w{foo#myserver.com}, no_release: true
Make sure both 'deploy' & 'foo' user can ssh into the box. Within your tasks, use the on keyword:
task :restart do
on roles(:foo_role) do
sudo "service nginx restart"
end
end
task :other_standard_deployment_tasks do
on release_roles(:all) do
# ...
end
end
Other gotchas:
Make sure some Capistrano tasks skips the additional no release role you added. Otherwise, it might cause file permission issues during deployment. E.g. capistrano/bundler extension need to override the default bundler_roles
set :bundler_roles, %w(web app db) # excludes the no release role.
Read more about no_release flag: related Github issue.
Capistrano 2
I used to have a custom functions to close and reconnect ssh sessions.
Reference Paul Gross's Blog
Place the following methods in deploy.rb. Call with_user to switch ssh session. Slightly simplified version:
def with_user(new_user, &block)
old_user = user
set :user, new_user
close_sessions
yield
set :user, old_user
close_sessions
end
def close_sessions
sessions.values.each { |session| session.close }
sessions.clear
end
Usage:
task :update_nginx_config, :roles => :app do
with_user "root" do
sudo "nginx -s reload"
end
end
Answer of #activars didn't work for me. Because when I defined several roles for one environment - only one was deployed :(
So my solution was to create several enviroments, e.g. production.rb and productionroot.rb.
productionroot has content with no_release=true flag - just as you've specified:
server '146.120.89.81', user: 'root', roles: %w{foo_role}, no_release: true
After that I've created sh script which runs
#/usr/bin/env bash
bundle exec cap production deploy
bundle exec cap productionroot deploy

Capistrano 2, SSH, Mac, EC2 - Permission Denied on Write

So I'm using WP-Stack and trying to deploy from my local machine to an EC2 instance.
Ive follow capistrano's SSH literature and I can for instance get the server info by just running SSH and the user/IP
I have created the user 'deploy' on my EC2 server, I have ensured it has permissions to write the folders I want (infact I can go in and manually from CL do "mkdir /production/" without problems to create the directory Capistrano is trying to make. Ive searched and searched online and I can't find anything specific to my issue. Most seem to be folder's having the wrong errors.
So I have this in by deploy.rb
#
set :user, "deploy"
set :use_sudo, false
set :deploy_via, :remote_cache
set :copy_exclude, [".git", ".gitmodules", ".DS_Store", ".gitignore"]
set :keep_releases, 5
after "deploy:update", "deploy:cleanup"
after "deploy:update_code", "shared:make_shared_dir"
after "deploy:update_code", "shared:make_symlinks"
after "deploy:update_code", "db:make_config"
after "deploy", "memcached:update"
# Pull in the config file
loadFile 'config/config.rb'
and in config
# Customize this file, and then rename it to config.rb
set :application, "myapp"
set :repository, "git#bitbucket.org:user/mygit.git"
set :scm, :git
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
# Using Git Submodules?
set :git_enable_submodules, 1
# This should be the same as :deploy_to in production.rb
set :production_deploy_to, '/var/www/vhost/i-16852366/production/'
# The domain name used for your staging environment
set :staging_domain, 'stage.domain.com'
# Database
# Set the values for host, user, pass, and name for both production and staging.
set :wpdb do
{
:production => {
:host => 'user.us-east-1.rds.amazonaws.com',
:user => 'user',
:password => 'pass',
:name => 'name',
},
:staging => {
:host => 'user.us-east-1.rds.amazonaws.com',
:user => 'user',
:password => 'pass',
:name => 'name2',
}
}
end
# You're not done! You must also configure production.rb and staging.rb
and finally for production
# This file is only loaded for the production environment
# Customize it and rename it as production.rb
# Where should the site deploy to?
set :deploy_to, '/var/www/vhost/i-16852366/production/'
# Now configure the servers for this environment
# OPTION 1
# role :web, "your web server IP address or hostname here"
# role :web, "second web server here"
# role :web, "third web server here, etc"
# OPTION 2
# If your web servers are the same as your memcached servers,
# comment out all the "role" lines and use "server" lines:
server "54.242.153.162", :web, :memcached
But when I try 'cap deploy:setup' or 'cap deploy:check' it can't write to folders I can create from command prompt with the deploy user
servers: ["54.242.153.162"]
[54.242.153.162] executing command
** [out :: 54.242.153.162] mkdir: cannot create directory `/var/www/vhost': Permission denied
** [out :: 54.242.153.162] mkdir: cannot create directory `/var/www/vhost': Permission denied
** [out :: 54.242.153.162] mkdir: cannot create directory `/var/www/vhost': Permission denied
command finished in 600ms
failed: "sh -c 'mkdir -p /var/www/vhost/i-16852366/production/ /var/www/vhost/i- 16852366/production/releases /var/www/vhost/i-16852366/production/shared && chmod g+w /var/www/vhost/i-16852366/production/ /var/www/vhost/i-16852366/production/releases /var/www/vhost/i-16852366/production/shared'" on 54.242.153.162
Any ideas? Is it due to the .tem file not being used? I can't find a tutorial that shows how to use it if so.
Access via SSH to an EC2 instance uses a regular user - for the Amazon AMI, for example, you will log in as ec2-user.
/var/www is owned by root, so the ec2-user will not be able to create a subdirectory.
I'd start by changing this line to true:
set :use_sudo, false

Argument error while deploying rails app via capistrano to bluehost

I have build a sample app using rails and trying to deploy it using capistrano to bluehost.
But I am failing to do so. I followed the instructions mentioned in this http://vasil-y.com/2012/08/21/rails-capistrano-git-bluehost/
This is the contents of my config/deploy.rb:
require 'bundler/capistrano'
set :application, "rails_scaffold"
# BlueHost SSH user
set :user, "username"
# App Domain
set :domain, "example.com"
# We don't need sudo on BlueHost
set :use_sudo, false
# git is our SCM
set :scm, :git
# master is our default git branch
set :branch, "master"
# Use local git repository
set :repository, "#{domain}:/home/#{user}/rails_apps/#{application}"
set :local_repository, "."
# Checkout, compress and send a local copy
set deploy_via, :copy
set deploy_to, "/home/#{user}/rails_apps/#{application}"
# We have all components of the app on the same server
server domain, :app, :web, :db, :primary => true
namespace :deploy do
task :start do ; end
task :stop do ; end
# Touch tmp/restart.txt to tell Phusion Passenger about new version
task :restart, :roles => :app, :except => { :no_release => true } do
run "touch #{File.join(current_path, 'tmp', 'restart.txt')}"
end
end
# Clean-up old releases
after "deploy:restart", "deploy:cleanup"
But when I run the cap deploy:setup command, I get the following error:
/home/swaroop/.rvm/gems/ruby-1.9.3-p362/gems/capistrano-2.14.2/lib/capistrano/configuration/variables.rb:22:in `set': invalid variable `/u/apps/rails_scaffold' (variables must begin with an underscore, or a lower-case letter) (ArgumentError)
It says the application name must begin with an underscore or lowercase alphabets. And my application name looks like it is valid.
What am I doin wrong here?
Thank You
A couple of your set calls have arguments which are not symbols:
set deploy_via, :copy
set deploy_to, "/home/#{user}/rails_apps/#{application}"
Those should be:
set :deploy_via, :copy
set :deploy_to, "/home/#{user}/rails_apps/#{application}"
(Note the colons before deploy_via and deploy_to)
You can see why it might look related to your :application variable if we inspect what is happening in the line containing :deploy_to: it first calls the deploy_to method (since you're missing the colon, it looks like a method call), and deploy_to defaults to "/u/apps/#{application}" in the Capistrano source code:
_cset(:deploy_to) { "/u/apps/#{application}" }
So really, your code is effectively trying trying to run this:
set "/u/apps/#{application}", "/home/#{user}/rails_apps/#{application}"
but "/u/apps/#{application}" is not a valid variable name in Capistrano. Adding colons to those lines should fix it.

Ubuntu 10.04 Rails deploy - Why is capistrano failing to deploy to server?

I am trying to deploy with capistrano. RVM is installed on the server and the ruby version is 1.93p385.
Here is the log of cap production deploy:
http://pastie.org/private/vs336nrgejpwdkuelufnma#
Why is capistrano failing to deploy?
Here is the deploy file:
require "rvm/capistrano"
require "bundler/capistrano"
set :rvm_ruby_string, "1.9.3-p385"
set :rvm_type, :user #Should the user by the username?
require "capistrano/ext/multistage"
set :http_server, :apache2
set :rake, "#{rake} --trace"
set :application, "app"
set :user, "myuser" # The server's user for deploys
set :ruby_version, "1.9.3-p385"
set :scm, "git"
set :repository, "my git repo here"
set :deploy_to, "/var/www/#{application}"
set :deploy_via, :remote_cache
set :use_sudo, true
default_run_options[:pty] = true # Must be set for the password prompt from git to work
ssh_options[:forward_agent] = true
set :nodejs, true
# if you want to clean up old releases on each deploy uncomment this:
after "deploy:restart", "deploy:cleanup"
The server is an Ubuntu 10.04 LTS
** [out :: server] No such file or directory - /var/www/app/releases/20130216170229/config/database.yml
Does this path exist on the server? You might need to create the /var/www/app/releases portion by hand, which capistrano will then deploy into.
It is a common pattern to .gitignore database.yml for capistrano deployment. The database config then resides in <:deploy_to>/shared/config/. The you use this cap task to symlink the db config in your release directory:
namespace :deploy do
task :start do ; end
task :stop do ; end
desc "Symlink shared folders on each deployment"
task :symlink_shared do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
end
before "deploy:assets:precompile", "deploy:symlink_shared"

Resources