First off let me say this is the first time I've deployed out a rails application so I'm pretty new to this. I have my production environment running successfully now and deployed it using Capistrano, but the deploy failed the first time due to missing gems. To get around it I basically cloned my repo on the server, ran
bundle install
This successfully installed the gems and Capistrano deployed successfully the next time around.
So with that in mind, is there a correct way to get new gems to install on each deploy?
My environment is Ubuntu Server, Apache2, Passenger, Rails.
Thanks!
We have the following in our deploy.rb
require 'bundler/capistrano'
load 'deploy/assets'
before 'deploy', 'rvm:install_rvm'
ssh_options[:forward_agent] = true
set :rvm_ruby_string, ENV['GEM_HOME'].gsub(/.*\//,"") # Read from local system
require 'rvm/capistrano'
set :rvm_ruby_string, '1.9.3-p194'
...
Works like a treat for us although usually on a new build we'll have to install a few gems on the server directly.
Adding this to the top of your config/deploy.rb file will make Capistrano execute bundle install.
require "bundler/capistrano"
Related
So I'm deploying to a Ubuntu droplet hosted on DigitalOcean a Rails 4 application running on Apache and Phusion Passenger. After deployment I've been getting 500s as a result of Rails production not finding the secret_key_base token for production. However, if I run an echo $SECRET_KEY_BASE it returns the rake secret generated by my deploy.rb.
The deploy.rb task to set that up is:
namespace :deploy do
task :start do ; end
task :stop do ; end
desc "Setup ENV variables"
task :env_vars do
on "root#xxx.xxx.xxx.xx" do
execute "export SECRET_KEY_BASE=#{`bundle exec rake secret`}"
end
end
end
before "deploy", "deploy:env_vars"
However, Rails is still not picking it up. I even ssh'd into my server and in rails console checked and ENV["SECRET_KEY_BASE"] returns the correct secret token.
I thought using Capistrano's :default_env would work, but that only seems to set up environmental variables for the deploy task, but not actually on the server. Is there any easy way to solve this solution? My fallback is to just place the secret within secrets.yml since the repo is private, but I rather not do that.
There is a gem for exactly this task:
https://github.com/capistrano-plugins/capistrano-secrets-yml
Install
Add this to Gemfile:
group :development do
gem 'capistrano', '~> 3.2.1'
gem 'capistrano-secrets-yml', '~> 1.0.0'
end
And then:
$ bundle install
Setup and usage
make sure your local config/secrets.yml is not git tracked. It should be on the disk, but gitignored.
populate production secrets in local config/secrets.yml:
production:
secret_key_base: d6ced...
add to Capfile:
require 'capistrano/secrets_yml'
create secrets.yml file on the remote server by executing this task:
$ bundle exec cap production setup
You can now proceed with other deployment tasks.
You can create a file in your server called application.yml in shared/config.
Choose any one of solution from bellow
Following code in deploy.rb will automatically symlink your application.yml
set :linked_files, %w{config/application.yml}
Or
Then symlink this application.yml with your current/config/application.yml with a simple capistrano task.
Rather than exporting env variables in deploy.rb, use dotenv to load environment variables from .env[.<staging>] into ENV when rails booting.
Follow these steps:
Add this line to the top of your Gemfile:
gem 'dotenv-rails'
Put .env.production file into the linked_file in deploy/production.rb:
set :linked_files, fetch(:linked_files, []).push('.env.production')
On the remote host, add the .env.production file in shared folder which contains this line:
SECRET_KEY_BASE=<Your secret>
Give up on environment vars and just simply read a file. Do this in secrets.yml.
production:
secret_key_base: <%= File.read('/home/me/SECRET_KEY_BASE').strip %>
Then make the secret file.
$ rake secret > ~/SECRET_KEY_BASE
Before settling on this solution I tried exporting the secret from my .bash_profile, .profile, and .bashrc (top and bottom). I also tried PermitUserEnvironment and .ssh/environment. I have no idea how an environment variable gets from "the environment" into a capistrano deployment. I ran ssh example.com printenv and saw my vars. I logged in and saw my vars. But puma started with capistrano... it always has it's own environment.
I have rails 4.1 app and multistage (staging, production) deployment with capistrano3.
I want to deploy it to one stage server (which use rvm) and one production server (which use ruby env)
By default everything works nice on production server, but without rvm1-capistrnao3 gem installed and included in Capefile I cannot deploy to staging.
Is there a way to require 'rvm1/capistrano3' in Capefile, only if I deploy to staging like that
cap staging deploy
Here is what I've done to fix it
I made default capistrano multistage setup, like Doug Hall said!
The tricky part is the way to include rvm1-capistrano3 in Capefile
See deepak's workaround here https://github.com/capistrano/rvm/issues/49
So instead of just require 'rvm1/capistrano3' in Capefile, do it like that
task :use_rvm do
require 'rvm1/capistrano3'
end
task 'staging' => [:use_rvm]
When you run cap install, it creates a file called config/deploy.rb and two files in the config/deploy directory: production.rb and staging.rb. Use the config/deploy.rb file for all settings that both the production and staging servers have in common. Use the other two for the respective settings on those machines. I would require 'capistrano/rvm' in your Capfile, but only use it in the config/deploy/staging.rb file. Capistrano executes the common config/deploy.rb FIRST, then calls the proper staging.rb/production.rb file, so all set values from config/deploy.rb are available in the staging.rb/production.rb file.
In my Gemfile I specify what branch to use on a git repository based on RAILS_ENV. However when Capistrano deploys, it runs the bundle install command - and since it's run through a shell, the proper environment (staging) isn't set. It defaults to development and gives me an error stating that there's a mismatch between Gemfile.lock and what is installed.
You are trying to install in deployment mode after changing your
Gemfile. Run bundle install elsewhere and add the updated
Gemfile.lock to version control.
You have added to the Gemfile:
* source: git#bitbucket.org:MyRepository/manager-engine.git (at develop)
You have deleted from the Gemfile:
* source: git#bitbucket.org:MyRepository/manager-engine.git (at master)
You have changed in the Gemfile:
* manager from git#bitbucket.org:MyRepository/manager-engine.git (at develop) to no specified source
Gemfile:
RAILS_ENV = ENV['RAILS_ENV'] || 'development'
gem 'manager', git: "git#bitbucket.org:MyRepository/manager-engine.git", branch: "#{ [:production, :staging].include?(RAILS_ENV.to_sym) ? :master : :develop }"
i.e., use the 'develop' branch if the rails environment is anything other than 'production' or 'staging'.
deploy/staging.rb:
set :branch, :master
set :keep_releases, 2
set :stage, :staging
set :rails_env, 'staging'
set :bundle_without, [:development, :test]
set :deploy_to, '/home/useraccount/rails_deployments/staging.www'
server 'localhost', user: 'useraccount', roles: %w{web app db}
So to be the most concise:
In regular SSH terminal, to install the repository gem under the proper environment, I have to issue RAILS_ENV=staging bundle install. Otherwise, just running bundle install installs the repository from the develop branch. Since Capistrano just runs bundle install and doesn't include the RAILS_ENV, this problem is occurring. But doesn't Capistrano set :rails_env, or is that not a real system environment variable?
I guess if there's no better way...
I ended up using a method illustrated somewhere else in SO and modified it for my needs.
Modify Gemfile to contain:
# Read environment from A) Explicit set through command, B) Existence of override file's contents or C) Default to development
RAILS_ENV = ENV['RAILS_ENV'] || `cat .rails-env`.to_s.split.first || 'development'
If .rails-env contains nothing or doesn't exist, it defaults to development. Otherwise it takes the first word as the environment. To create the file from the command line, just type echo "your-environment-name-here" > .rails-env, assuming you're in the app's root directory.
You can also create the file upon every deploy with capistrano using the command above, or just create a symlink to the file and share it between deployments:
Deploy.rb:
set :linked_files, %w{ .rails-env }
So now the environment can be forced via a file in the root of your app called .rails-env. Explicit RAILS_ENV calls such as RAILS_ENV=test bundle exec ... will still work as advertised.
I have two files on the server, one in each environment's shared directory, named rvmrc. This contains rvm use ree-1.8.7-2012.02#appname-production --create for production and rvm use ree-1.8.7-2012.02#appname-staging --create for staging. This should allow the app to run under its own gemset, because I've built in a task to the deploy script to link the corresponding shared/rvmrc file into the app as .rvmrc. That task is displayed below, in my deploy.rb example.
I still need to get bundler to use the correct gemset during the deploy, though. I thought I could do this by using set :rvm_ruby_string, "ree-1.8.7-2012.02#appname-#{rails_env}" to dynamically set the rvm_ruby_string to the environment's gemset. However, I find that my deploys only use the production gemset - even when doing cap staging deploy.
See this question for more information on my thought process for even trying this (and to chime in if you think it's just a bad idea).
What do I need to change to get my deploys to use the correct gemset based on the environment?
In my deploy file, the relevant lines that I have (I've stripped out quite a bit) are:
require 'rvm/capistrano'
require 'capistrano/ext/multistage'
require 'bundler/capistrano'
set :stages, %w(staging production)
set :default_stage, "staging"
set :rvm_ruby_string, "ree-1.8.7-2012.02#appname-#{rails_env}"
set :rvm_type, :system
set :bundle_without, [:development]
namespace :deploy do
task :rvmrc do
run "rm #{latest_release}/.rvmrc; ln -s #{shared_path}/rvmrc #{latest_release}/.rvmrc"
end
end
before "bundle:install", "deploy:rvmrc"
In my production.rb file, the relevant lines that I have (I've stripped out quite a bit) are:
set :branch, "master"
set :rails_env, "production"
In my staging.rb file, the relevant lines that I have (I've stripped out quite a bit) are:
set :branch, "staging"
set :rails_env, "staging"
You can set the ruby version and gemset when you launch the application. I.e. use rvm wrappers as it is described for the use with God in the link. No .rvmrc symbolic link juggling needed that way.
I.e., if you're using Unicorn, create a wrapper:
rvm use ree-1.8.7-2012.02#appname-production
rvm wrapper ree-1.8.7-2012.02#appname-production ree187prod unicorn
That gives you ~.rvm/bin/ree187prod_unicorn. Use it instead of unicorn in your start script. Unicorn will then use the correct ruby version and gemset.
I'm running Rails + Passenger under an Ubuntu AWS's instance. Now I'm trying to deploy with Capistrano, I already did my git repository (and upload it to the server) and my deploy.rb file (with capify .). I already runned cap deploy:setup and cap deploy:check with success. But now when I try to run cap deploy it fail and I get this error http://pastebin.com/uzkerA9F
Well, I found the problem and solution here
Capistrano asks for password when deploying, despite SSH keys
So > I add set :ssh_options, {:forward_agent => true} to my deploy.rb file