Capistrano and environment variables

41,796

Solution 1

You might be best looking at the difference between ENVIRONMENT VARIABLES and SHELL VARIABLES

When you fire SSH, your app will load the SHELL variables which are defined in your .bashrc file. These only exist for the life of the shell, and therefore, we don't use them as much as ENV vars

You may be better putting the ENV vars in:

/etc/environment

Like this:

export ENVIRONMENT_VAR=value

This will make the variables available throughout the system, not just in different shell sessions


Update

Have you tried

Capistrano: Can I set an environment variable for the whole cap session?

set :default_env, { 
  'env_var1' => 'value1',
  'env_var2' => 'value2'
}

Solution 2

Although this has been answered, I'm going to leave this here in case anyone else is in the same situation I was.

Capistrano does load .bashrc. But if you'll notice at the top of the file there is this:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

The solution was simply to put any setup above this and Capistrano works how I want.

This solution was also noted at this GitHub issue.

Solution 3

In order to debug the issue update config/deploy.rb with a simple task:

namespace :debug do
  desc 'Print ENV variables'
  task :env do
    on roles(:app), in: :sequence, wait: 5 do
      execute :printenv
    end
  end
end

now run cap staging debug:env. You should be able to see effective configuration of ENV variables.

The order and names of files are dependent on your distribution, e.g. on Ubuntu the sourcing sequence is following:

  1. /etc/environment
  2. /etc/default/locale
  3. /etc/bash.bashrc
  4. ~/.bashrc

When ~/.bashrc contains first lines like this, any code afterwards won't be sourced:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

To understand how capistrano loads ENV variables this chart (source) might be helpful.

Most likely the ~/.bash* file is not loaded due to non-interactive session.

capistrano env variables loading

Solution 4

You need to set environment variables in the /etc/environment file to make them available to all users and process within a system. Environment variables in the .bashrc or .bash_profile files are only available within a shell session and not for automatically spawned processes and services.

I made a Capistrano library (capistrano-env_config) some time ago for managing and syncing environment variables across a cluster which works exactly by modifying the /etc/environment file. It's easy to use and is similar to how you can set environment variables with the Heroku toolbelt. Here are some examples:

cap env:list
cap env:get[VARIABLE_NAME, VARIABLE_NAME, ...] 
cap env:unset[VARIABLE_NAME, VARIABLE_NAME, ...] 
cap env:set[VARIABLE_NAME=VALUE, VARIABLE_NAME=VALUE, ...] 
cap env:sync
Share:
41,796
Rahul Sekhar
Author by

Rahul Sekhar

Updated on July 09, 2022

Comments

  • Rahul Sekhar
    Rahul Sekhar almost 2 years

    I've switched to using environment variables for configuration and it works very well - except when I have to deploy or run tasks with capistrano.

    Capistrano 3 seems to execute each command prefixed with /usr/bin/env which erases any environment variables I've set through .bashrc.

    EDIT - on doing some more reasearch, this might not be the issue, the issue might be because capistrano executes as a non-login, non-interactive shell and does not load .bashrc or .bash_profile. Still stuck, though.

    What would be the best way of making sure the environment vars are set when capistrano executes its tasks?

  • Rahul Sekhar
    Rahul Sekhar about 10 years
    I need the variables to be set for a single user, but available to processes run. I've got export FOO=BAR in .bashrc and this works fine in SSH. Just not in Capistrano.
  • Richard Peck
    Richard Peck about 10 years
    Hmmmmmmmm - let me have a look! Thanks for reply
  • Rahul Sekhar
    Rahul Sekhar about 10 years
    default_environment seems to have no effect, strangely enough. I'm running a test task that echoes a test env variable and BASH_VERSION. BASH_VERSION is shown, the test variable is blank
  • Richard Peck
    Richard Peck about 10 years
    Is the env var in your /etc/environment or .bashrc?
  • Rahul Sekhar
    Rahul Sekhar about 10 years
    In .bashrc. I need these env vars to be applied only for a one user.
  • Richard Peck
    Richard Peck about 10 years
    Sorry, I was just checking :) So it loads the bash_version? Did you set that specifically though?
  • Rahul Sekhar
    Rahul Sekhar about 10 years
    No, I didn't set that. I was just using that as a control test.
  • Richard Peck
    Richard Peck about 10 years
    Okay - bash_version will likely be an ENV var set in the system. You're trying to load SHELL vars
  • Rahul Sekhar
    Rahul Sekhar about 10 years
    Ah, it seems capistrano3 uses default_env, not default_environment (github.com/capistrano/capistrano/pull/564). And that seems to work. Less than ideal, but it'll work for me :)
  • Richard Peck
    Richard Peck about 10 years
    NICE - so this sets SHELL vars when you deploy? Capistrano the most ridiculous software I've used for non-documentation
  • Rahul Sekhar
    Rahul Sekhar about 10 years
    Hahah, indeed. And yes, it prefixes each command with VAR=VAL FOO=BAR ...
  • rolebi
    rolebi about 9 years
    Works like a charm, less complicated than the above solutions.
  • ryan2johnson9
    ryan2johnson9 over 8 years
    "just use ENV variables" they say!! What a pain to put them in 3 places! If the sole reason for it is to prevent putting secrets in source control files, why not just add them to a config file that is not in source control?
  • odigity
    odigity over 8 years
    I've since abandoned everything I previously built for that project and started over with entirely new and better tech: Docker, Thin, Sinatra, Sequel, and etcd. Working on a tool right now to store/retrieve production secrets to/from etcd. No more Rails, Puppet, Capistrano, SSH, env vars, and all that other clunky garbage. I'm not even done, and already the difference has been like night and day.
  • Steven Chanin
    Steven Chanin almost 8 years
    This helped me with a Rails 4.2 app and Capistrano3. Rails was looking for things like the database password and secret_key_base to be set by ENV variables ... which I had added to the end of my bashrc file ... but those weren't bound so everything was crashing towards the end of the deploy.
  • Disha
    Disha almost 8 years
    3. Set my env vars in /etc/init/puma.conf's "script" section. (So they exist when Puma/Rails starts.) - This did the trick for me! Thanks a ton!
  • zx1986
    zx1986 over 6 years
    how could I puts these in a .env file?
  • Alexander
    Alexander over 6 years
    This helped me after spending hours trying to find the right solution. Thank you very much!
  • Hassan Akram
    Hassan Akram almost 6 years
    I think we don't add export in /etc/environment.
  • Abdullah Aden
    Abdullah Aden over 3 years
    Thanks! I have moved all my customer config to the top of .bashrc file.
  • simo
    simo about 2 years
    @RichardPeck putting the env var in /etc/environment did not work for capistrano deploy user, what could be the issue?