TECH EXPERT 33日目

TECH::EXPERT

無事追いついて、1日アドバンテージが取れたかな。
17日もサボる予定なので適度なペースでやらないと。

AWS

インスタンスの作成

elastic IPの取得・インスタンスとの関連付け

sshでサーバーに接続

~/.sshディレクトリで以下を実行。

$ ssh -i ダウンロードした鍵の名前.pem ec2-user@作成したEC2インスタンスと紐付けたElastic IP

最低限の環境を整える

sudo yum update

最低限必要なものをインストール
sudo yum install \
git make gcc-c++ patch \
libyaml-devel libffi-devel libicu-devel \
zlib-devel readline-devel libxml2-devel libxslt-devel \
ImageMagick ImageMagick-devel \

railsを始めるに当たって必要なパッケージをインストール
sudo yum install -y openssl-devel

nodejsをインストール
sudo curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
sudo yum install nodejs

Node.js

サーバーサイドJavaScriptのパッケージ

rbenvとruby-buildをインストール

#rbenvのインストール
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv 
#パスを通す
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile 
#rbenvを呼び出すための記述
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
#.bash_profileの読み込み
source .bash_profile
#ruby-buildのインストール
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
#rehashを行う
rbenv rehash  

rubyのインストール

rbenv install 2.5.1
rbenv global 2.5.1
rbenv rehash  #rehashを行う
ruby -v # バージョンを確認

mysqlをインストール

sudo yum install mysql56-server mysql56-devel mysql56

mysqlを起動

service コマンドを利用。Amazon LinuxやCentOSに含まれ、インストールしたソフトウェアの起動を一括して行えるツール。

sudo service mysqld start

mysqld:daemonの略。linux用語でサーバーの意。

rootパスワードの設定

sudo /usr/libexec/mysql56/mysqladmin -u root password '設定したいパスワード'

Using a password on the command line interface can be insecure.

これが出る。passwordが丸見えだからセキュアじゃないよって意味。

アプリケーションサーバーの準備

Githubに接続

GithubにSSH鍵を登録

まずEC2サーバーでキーペアを生成

ssh-keygen -t rsa -b 4096

.ssh]$ ls
authorized_keys  id_rsa  id_rsa.pub

上記の2種類が作成される。この内publicの方の中身を確認。

cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2E***

githubへアクセスし、SSHキーを登録する。
※ssh-rsaからIPまでを含めた全体を登録する。

ssh-rsa AAAAB3NzaC1***== ec2-user@ip-111-11-11-111

Unicorn

アプリケーションサーバ
rails sコマンドの代わりにunicorn_railsコマンドで起動する。

Unicornをインストール

gemfileに以下を記述。

group :production do
  gem 'unicorn', '5.4.1'
end

config/unicorn.rbを新規作成

#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../', __FILE__)

#アプリケーションサーバの性能を決定する
worker_processes 1

#アプリケーションの設置されているディレクトリを指定
working_directory app_path

#Unicornの起動に必要なファイルの設置場所を指定
pid "#{app_path}/tmp/pids/unicorn.pid"

#ポート番号を指定
listen 3000

#エラーのログを記録するファイルを指定
stderr_path "#{app_path}/log/unicorn.stderr.log"

#通常のログを記録するファイルを指定
stdout_path "#{app_path}/log/unicorn.stdout.log"

#Railsアプリケーションの応答を待つ上限時間を設定
timeout 60

#以下は応用的な設定なので説明は割愛

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&
    ActiveRecord::Base.connection.disconnect!

  if run_once
    run_once = false # prevent from firing again
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end

worker(ワーカー)

リクエストを処理するunicornのプロセスのこと。適宜増える。
unicornはmaster1つと複数のworkerで構成される。

Unicornの設定

設定項目詳細
worker_processesリクエストを受け付けレスポンスを生成するworker(ワーカー)の数を決めます。
working_directoryUnicornがRailsのコードを動かす際、ルーティングなど実際に参照するファイルを探すディレクトリを指定します。
pidUnicornは、起動する際にプロセスidが書かれたファイルを生成します。その場所を指定します。
listenどのポート番号のリクエストを受け付けることにするかを決定します。今回は、3000番ポートを指定しています。

ディレクトリの作成

#mkdirコマンドで新たにディレクトリを作成
[ec2-user@ip ~]$ sudo mkdir /var/www/
#作成したwwwディレクトリの権限をec2-userに変更
[ec2-user@ip ~]$ sudo chown ec2-user /var/www/

作成したディクトリのownerはrootになるので、ec2-userへ変更しておく。

/var/www/に移動してgit cloneする。

[ec2-user@ip ~]$ cd /var/www/
[ec2-user@ip www]$ git clone https://github.com/user名/レポジトリ名.git

rail環境の再構築

まずローカル環境のrubyとbundlerのバージョンを確認。

ruby -v
bundler -v

サーバーでもruby -vを確認。違っていればバージョンを入れ直す。
続いてbundlerをバージョンを指定してインストール

gem install bundler -v 2.0.2

i18nをrails 5.2.2以下で使っている場合に注意がでる。
以下のように変更すればOK

config/environments/production.rb
config.i18n.fallbacks = true
↓
config.i18n.fallbacks = [I18n.default_locale]
Release v1.1.0 · ruby-i18n/i18n
BREAKINGCHANGE:FallbacksFallbacksnowexcludedefaultlocale-#415,possiblyfixes#413+#338PleasecheckyourRailsappforthisline:config.i18n.fallbacks=trueThissettingisno...

環境変数

データベースのパスワードなどはセキュアに扱うためサーバー内の環境変数で扱います。
環境変数は /etc/environment というファイルに保存することで、サーバ全体に適用される。

secret_key_base

Cookieの暗号化に用いられる文字列。
Railsアプリケーションを動作させる際は必ず用意する。

config/secrets.yml と config/database.ymlで扱う。

以下のコマンドでsecret_keyを生成できる。

rake secret

環境変数を編集。

sudo vim /etc/environment
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'

を書き込んで保存して終了。
一旦サーバーからexitしてログインしなおすと環境変数として適応される。

portの解放

AWSのセキュリティーグループからインバウンドの編集へ。
カスタムTCP, port 3000として解放。

railsを起動する。

projectの階層で
unicorn_rails -c config/unicorn.rb -E production -D

-c config/unicorn.rb は設定ファイルの指定、 
-E productionは環境を「本番モードとして動作させる」。
-Dは「Daemon(デーモン)」の略で、プログラムを起動させつつターミナルで別のコマンドを打てるようにするオプション。

データベースのアクセスで失敗するのでローカルプロジェクトを以下のように編集する。終わったらpushしておく。

config/database.yml

production:
  <<: *default
  database: ~~~(それぞれのアプリケーション名によって異なっています。こちらは編集しないでください)
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

gitから差分を更新する。(pullする)

git pull origin master

production用のDBを作成する。

rails db:create RAILS_ENV=production
rails db:migrate RAILS_ENV=production

ユニコーンを起動する。

unicorn_rails -c config/unicorn.rb -E production -D

アセットファイルをコンパイル

開発中はアクセス毎にアセットファイル(画像・CSS・JSファイルの総称)を自動的にコンパイル(圧縮)するが、
本番モードのときにはパフォーマンスのためアクセス毎には実行されないようになっている。

このためコンパイルしないとレイアウトが崩れる。
以下を実行してコンパイルしてrailsを再起動する。

rails assets:precompile

unicornの再起動

unicornのプロセスを探す。

ps aux | grep unicorn

unicron_rails masterのプロセスIDを確認。
killコマンドで終了させる。

kill -9 プロセスID

unicornを再起動する。
この時、頭にRAILS_SERVE_STATIC_FILES=1を指定する。
これはコンパイルされたアセットをrailsに渡す指定。

$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

アクセス時のログは↓に記録されていくらしいが、なぜかblank。
stderrは書き込みがあるのになぜ?

log/unicorn.stdout.log 

一応ここまででIP:3000にアクセスすれば動くはず。

NGINX

エンジンエックス。

sudo yum install nginx

設定ファイルを書き換える。

sudo vim /etc/nginx/conf.d/rails.conf
upstream app_server {
  # Unicornと連携させるための設定。アプリケーション名を自身のアプリ名に書き換えることに注意。今回であればおそらくchat-space
  server unix:/var/www/<アプリケーション名>/tmp/sockets/unicorn.sock;
}

# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
  # このプログラムが接続を受け付けるポート番号
  listen 80;
  # 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
  server_name <Elastic IP>;

# 接続が来た際のrootディレクトリ
  root /var/www/<アプリケーション名>/public;

# assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}

POSTメソッドでもエラーが出ないようにするために、下記のコマンドも実行し、
権限を変更。

cd /var/lib
sudo chmod -R 775 nginx  
(デフォルトではnginxは770に指定されていた)

unicorn.rbを編集

project/confiig/unicorn.rbを編集する。

listen 3000

↓以下のように修正

listen "#{app_path}/tmp/sockets/unicorn.sock"

これでデプロイ作業は終了!

Capistrano

自動デプロイツール

Gemをインストール

gemfileに以下を追記。

group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end

bundle installする。

次のコマンドも行う。
capistranoのインストール(というかconfigファイルの作成なのかな?)

bundle exec cap install

以下が生成される。
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified
Capfile
  Capistrano関連のライブラリのうちどれを読み込むかを指定
deploy.rb     共通設定
production.rb 本番環境用
staging.rb   staging用
  デプロイのための情報を記載する。

capfileを以下のように編集

require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

deploy.rb

  • アプリケーション名
  • gitのレポジトリ
  • 利用するSCM
  • タスク
  • それぞれのタスクで実行するコマンド

などを記載する。

以下のように編集する。

# config valid only for current version of Capistrano
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '<Capistranoのバージョン>'

# Capistranoのログの表示に利用する
set :application, '自身のアプリケーション名'

# どのリポジトリからアプリをpullするかを指定する
set :repo_url,  'git@github.com:<Githubのユーザー名>/<レポジトリ名>.git'

# バージョンが変わっても共通で参照するディレクトリを指定
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, '<このアプリで使用しているrubyのバージョン>' #カリキュラム通りに進めた場合、2.5.1か2.3.1です

# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['<ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス>']  ※例:~/.ssh/key_pem.pem

# プロセス番号を記載したファイルの場所
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }

# Unicornの設定ファイルの場所
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

# デプロイ処理が終わった後、Unicornを再起動するための記述
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end
git@github.com:ユーザ名/リポジトリ名.git

DSL(Domain Specific Language)

ドメイン固有言語。
capistrano内で記載されるset :名前, 値 などの記法もこの種のもの。
setは変数の定義なようなもので、fetch 名前 とすることで値を取り出せる。

deploy.rb内に記述されているdesc ‘◯◯’やtask:XX doなどもcap deploy時に実行される。

Capistranoによる自動デプロイ後のディレクトリ構成について

capistranoでデプロイを実行すると
releases、current、sharedディレクトリ等のディレクトリが作られる。
/var/www/project内に以下のフォルダが作成される。
capistranoを使わない場合と比べてcurrentディレクトリ下に配置される分だけ階層が深くなる。

releaseディレクトリ

過去のデプロイバージョンが保存される。
deploy.rbのset :keep_releases, 5
で指定しているのが保存するバージョン数。
上記の場合過去5つ分まで保存する。

currentディレクトリ

デプロイされた最新のものがここに格納される。

sharedディレクトリ

バージョンが変わっても共通で参照されるディレクトリが格納される。
具体的には、log、public、tmp、vendorディレクトリが格納される。

unicorn.rbとnginx設定ファイルを修正

config/unicorn.rb

app_path = File.expand_path('../../', __FILE__)

worker_processes 1

working_directory app_path
pid "#{app_path}/tmp/pids/unicorn.pid"
listen "#{app_path}/tmp/sockets/unicorn.sock"
stderr_path "#{app_path}/log/unicorn.stderr.log"
stdout_path "#{app_path}/log/unicorn.stdout.log"

 ↓↓↓↓↓↓↓ 以下のように変更 ↓↓↓↓↓↓

# ../が一つ増えている
app_path = File.expand_path('../../../', __FILE__)

worker_processes 1
# currentを指定
working_directory "#{app_path}/current"

# それぞれ、sharedの中を参照するよう変更
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"
sudo vim /etc/nginx/conf.d/rails.conf
upstream app_server {
  server unix:/var/www/<アプリケーション名>/tmp/sockets/unicorn.sock;
}

root /var/www/<アプリケーション名>/public;

location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }
      
 ↓↓↓↓↓↓↓ 以下のように変更 ↓↓↓↓↓↓

upstream app_server {
  server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}

root /var/www/<アプリケーション名>/current/public;

location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    root   /var/www/<アプリケーション名>/current/public;
  }

変更後はnginxの再起動

sudo service nginx reload
sudo service nginx restart

mysqlも立ち上げておく。
∵MySQLが立ち上がっていないとデプロイが失敗

sudo service mysqld restart

unicornを停止させる

cd /var/www/アプリ名
kill -QUIT `cat tmp/pids/unicorn.pid`  #Unicornの停止

自動デプロイさせる

bundle exec cap production deploy

自動デプロイでCSSが機能しない!

悩んで悩んで悩みまくった挙句、この方の記事を見て同じように確認すると、、、
まさに同じ箇所でタイポしてた!(笑)
私の場合は-を入れ忘れてた。
いやーこんな初歩的なことで同じ間違いをしているとは。

Uglifier

JavaScriptを軽量化するためのgem。
テンプレートリテラル記法(`)に対応してないため自動デプロイ時にエラーの原因となる。

config/environments/production.rb
以下のようにコメントアウトする。
# config.assets.js_compressor = :uglifier

ちなみにエラーを起こさせると以下のように怒られる。

rake stderr: rake aborted!
Uglifier::Error: Unexpected character '`'

killコマンド

kill -9は問答無用の強制終了。
シグナル指定なしなら -15 -1 -9の順にシグナルが流れる。

子プロセスが残る可能性があるので可能な限り-9を使わないほうが良い。

$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX

lessコマンド

テキストファイルを1画面ずつ表示する。
Enterで1行、Spaceで1画面ずつスクロールする。
終了するにはqキーを押す。

rails

migrationファイルを手動でごにょごにょした時。
アクセス時にMigrations are pendingと出る問題。

rake db:reset
rake db:migrate

railsではmigrationさせたかどうかを管理されているのでこっそりファイル増やしたら怒られる。たとえそれが整合性を保つために書き直したファイルであっても。
なので一旦dbをリセットしてからmigrateさせると動く。

GIT

indexに載せているファイルを確認。

git status

indexから取り除く。

git checkout .
git checkout file_name

AWS S3

2段階認証にするためにauthyを導入。

AWS
Identity and Access Managementの「セキュリティステータス」でMFAの管理を選択

S3を使う専用のIAM userを作成し、S3fullAccess権限を付与。
同時に2段階認証へ。

git-secrets

git-secretsは、AWSが提供しているツール。
パスワード、secret_keyなどの秘密にしたい情報を、誤ってコミットされることを防ぐ。
=秘密情報を含むcommitができなくなる。

ローカルにインストール。

brew install git-secrets

projectフォルダに移って以下を入力

git secrets --install

secretsの条件を設定
以下のコマンドでsecret_key, access_keyなど、アップロードしたくないAWS関連の秘密情報を一括で設定

git secrets --register-aws --global

以下のコマンドで設定を確認できる。

git secrets --list

以下のコマンドで今後作成するproject全てにgit-secretsが適用される。
=git管理下に含めた時点でgit-secretsも有効になる。

$ git secrets --install ~/.git-templates/git-secrets
$ git config --global init.templatedir '~/.git-templates/git-secrets'

GitHub Desktop経由でgit secretsを利用する

GitHub Desktop経由でgit secretsを利用する場合は追加の設定が必要
以下のコマンドをうつ。

sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets

S3のパブリックアクセス管理

  • アクセスコントロールポリシー
  • バケットポリシー

バケットポリシーで以下を入力してバケットにuserを許可する。

{
    "Version": "2012-10-17",
    "Id": "Policy1544152951996",
    "Statement": [
        {
            "Sid": "Stmt1544152948221",
            "Effect": "Allow",
            "Principal": {
                "AWS": "************①****************"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::************②**********"
        }
    ]
}

画像アップロード先を変更

1.fog-awsというgemをインストールする
2.image_uploader.rbを編集する
3.CarrierWaveの設定ファイルを作成する
4.環境変数を設定する

gemfileに下を記述し、bundle install
group :production doではなく、全てなので一番下にでも入れてください。

gem 'fog-aws'

app/uploads/image_uploader.rbファイルを以下のように変更。
storage :file → storage :fog

class ImageUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick

  storage :fog

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

CarrierWaveの設定ファイルを新規作成。
/config/initializers直下に、carrierwave.rbを作成

require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  config.storage = :fog
  config.fog_provider = 'fog/aws'
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: Rails.application.secrets.aws_access_key_id,
    aws_secret_access_key: Rails.application.secrets.aws_secret_access_key,
    region: 'リージョンを入力' #例 'ap-northeast-1'
  }

  config.fog_directory  = 'ここにバケット名を入れます'
  config.asset_host = 'https://s3-ここにリージョン名を入れます(※例 ap-northeast-1).amazonaws.com/ここにバケット名を入れます'
end

application.secrets.aws_secret_access_keyとidは、一旦secrets.ymlに設定してそこから参照させるようにする。

.gitignoreに追加

secrets.ymlにデリケートな情報を持たせるので、このファイルを.ignoreに追加する。

config/secrets.yml

.gitignoreに記載した変更は、一度gitの監視下に置かれてしまったファイルには適用されません。今.gitignoreに記載した変更を反映させるためには、config/secrets.ymlをgitの監視から外す必要があります。次のコマンドを実行して、config/secrets.ymlをgitの監視から外してください。

git rm --cached config/secrets.yml

環境変数を指定

$ vim ~/.bash_profile

export AWS_SECRET_ACCESS_KEY='ここにCSVファイルに乗っている値をコピー'
export AWS_ACCESS_KEY_ID='ここにCSVファイルに乗っている値をコピー'

$ source ~/.bash_profile

ローカル環境とサーバーの両方で上を行う。

secrets.ymlに登録

config/secrets.ymlを以下のように編集。

development:
  secret_key_base: ~~~~~~~~
  aws_access_key_id: <%= ENV["AWS_ACCESS_KEY_ID"] %>
  aws_secret_access_key: <%= ENV["AWS_SECRET_ACCESS_KEY"] %>

test:
  secret_key_base: ~~~~~~~~

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  aws_access_key_id: <%= ENV["AWS_ACCESS_KEY_ID"] %>
  aws_secret_access_key: <%= ENV["AWS_SECRET_ACCESS_KEY"] %>

環境変数を呼べるように変更。

全体の流れとしてはログインユーザーにしか参照できない環境変数にAWSのキーを登録。
→ railsがyml内にそれを呼び出し
→ それをもってAWSと通信する。

この状態ならGIT上には環境変数はどうやっても乗らないのでセキュア。
この理論ならsecrets.yml自体もセキュアなのでgitであげちゃっても大丈夫そうだけどどうなんだろう?

capistranoの記述を変更

自動デプロイで利用するためには、明示的に環境変数を指定する。

config/deploy.rbに以下を追記

set :default_env, {
  rbenv_root: "/usr/local/rbenv",
  path: "/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH",
  AWS_ACCESS_KEY_ID: ENV["AWS_ACCESS_KEY_ID"],
  AWS_SECRET_ACCESS_KEY: ENV["AWS_SECRET_ACCESS_KEY"]
}

さらに先ほど.gitignoreにsecrets.ymlを追加したため、デプロイしてもgitにpushされないため、明示的にproduction環境にアップロードしてあげる必要がある。

# secrets.yml用のシンボリックリンクを追加
set :linked_files, %w{ config/secrets.yml }

# 元々記述されていた after 「'deploy:publishing', 'deploy:restart'」以下を削除して、次のように書き換え

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end

  desc 'upload secrets.yml'
  task :upload do
    on roles(:app) do |host|
      if test "[ ! -d #{shared_path}/config ]"
        execute "mkdir -p #{shared_path}/config"
      end
      upload!('config/secrets.yml', "#{shared_path}/config/secrets.yml")
    end
  end
  before :starting, 'deploy:upload'
  after :finishing, 'deploy:cleanup'
end

set :linked_filesで指定されたファイルは、元々のディレクトリを参照する代わりに、shared/元々のディレクトリ構成を参照するようになります。今回の例で言うと、config/secrets.ymlを参照する代わりに、shared/config/secrets.ymlを参照するようになります。

コメント