LoginSignup
21
17

More than 5 years have passed since last update.

安全に環境変数をリポジトリに入れてcap deployする方法

Last updated at Posted at 2016-03-12

はじめに

データベースの接続情報などは、ベタ書きでは無く環境変数を通じて取り扱った方が取り回しが良い気がします。

config/database.yml
production:
  url: <%= ENV['DATABASE_URL'] %>

dotenvを使えばRailsのenvironmentごとに環境変数を分けることが出来、更に便利感あります。

.env.production
DATABASE_URL=mysql2://user:password@db.example.com/database

じゃあ、このファイルの取り扱いはどうしましょう?そのままリポジトリにプッシュする?
最重要機密なのでプッシュするのは怖いです。

ではサーバに直接置いとく?
いや、環境変数だって変更したい時があります。その時にサーバに入って更新するのは面倒です1

ということで、ここではdotenvファイルを暗号化したものをリポジトリにプッシュすると共に、その鍵をサーバに置いておき、デプロイ時にサーバの方で復号化および環境変数の反映を行う方法を示します。

用意するもの

  • dotenv gem (環境変数反映)
  • gibberish gem (暗号化, 復号化)
  • capistrano gem (デプロイ)

手順

1. 鍵を用意

暗号化に使う鍵を用意します。ここではなんとなくChefのやり方に則って用意します。

openssl rand -base64 512 | tr -d '\r\n' > config/encrypted_data_bag_secret

2. 環境変数を暗号化、復号化するRake タスクを用意

lib/tasks/env.rake
namespace :env do
  key_path = Rails.root.join 'config', 'encrypted_data_bag_secret'

  actual_path = Rails.root.join ".env.#{Rails.env}"
  decrypted_path = actual_path.to_s + '.decrypted'
  encrypted_path = actual_path.to_s + '.encrypted'

  task :encrypt do
    cipher = Gibberish::AES.new File.read(key_path)

    decrypted = File.read(decrypted_path)
    encrypted = cipher.encrypt(decrypted)

    File.write(encrypted_path, encrypted)
  end

  task :decrypt do
    cipher = Gibberish::AES.new File.read(key_path)

    encrypted = File.read(encrypted_path)
    decrypted = cipher.decrypt(encrypted)

    File.write(decrypted_path, decrypted)
  end

  task :deploy do
    cp decrypted_path, actual_path
  end
end

3. dotenvファイルを用意

ここではProduction環境のdotenvファイルを作成します。

.env.production.decrypted
DATABASE_URL=mysql2://user:password@db.example.com/database

4. dotenvファイルを暗号化

これで.env.production.encryptedに暗号化されたdotenvファイルが作成されます。

RACK_ENV=production bundle exec rake env:encrypt

5. cap deploy時にdotenvファイルが反映されるように設定

config/deploy.rb
namespace :deploy do
  task :env => [:set_rails_env] do
    on roles(:app), in: :parallel do |host|
      info '[deploy:env] Deploy Environment'
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, 'env:decrypt'
          execute :rake, 'env:deploy'
        end
      end
    end
  end
end
before 'deploy:updated', 'deploy:env'

6. 機密情報をPushしないように設定

.gitignore
/.env.*.decrypted
/config/encrypted_data_bag_secret

7. サーバに鍵を置く

scp config/encrypted_data_bag_secret app:/var/www/app/shared/config/encrypted_data_bag_secret

8. デプロイ

bundle exec cap production deploy

9. 動作確認

お願いします ( _ _)


  1. Chefで環境変数を設定するようにしEncrypt a Data Bag Itemとかする方法もアリだと思いますが、ここでは取り扱いません 

21
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
17