はじめに
データベースの接続情報などは、ベタ書きでは無く環境変数を通じて取り扱った方が取り回しが良い気がします。
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. 動作確認
お願いします ( _ _)
-
Chefで環境変数を設定するようにしEncrypt a Data Bag Itemとかする方法もアリだと思いますが、ここでは取り扱いません ↩