ユカシカド エンジニアブログ

体の栄養状態を把握する検査サービス VitaNoteを開発するエンジニアのブログ

Capistranoでデプロイする際のヒミツ情報の取り扱い

自分自身ではしばらくの間、このブログは「コンピュータの力で精神衛生を確保しようとする、ひとり開発部」のノウハウ集のようになればいい!と考えているのですが、当然デプロイも自動化できないと精神衛生上よくないわけです。

Capistrano

さらに上のレイヤーでの自動化がブームの最中、初めてCapistranoの門を叩きました。それでつまずいたのが、Jenkins導入の際と同じでdatabase.ymlの情報とSECRET_TOKENを隠蔽する方法です。

デプロイスクリプトのrunメソッドを使って、環境変数にそれらの情報を書いたファイルをsourceコマンドで読み込むという方法が上手くいかず大いにハマりました。

capistrano使用時とsshログイン時とで環境変数が異なってしまう

この記事でようやく判明したのが、capistranoがログインした時はユーザのログインシェルが割り当てられないんですね。

結果としての現時点での対策

config/deploy.rb

  # capistranoの出力がカラーになる
  require 'capistrano_colors'

  # cap deploy時に自動で bundle install が実行される
  require 'bundler/capistrano'

  # rbenvを使う 
  require 'capistrano-rbenv'

  # deploy:startでpuma起動
  require 'puma/capistrano'


  set :rbenv_ruby_version, ENV['RBENV_VERSION']
  set :application, ENV['RAILS_APP']
  set :scm, :git
  set :repository,  "#{ENV['PRIVATE_REPOSITORY']}/#{application}.git"
  set :branch, 'master'
  set :rails_env, 'production'
  set :deploy_via, :remote_cache
  set :deploy_to, "#{ENV['DEPLOY_ROOT_DIR']}/#{application}"
  set :use_sudo, false
  set :default_shell, '/bin/bash -l'

  role :web, ENV['DEPLOY_SERVER']                          # Your HTTP server, Apache/etc
  role :app, ENV['DEPLOY_SERVER']                          # This may be the same as your `Web` server
  role :db,  ENV['DEPLOY_SERVER'], :primary => true        # This is where Rails migrations will run

  # SSH
  set :user, ENV['DEPLOY_USER']
  set :password, ENV['DEPLOY_PASSWORD']
  ssh_options[:port] = ENV['DEPLOY_PORT']
  ssh_options[:forward_agent] = 'false'
  ssh_options[:keys] = ENV['DEPLOY_KEYS']
  ssh_options[:passphrase] = ENV['DEPLOY_SSH_PASSPHRASE']
  default_run_options[:pty] = true

  # assets:precompile
  load 'deploy/assets'

  namespace :setup do
   task :fix_premissions do
     "find . -type f -print | xargs chmod 644 #{deploy_to}"
     "find . -type d -print | xargs chmod 755 #{deploy_to}"
   end
  end

~/.profile

最終行に環境変数を読み込むコードを追加

source ~/.rails_env/*

まとめ

自分でもスマートとは言えないものの、テストとデプロイで隠蔽を両立するには現時点でこれしか思いつきませんでした。

amfranz/capistrano_database_yml

のような機構も検討しましたが、うっかりpushやSECRET_TOKENには対応できないので、ひとまずこの方法でやりながら考えていきます。