阿里雲如何使用AWS S3並用figaro管理密碼

董志欽發表於2019-02-16

前提: 已經把rails app部署到阿里雲,已有AWS賬號,並且申請了AWS
S3,記錄下金鑰ID和私鑰,Region,Bucket_name。

設定figaro

編輯config/application.yml

production:
  SEND_CLOUD_USER_NAME: xxx
  SEND_CLOUD_USER_KEY: xxxxx
  secret_key_base: xxxxxxx
  AWS_ACCESS_KEY_ID: xxxxxxxx
  AWS_SECRET_ACCESS_KEY: hIMMHPxxxxxxx
  AWS_REGION: ap-northeast-1
  AWS_BUCKET_NAME: xxxxx
development:
  SEND_CLOUD_USER_NAME: xxx
  SEND_CLOUD_USER_KEY: xxxxx
  secret_key_base: xxxxxxx
  AWS_ACCESS_KEY_ID: xxxxxxxx
  AWS_SECRET_ACCESS_KEY: hIMMHPxxxxxxx
  AWS_REGION: ap-northeast-1
  AWS_BUCKET_NAME: xxxxx

安裝fog

另外還有fog-aws可以用。
新增gem `fog`
bundle install
新增carrierwave.rb檔案,touch config/initializers/carrierwave.rb
編輯這個檔案:

CarrierWave.configure do |config|
  if Rails.env.production?                  #這裡同樣也用條件語句寫明瞭不同環境用什麼設定。
    config.fog_provider = `fog`                  
    config.fog_credentials = {
      provider:              `AWS`,                        #這裡寫明瞭儲存服務的提供商,下面就是各種aws的key
      aws_access_key_id:     ENV["AWS_ACCESS_KEY_ID"],       # 這樣寫rails就會自動去figaro之前生成的application.yml中去抓對應名稱的key和資訊
                                                             # 如此這些rb檔案被push上去就不會洩露資訊
      aws_secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],

      region:                ENV["AWS_REGION"]            # 這個區域如果不清楚就去Amazon上查下建立的儲存桶的資訊

    }
    config.fog_directory  = ENV["AWS_BUCKET_NAME"]    # 這裡寫明儲存桶的名稱


  else                        #這裡寫明非產品環境就儲存在本地。
    config.storage :file
  end
end

使用fog存圖片

在xxx_uploader.rb中設定,當在開發模式的時候就把圖片存在本地文件中,如果是在產品模式,就用fog存圖片。

uploaders/house_image_uploader.rb

  if Rails.env.development?
    storage :file
  elsif Rails.env.production?
    storage :fog
  end

debug

做完這些,如果是部署到heroku的,還會有一步驟是要把figaro同步到heroku,figaro heroku:set -e production,但我們是部署到阿里雲的,就沒有這一步。
提交程式碼到github,準備部署,執行cap production deploy,過程中會報錯:

00:22 deploy:assets:precompile
      01 bundle exec rake assets:precompile
      01 rake aborted!
      01 ArgumentError: Missing required arguments: aws_access_key_id, aws_secret_access_key
      01 /home/deploy/homey/shared/bundle/ruby/2.4.0/gems/fog-core-1.45.0/lib/fog/core/service.rb:244:in `validate…
      01 /home/deploy/homey/shared/bundle/ruby/2.4.0/gems/fog-core-1.45.0/lib/fog/core/service.rb:268:in `handle_s…
      01 /home/deploy/homey/shared/bundle/ruby/2.4.0/gems/fog-core-1.45.0/lib/fog/core/service.rb:98:in `new`
      01 /home/deploy/homey/shared/bundle/ruby/2.4.0/gems/fog-core-1.45.0/lib/fog/core/services_mixin.rb:16:in `ne…
      01 /home/deploy/homey/shared/bundle/ruby/2.4.0/gems/fog-core-1.45.0/lib/fog/storage.rb:27:in `new`
      ...
      ...

大概意思是說沒有aws_access_key_idaws_secret_access_key,可以理解,因為如果是heroku還要同步一下figaro的資訊呢,而在阿里雲的時候就缺少了這一步,明顯不行。
然後開figaro的git資料,看到這一段:

Other Hosts
If you`re not deploying to Heroku, you have two options:

Generate a remote configuration file
Set ENV variables directly
Generating a remote configuration file is preferred because of:

familiarity – Management of config/application.yml is like that of config/database.yml.
isolation – Multiple applications on the same server will not produce configuration key collisions.

大概意思大概是讓我們自己建立一個application.yml放到雲伺服器了,只要不是放在github裡就好。於是我連線遠端伺服器,在/appname/shared/config下和/appname/current/config兩個地方都建立了application.yml,並且把內容貼進去,儲存退出。
再次執行,發現同樣的問題還在!但是進入到遠端伺服器的console,用Figaro.env.aws_access_key_id來測試又是能顯示金鑰來的。

irb(main):003:0> ENV["AWS_ACCESS_KEY_ID"]
=> "AKIAJNP35BSxxxxxxxxx"
irb(main):004:0> Figaro.env.AWS_ACCESS_KEY_ID
=> "AKIAJNP35BSxxxxxxxxx"
irb(main):005:0> 

到底問題出在哪裡?繼續查資料,直到我看到這樣的一段話:

And finally if we deploy application with Capistrano we have to deploy it properly. We should put local_env.yml to the Capistrano shared folder on the server and change config/deploy.rb like this:

before `deploy:assets:precompile`, :symlink_config_files

desc "Link shared files"
task :symlink_config_files do
  symlinks = {
    "#{shared_path}/config/database.yml" => "#{release_path}/config/database.yml",
    "#{shared_path}/config/local_env.yml" => "#{release_path}/config/local_env.yml"
  }
  run symlinks.map{|from, to| "ln -nfs #{from} #{to}"}.join(" && ")
end

得到一些靈感,在自己的rails application中找到config/deploy.rb,裡面有一行是:

append :linked_files, "config/database.yml", "config/secrets.yml"

我把application.yml加到後面去:

append :linked_files, "config/database.yml", "config/secrets.yml", "config/application.yml"

再次嘗試,部署成功!

相關文章