Ben
Ben

Reputation: 5182

capistrano + sidekiq / unable to pick environments variables

So the problem is not that uncommon as so far I could've gathered loads of issues about it, but still, without being able to solve this on my own

I had the following task :

namespace :sidekiq do
      task :start do
        on roles(:app), in: :sequence, wait: 5 do
          within release_path do
            as :deploy  do
              with rails_env: fetch(:rails_env) do
                execute :bundle, "exec sidekiq -e production -C ./config/sidekiq.yml -L ./log/sidekiq.log -d"
              end
            end
          end
        end
      end
end

The task is being called within namespace :deploy do ... end in the main deploy.rb file

As my database creds' are stored on the remote machine in ~/.profile, sidekiq fails to run things (I tried to put those env vars in ~/.bashrc, etc… whatever dot files that could have been present or named in the found issues… nothing worked). I've almost done anything possible.

Obviously, if i run the _very_ same command on the remote machine and not via capistrano, everything works perfectly. I ended up with this poor one :

task :start do
  run_locally do
    %x(ssh deploy@#{fetch(:application)} 'cd /var/www/#{fetch(:application)}/current && /home/xx/.rvm/bin/rvm 2.4.0 do bundle exec sidekiq -e production -C /var/www/#{fetch(:application)}/current/config/sidekiq.yaml -L /var/www/#{fetch(:application)}/current/log/sidekiq.log -d')
   end
end

That said, if the mistake sounds obvious for some who use a regular execute :bundle, '...sidekiq startup cmd...' without this kind of issue; thanks a mega lot in advance for any help

Best

Upvotes: 2

Views: 2657

Answers (2)

Matt Brictson
Matt Brictson

Reputation: 11092

If you are running Ubuntu, you should just be able to export the environment variables by putting them at the very top of ~/.bashrc.

Here's an example from a machine running Ubuntu 14.04:

# ~deployer/.bashrc
export HELLO=world

To demonstrate, I have a Capistrano task that simply prints the environment:

task :env do
  on roles(:all) do
    execute "env"
  end
end

And when I run it, you can see that HELLO=world is indeed in the environment as expected:

$ cap production env
00:00 env
      01 env
      01 XDG_SESSION_ID=328
      01 SHELL=/bin/bash
      01 HELLO=world
      01 SSH_CLIENT=xx.xx.xx.xx 16582 22
      01 USER=deployer
      01 SSH_AUTH_SOCK=/tmp/ssh-Twu5TDVnXb/agent.32558
      01 MAIL=/var/mail/deployer
      01 PATH=/home/deployer/.rbenv/shims:/home/deployer/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/b…
      01 PWD=/home/deployer
      01 LANG=en_US.UTF-8
      01 RBENV_SHELL=bash
      01 SHLVL=1
      01 HOME=/home/deployer
      01 LOGNAME=deployer
      01 SSH_CONNECTION=xx.xx.xx.xx 16582 xx.xx.xx.xx 22
      01 XDG_RUNTIME_DIR=/run/user/1000
      01 _=/usr/bin/env
    ✔ 01 [email protected] 2.131s

For other Capistrano-compatible ways to pass environment variables to a Ruby process, see this answer: https://stackoverflow.com/a/39628182/4625365

Upvotes: 6

Jem
Jem

Reputation: 656

I've run into this problem before, and it's because capistrano uses a non-login, non-interactive shell. Therefore, when you deploy your app, it doesn't touch the .bash_rc or .profile files at all, and sidekiq won't have access to your env vars. You can find more information about that in the Capistrano docs. Using Unicorn, I had to place my env vars in /etc/default/unicorn so I knew they would be sourced. Depending on what you're using, you should find the configuration file you know will be touched when you deploy your app.

Upvotes: 1

Related Questions