File backup for deploying a rails app with capistrano - ruby-on-rails-4

I am deploying my rails 4 application with capistrano onto an Ubuntu 14.04 server. This is the deploy.rb I am using currently:
server 'ip', port: port, roles: [:web, :app, :db], primary: true
set :repo_url, 'git git'
set :application, 'appname'
set :user, 'user'
set :puma_threads, [4, 16]
set :puma_workers, 0
set :pty, true
set :use_sudo, false
set :stage, :production
set :deploy_via, :remote_cache
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.error.log"
set :puma_error_log, "#{release_path}/log/puma.access.log"
set :ssh_options, { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true # Change to false when not using ActiveRecord
## Defaults:
# set :scm, :git
# set :branch, :master
# set :format, :pretty
# set :log_level, :debug
# set :keep_releases, 5
## Linked Files & Directories (Default None):
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/uploads}
namespace :puma do
desc 'Create Directories for Puma Pids and Socket'
task :make_dirs do
on roles(:app) do
execute "mkdir #{shared_path}/tmp/sockets -p"
execute "mkdir #{shared_path}/tmp/pids -p"
end
end
before :start, :make_dirs
end
namespace :deploy do
desc "Make sure local git is in sync with remote."
task :check_revision do
on roles(:app) do
unless `git rev-parse HEAD` == `git rev-parse origin/master`
puts "WARNING: HEAD is not the same as origin/master"
puts "Run `git push` to sync changes."
exit
end
end
end
desc 'Initial Deploy'
task :initial do
on roles(:app) do
before 'deploy:restart', 'puma:start'
invoke 'deploy'
end
end
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
invoke 'puma:restart'
end
end
before :starting, :check_revision
after :finishing, :compile_assets
after :finishing, :cleanup
after :finishing, :restart
end
namespace :sake do
desc "Run a task on a remote server."
# run like: cap staging sake:invoke task="a_certain_task"
task :invoke do
on roles(:all) do |h|
execute "cd #{fetch(:deploy_to)}/current && bundle exec rake #{ENV['task']} RAILS_ENV=#{fetch(:rails_env)}"
end
end
end
# ps aux | grep puma # Get puma pid
# kill -s SIGUSR2 pid # Restart puma
# kill -s SIGTERM pid # Stop puma
I had an issue in this file so that my shared/public folder got overwritten and I lost a lot of uploaded images. Due to this loss I am now considering to implement some way of creating a backup outside of the application directory on the server for uploaded files.
Is it possible to create some kind of automated routine that copies the current shared folder to a save space on the server before capistrano deploys the new version?
Regards.

Yes, you probably want to hook into Capistrano's deploy:started step to perform your backup before the new version is deployed.
Define a task that performs your backup:
task :backup_shared_public do
on roles(:all) do
# Very basic backup technique. YMMV!
execute "mkdir -p ~/public_backups"
execute "cp -Rp #{shared_path.join('public')} ~/public_backups/#{Time.now.to_i}"
end
end
And then tell Capistrano to execute it before every deploy:
after "deploy:started", "backup_shared_public"

Related

Keep public/uploads folder of the last version with capistrano deploy

I am using Rails 4 with Capistrano to deploy on an Ubuntu 14.04 server and my users are able to upload files which are stored in /public/uploads. This folder should always be kept for new versions and should never get files from the git repository.
After reading a few guides I followed those steps:
Adding this to my deploy.rb:
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
set :linked_dirs, fetch(:linked_dirs) + %w{public/uploads}
Adding this to my /.gitignore:
# Ignore uploads
/public/uploads
Deleting the folder in my current git repository:
git rm -r --cached public/uploads
Now if I run cap deploy:setup I get this error:
Stage not set, please call something such as `cap production deploy`, where production is a stage you have defined.
If I define the stage production the deploy begins but I aborts very early:
cap aborted!
Don't know how to build task 'deploy:setup' (see --tasks)
And if I use my regular command to deploy cap production deploy everything works but the public/uploads/ folder will be renewed as before those changes.
Not sure if I am just missing the setup command or if I made mistakes in setting this up. My deploy.rb looks like this:
# Change these
server 'ip', port: port, roles: [:web, :app, :db], primary: true
set :repo_url, 'git#github.com:blabla/bla.git'
set :application, 'blub'
set :user, 'blib'
set :puma_threads, [4, 16]
set :puma_workers, 0
set :pty, true
set :use_sudo, false
set :stage, :production
set :deploy_via, :remote_cache
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.error.log"
set :puma_error_log, "#{release_path}/log/puma.access.log"
set :ssh_options, { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true # Change to false when not using ActiveRecord
## Defaults:
# set :scm, :git
# set :branch, :master
# set :format, :pretty
# set :log_level, :debug
# set :keep_releases, 5
## Linked Files & Directories (Default None):
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
set :linked_dirs, fetch(:linked_dirs) + %w{public/uploads}
#set :linked_files, %w{config/database.yml}
namespace :puma do
desc 'Create Directories for Puma Pids and Socket'
task :make_dirs do
on roles(:app) do
execute "mkdir #{shared_path}/tmp/sockets -p"
execute "mkdir #{shared_path}/tmp/pids -p"
end
end
before :start, :make_dirs
end
namespace :deploy do
desc "Make sure local git is in sync with remote."
task :check_revision do
on roles(:app) do
unless `git rev-parse HEAD` == `git rev-parse origin/master`
puts "WARNING: HEAD is not the same as origin/master"
puts "Run `git push` to sync changes."
exit
end
end
end
desc 'Initial Deploy'
task :initial do
on roles(:app) do
before 'deploy:restart', 'puma:start'
invoke 'deploy'
end
end
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
invoke 'puma:restart'
end
end
before :starting, :check_revision
after :finishing, :compile_assets
after :finishing, :cleanup
after :finishing, :restart
end
namespace :sake do
desc "Run a task on a remote server."
# run like: cap staging sake:invoke task="a_certain_task"
task :invoke do
on roles(:all) do |h|
execute "cd #{fetch(:deploy_to)}/current && bundle exec rake #{ENV['task']} RAILS_ENV=#{fetch(:rails_env)}"
end
end
end
# ps aux | grep puma # Get puma pid
# kill -s SIGUSR2 pid # Restart puma
# kill -s SIGTERM pid # Stop puma

Capistrano 3.4 Deployment Problems

I have inherited a Rails project and I am unable to deploy it using the supplied instructions using Capistrano. I am not familiar with capistrano at all.
Whatever I try I always get the following error message
(Backtrace restricted to imported tasks)
cap aborted!
ArgumentError: wrong number of arguments (1 for 2)
Tasks: TOP => production
(See full trace by running task with --trace)
This includes
$ bundle exec cap -T
$ bundle exec cap production deploy
I am following the guide here https://github.com/capistrano/capistrano
I have starred out important info but here is the a copy of the config/deploy/staging.rb
role :app, %w{deploy#**.**.**.**:****}
role :web, %w{deploy#**.**.**.**:****}
role :db, %w{deploy#**.**.**.**:****}
set :branch, 'develop'
set :deploy_to, '/var/www/soreen.staged.ws'
set :ssh_options, {
keepalive: true,
keepalive_interval: 60 #seconds
}
and here is Capfile
# Load DSL and Setup Up Stages
require 'capistrano/setup'
# Includes default deployment tasks
require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/migrations'
require 'capistrano/rails/assets'
require 'capistrano/rails/collection'
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
and here is config/deploy.rb
# config valid only for current version of Capistrano
lock '3.4.0'
set :application, 'Soreen'
set :repo_url => "****************"
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
set :rbenv_type, :user # or :system, depends on your rbenv setup
set :rbenv_ruby, '2.1.2'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=# {fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w{rake gem bundle ruby rails}
set :rbenv_roles, :all # default value
namespace :deploy do
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
# Your restart mechanism here, for example:
execute :mkdir, '-p', "#{ release_path }/tmp"
execute :touch, release_path.join('tmp/restart.txt')
end
end
after :publishing, :restart
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
end
end
end
Please help !
You can get a backtrace for the error using the following:
bundle exec cap --backtrace -T
That will give you more information. Likely this is a syntax error in your configuration.

No such file or directory - connect(2) for "/tmp/puma-status-1439451994589-14316"

I want to deploy my rails through Capistrano with Puma and Nginx. I have configured deploy.rb for puma and added required gems in gem files.
I am able to run initial deploy command as 'cap production deploy:initial' and able to access my rails app as described below.
But when I want to deploy some new changes or restart puma it fails and gave this error.
Gemfile:
gem 'capistrano', '~> 3.4.0'
gem 'capistrano-rvm', require: false
gem 'capistrano-rails', require: false
gem 'capistrano-bundler', require: false
gem 'capistrano3-puma', require: false
# gem 'capistrano-passenger', require: false
gem 'capistrano-ext', require: false
gem 'capistrano-faster-assets', '~> 1.0.2'
Capfile:
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
require 'capistrano/rails'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/faster_assets'
require 'capistrano/rvm'
require 'capistrano/puma'
require 'capistrano/puma/workers'
require 'capistrano/puma/nginx'
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
deploy.rb
# Puma Server Configuration
set :puma_threads, [4, 16]
set :puma_workers, 1
# Don't change these unless you know what you're doing
set :pty, true
set :use_sudo, false
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"
# set :puma_conf, "#{shared_path}/puma.rb"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.error.log"
set :puma_error_log, "#{release_path}/log/puma.access.log"
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true
namespace :puma do
desc 'Create Directories for Puma Pids and Socket'
task :make_dirs do
on roles(:app) do
execute "mkdir #{shared_path}/tmp/sockets -p"
execute "mkdir #{shared_path}/tmp/pids -p"
end
end
before :start, :make_dirs
end
namespace :deploy do
desc "Make sure local git is in sync with remote."
task :check_revision do
on roles(:app) do
unless `git rev-parse HEAD` == `git rev-parse origin/capistrano`
puts "WARNING: HEAD is not the same as origin/capistrano"
puts "Run `git push` to sync changes."
exit
end
end
end
desc 'Initial Deploy'
task :initial do
on roles(:app) do
before 'deploy:restart', 'puma:start'
invoke 'deploy'
end
end
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
invoke 'puma:restart'
end
end
before :starting, :check_revision
after :finishing, :compile_assets
after :finishing, :cleanup
after :finishing, :restart
end
I have also used the below command to generate template for Puma and Nginx as below.
rails g capistrano:nginx_puma:config
I have run below commands to deploy my rails to EC2 instance (with Ubuntu)
cap production deploy:check
cap production puma:config
cap production puma:nginx_config
cap production deploy:initial
Now, I want to deploy some changes with below code.
cap production deploy
But I am getting the error as below.
(Backtrace restricted to imported tasks)
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as ubuntu#54.175.134.149: bundle exit status: 1
bundle stdout: No such file or directory - connect(2) for "/tmp/puma-status-1439451994589-14316"
bundle stderr: Nothing written
SSHKit::Command::Failed: bundle exit status: 1
bundle stdout: No such file or directory - connect(2) for "/tmp/puma-status-1439451994589-14316"
bundle stderr: Nothing written
Tasks: TOP => deploy:restart
(See full trace by running task with --trace)
Please help!
Thanks
I found one workaround to fix this issue.
Just add the snippet below to your deploy.rb file.
It will override puma restart task.
Rake::Task["puma:restart"].clear_actions
namespace :puma do
task :restart do
on roles(:all) do
execute "RACK_ENV=#{fetch(:rails_env)} #{fetch(:rvm_binary)} #{fetch(:rvm_ruby_version)} do pumactl -S #{shared_path}/tmp/pids/puma.state restart"
end
end
end

Rails 4, capistrano 3, delayed_job - can't find bin/delayed_job on one of the servers

When i deploy to pre server everything's woking fine. But if i try to deploy to staging server i get this error:
bundler: command not found: bin/delayed_job
file - config/deploy/staging.rb
set :rails_env, 'staging'
set :eager_load, :true
set :unicorn_rack_env, 'staging'
role :app, %w{deploy#x.x.x.x}
role :web, %w{deploy#x.x.x.x}
role :db, %w{deploy#x.x.x.x}
set :rvm_type, :auto # Defaults to: :auto
set :rvm_ruby_version, '2.1.2'
set :rails_env, 'staging'
set :eager_load, :true
role :app, %w{deploy#x.x.x.}
role :web, %w{deploy#x.x.x.}
role :db, %w{deploy#x.x.x.}
set :rvm_type, :auto # Defaults to: :auto
set :rvm_ruby_version, '2.1.2'
set :deploy_to, '/var/www/app'
server 'x.x.x', user: 'deploy', roles: %w{web app} , port: 222
set :unicorn_pid, ->{ "#{deploy_to}/shared/tmp/pids/unicorn.pid" }
set :scm, :git
set :ssh_options, { user: 'superman' }
set :keep_releases, 5
restart of delayed jobs -
namespace :delayed_job do
def args
fetch(:delayed_job_args, "")
end
def delayed_job_roles
fetch(:delayed_job_server_role, :app)
end
desc 'Stop the delayed_job process'
task :stop do
on roles(delayed_job_roles) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :bundle, :exec, :'bin/delayed_job', :stop
end
end
end
end
desc 'Start the delayed_job process'
task :start do
on roles(delayed_job_roles) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :bundle, :exec, :'bin/delayed_job', args, :start
end
end
end
end
desc 'Restart the delayed_job process'
task :restart do
on roles(delayed_job_roles) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :bundle, :exec, :'bin/delayed_job', args, :restart
end
end
end
end
end
Could you please give me a hand in this issue ? Thanks in advance!
UPDATE 1
More info on this error :
lib/capistrano/tasks/delayed_job.rake:33 which is execute :bundle, :exec, :'bin/delayed_job', args, :restart
You should run once on destination server:
bundle exec rails generate delayed_job
This will generate delayed_job executable script in shared/bin
Check if you can see delayed_job on your staging server in #{deploy_to}/shared/bin/
If it's not there, copy it there from your project's bin folder.
In addition to operations in answer by Rider. Following will perform 'bundle exec rails generate delayed_job' on remote if bin/delayed_job is missing there. Put it in config/deploy.rb file.
namespace :delayed_job do
desc "Install Deployed Job executable if needed"
task :install do
on roles(delayed_job_roles) do |host|
within release_path do
# Only install if not already present
unless test("[ -f #{release_path}/#{delayed_job_bin} ]")
with rails_env: fetch(:rails_env) do
execute :bundle, :exec, :rails, :generate, :delayed_job
end
end
end
end
end
before :start, :install
before :restart, :install
end
This is happening because the delayed_job executable is missing on the server. It should exist in the bin directory. To fix this you should generate the executable on your development machine and check it in to source control.
This command will generate the executable for you:
bundle exec rails generate delayed_job
Its better to use Capistrano::DelayedJob Gem
Delayed Job support for Capistrano 3.x
Add this line to your application's Gemfile:
gem 'capistrano3-delayed-job', '~> 1.0'
Require in Capfile to use the default task:
require 'capistrano/delayed-job'
Add this to your deploy.rb file
after 'deploy:published', 'restart' do
invoke 'delayed_job:restart'
end
For more configurable options https://github.com/platanus/capistrano3-delayed-job
Please check if you setup your rails_env system variable correctly.

Capistrano 3 not deploy and show this error SSHKit::Command::Failed: rake stdout: Nothing written

I have used rails 4 and Capistrano 3. When i depoly with Capistrano fail during rake assets:precompile and show following error
INFO [1c9c2531] Running ~/.rvm/bin/rvm default do bundle exec rake assets:precompile on 107.170.67.113
cap aborted!
SSHKit::Command::Failed: rake stdout: Nothing written
rake stderr: Nothing written
Tasks: TOP => deploy:assets:precompile
(See full trace by running task with --trace)
I'm newbie on rails and server setup so where am i missing.I don't know
Here my depoly.rb
SSHKit.config.command_map[:rake] ||= "bundle exec rake"
# config valid only for Capistrano 3.1
lock '3.0.1'
set :application, 'PCA'
set :repo_url, 'git#github.com:3lackRos3/pca.git'
# Default branch is :master
# ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call
# Default deploy_to directory is /var/www/my_app
set :deploy_to, '/home/pca/app/pca'
set :deploy_user, 'pca'
set :rvm_ruby_string, ENV['GEM_HOME'].gsub(/.*\//,"")
set :rvm_type, :user
set :rvm_bin_path, '/usr/local/rvm/bin'
# set :default_environment, {
# 'RBENV_ROOT' => '/usr/local/rbenv',
# 'PATH' => "/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH"
# }
# set :default_environment, {
# 'PATH' => "$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
# }
# set :rbenv_ruby, "2.1.1"
# set :rbenv_ruby_dir, -> { "#{fetch(:rbenv_path)}/versions/#{fetch(:rbenv_ruby)}" }
# set :rbenv_map_bins, %w{rake gem bundle ruby rails}
# Default value for :scm is :git
set :scm, :git
set :ssh_options, { forward_agent: true }
#set :ssh_options, proxy: Net::SSH::Proxy::Command.new('ssh pca#107.170.67.113 -W %h:%p')
# Default value for :format is :pretty
# set :format, :pretty
set :log_level, :info
# Default value for :log_level is :debug
# set :log_level, :debug
# Default value for :pty is false
set :pty, true
# 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}
# SSHKit.config.command_map[:rake].sub!(/\(.*\)rake/, "\1bundle exec rake")
# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
# Default value for keep_releases is 5
# set :keep_releases, 20
after "deploy", "deploy:cleanup"
namespace :deploy do
desc 'Restart application'
task :restart do
# on roles(:app), in: :sequence, wait: 5 do
# Your restart mechanism here, for example:
# execute :touch, release_path.join('tmp/restart.txt')
# end
end
after :publishing, :restart
after :restart, :clear_cache do
# on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
# end
end
after :finishing, 'deploy:cleanup'
end
Here my capfile
# Load DSL and Setup Up Stages
require 'capistrano/setup'
# Includes default deployment tasks
require 'capistrano/deploy'
#require 'rvm1/capistrano3'
#require 'capistrano/rvm'
# Includes tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
# https://github.com/capistrano/rvm
# https://github.com/capistrano/rbenv
# https://github.com/capistrano/chruby
# https://github.com/capistrano/bundler
# https://github.com/capistrano/rails
#
require 'capistrano/rvm'
# require 'capistrano/rbenv'
# require 'capistrano/chruby'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/rails'
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
I have run bundle exec cap production deploy:check and
my output is
INFO [ecf1a980] Running /usr/bin/env mkdir -p /tmp/PCA/
INFO [ecf1a980] Finished in 4.848 seconds with exit status 0 (successful).
INFO Uploading /tmp/PCA/git-ssh.sh 100.0%
INFO [8e7210f6] Running /usr/bin/env chmod +x /tmp/PCA/git-ssh.sh on serverip
INFO [8e7210f6] Finished in 0.639 seconds with exit status 0 (successful).
INFO [4c538c51] Running /usr/bin/env mkdir -pv /home/pca/app/pca/shared /home/pca/app/pca/releases
INFO [4c538c51] Finished in 4.480 seconds with exit status 0 (successful).
INFO [d6a7dce6] Running /usr/bin/env mkdir -pv /home/pca/app/pca/shared/bin /home/pca/app/pca/shared/log /home/pca/app/pca/shared/tmp/pids /home/pca/app/pca/shared/tmp/cache /home/pca/app/pca/shared/tmp/sockets /home/pca/app/pca/shared/vendor/bundle /home/pca/app/pca/shared/public/system
INFO [d6a7dce6] Finished in 4.507 seconds with exit status 0 (successful).
Anybody help me..
thanks!
I have the same issue, having the error rake stderr: Nothing written when running (deployment) cap production deploy.
Turns out it's due to lack of memory, I have a 1G memory server, so "The Solution is to create a swap memory". For me, creating a 2G swap memory fixed it. Deployment now continues and finishes without any errors.
Seems like precompiling process killing due to the lack of memory.
Try to create swap memory.
Check out this tutorial
Make sure to include ssh key of server where deployment is occurring in gits trusted keys.