Capistrano Not recognizing secret_key_base in Rails production.enc - ruby-on-rails

I'm using Capistrano to deploy my Rails 7.0.2 app with Ruby 3.1.1, when I run cap production deploy and then when Capistrano runs:
deploy:assets:precompile
$HOME/.rbenv/bin/rbenv exec bundle exec rake assets:precompile
I receive the following error :
ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `bin/rails credentials:edit`
deploy.rb:
# config valid for current version and patch releases of Capistrano
lock '~> 3.17.0'
set :application, 'app'
set :repo_url, 'git#github.com:foo/app.git'
# Deploy to the user's home directory
set :deploy_to, "/#{fetch :application}"
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', '.bundle', 'public/system', 'public/uploads'
# Only keep the last 5 re
The problem is that I already have the secret_key_base defined in my productions encrypted credentials file so I should not be getting this error. I also tried putting the secret_key_base as a .rbenv-vars file and still got the same error. How do I properly use a secret_key_base in a production environment with Rails and Capistrano? Thanks again!

Can you try adding to the deploy.rb file:
append :linked_files, 'config/credentials/production.key',
And copy the production.key (the one that is in charge of decrypting the production credentials) to the shared folder in your server, something like /var/www/{proyect_name}/shared/config/credentials/production.key you can leave the production.yml.enc in your GitHub.
And check that you have set the secret_key_base in your production secret keys with EDITOR=nano rails credentials:edit -e production

Added the following to config/environments/production:
config.require_master_key = true
run EDITOR=vi rails credentials:edit --environment=production
Save the production key generated to your server # app/config/credentials/production.key
Changed set :deploy_to, "/#{fetch :application}" to set :deploy_to, "~/#{fetch :application}"

Copy master.key on your remote machine at project_folder/shared/config and it should be ok.
EDIT:
wait a second, add --> append :linked_files, "config/master.key"
after set :deploy_to, "/#{fetch :application}"

Related

capistrano + rails 5 : server starts in production mode instead of staging

I'm trying to deploy a rails 5 app to a staging server using capistrano with nginx and passenger, however running Rails.env yields production instead of staging. Here's my capistrano setup:
in config/deploy.rb:
set :stages, %i(staging production)
set :default_stage, :staging
in config/environments/staging.rb:
set :stage, :staging
set :rails_env, :staging
running echo $RAILS_ENV in my server yields 'staging'
and my passenger_app_env config aso has staging
I'm not aware of anything that could override those, Any ideas?
Thanks in advance.
PD: I'm using rbenv
Just in case anyone hits this, I ended up re-installing nginx and redoing all config files and got it working without changing anything in capistrano. So it was a setup issue.

Setting up secret_key_base on deploy with Capistrano 3

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.

Capistrano doesn't set RAILS_ENV for bundler

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.

Capistrano 3: use short `cap deploy` to deploy on production by default

I'm curious how to configure capistrano 3 with short cap deploy command to deploy on production by default instead of full cap production deploy.
Try this in your deploy.rb:
require 'capistrano/ext/multistage'
set :stages, ["dev", "production"]
set :default_stage, "production"
Then run:
cap deploy
In your Capfile add this at the bottom
invoke :beta
This will call the beta stage and make it the default.
I'm not shure this is the correct way, but it seems to work :)

Rails Capistrano deploy_to path

I'm trying to deploy my rails app, until now hostet at Heroku, now at DigitalOcean using Capistrano. I've created a "1-Click-Rails-Application", which creates a blank rails app, so when I open the remote server in my webbrowser, the typical rails welcome screen (index.html) shows up. When I ssh to the remote directory, the path to the rails app is:
/home/rails/
inside of the rails directory are the typical rails folders like controllers etc. So I thought that the correct deploy_to path should be:
set :deploy_to, "/home/rails/"
I've seen so many different directory suggestions that I really can't figure out what could be right. I had
set :deploy_to, "var/www/#{application}"
as well, which didn't seem to work either.
I'm glad I've managed to upload my local app to the new vpn server without any errors at all. I want to avoid using a git repo to save the extra costs for a private git repo and push it directly from my computer. The problem is, after a
cap production deploy:cold
which does a lot and runs through without any errors, doesn't seem to upload anything. At least I can't find any of "my" files on the server. Well, I'm really happy that I got this far but don't understand why my config isn't working. I hope someone can help. Here is my deploy.rb from the config directory. (I'm using rvm.)
require 'capistrano/ext/multistage'
require "bundler/capistrano"
require "rvm/capistrano"
set :application, "myApp"
set :user, "root"
set :port, 22
set :deploy_to, "home/rails/"
set :repository, "."
set :scm, :none
set :deploy_via, :copy
set :checkout, :export
set :use_sudo, false
#set :rvm_ruby_string, "ruby-2.0.0p195##{application}"
set :rvm_type, :user
set :rvm_type, :system
server "xx.xxx.xx.xx", :app, :web, :db, :primary => true
after "deploy", "deploy:migrate"
I'm using Rails 3.2.13 and Ruby 2.0.0. Thanks a lot!
Update:
I was originally following a railscast capistrano deployment tutorial to get my head around this. Thus I created the deploy folder inside the config folder with a production.rb and a staging.rb inside.
Long story short, I've found "my" rails app, inside a var/www/xx.xxx.xx.xx/current/ directory on the server. The path is specified inside the production.rb which looks like this:
server "xx.xxx.xx.xx", :app, :web, :db, :primary => true
set :deploy_to, "/var/www/xx.xxx.xx.xx"
I could now change the path above to /home/rails but the actual rails app was inside the additional folder named current. How do I have to write the path so that there is no current directory? at least not there?
set :deploy_to, "home/rails/"
The correct way is:
set :deploy_to, "/home/rails/"
and for var path:
set :deploy_to, "/var/www/#{application}"
I got this working with the latest version of Capistrano: 3.2.1 and 3.1.0
Perhaps this was fixed in a patch?
Here are the relevant parts of my files:
Gemfile:
group :development do
gem 'capistrano-rails'
end
Capfile:
require 'capistrano/setup'
# Includes default deployment tasks
require 'capistrano/deploy'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }
config/deploy.rb
set :deploy_to, '/var/www/wrong_stage_folder'
# make sure this value is ignored.
config/deploy/staging.rb
set :deploy_to, '/var/www/appname_stage'
config/deploy/production.rb
set :deploy_to, '/var/www/appname_prod'
Run check: cap staging deploy:check --trace
INFO [2618043b] Running /usr/bin/env mkdir -pv /var/www/appname_stage/shared /var/www/appname_stage/releases on example.server.com
Works as expected, same for production.

Resources