NginxにおいてのRailsプロダクション環境のsecret_key_base設定

2018/10/17追記:
新規プロジェクトでconfig/secrets.ymlが見つからないことで、Rails5.2からsecrets.ymlが廃止され、credentials.yml.encで統合されたことが知りました。
詳しくは参考8が参考になると思いますが、デプロイの方法でも同じのはずですが、違いとしてはsecrets.ymlではなく、master.keyに置き換えれば良いと思われます。
このmaster.keyがないと、credentials.yml.encが解読できないことになりますので、注意が必要です。


まず結論です。

  1. capistranoの設定ファイルconfig/deploy.rbにある以下(32行あたり)のコメントアウトを外します。
    append :linked_files, 'config/database.yml', 'config/secrets.yml'

    ※Rails 5.2以降master.key使ったの場合は:(2018/10/17追記)

    append :linked_files, 'config/database.yml', 'config/master.key'
  2. ※必要がなければ’config/database.yml’を消してもいいと思いますが、ついでに、今回のプロジェクトはMongoDB採用したので、1.の’config/database.yml’を’config/mongoid.yml’に変えます。
  3. 該当ファイルのmongoid.ymlとsecrets.ymlをサーバーの{デプロイルートディレクトリー}/shared/config/の下にアップします。
  4. $ bundle exec cap production deploy #デプロイし直す
  5. {デプロイルートディレクトリー}/shared/config/secrets.ymlの以下
    production:
      secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
    

    production:
      secret_key_base: 91301eecc7163...... # 取得した長いプロダクションのシークレットキー
    

    に変えます。

以上です。

参考1.のように、SECRET_KEY_BASEを~/.bash_profileに設定すればいいよね〜とすぐ納得しましたが、Railsが「app error: Missing `secret_key_base` for ‘production’ environment」のエラーを出し続けました。
最初は環境設定後にRailsに反映されてないだけかと思いましたが、何を再起動しても変わらりませんでした。

参考1.のコメント欄にもやっぱり反映されない(以下)と書かれることもあったが、うまく動くことも書かれました。

It seems, that Rails does’t sees environment variable SECRET_KEY_BASE. printenv shows it, rails c production also displays it, if I inspect ENV. But, i has no effect, when I restarting Unicorn. The only way, that works now, is pasting it directly to secrets.yml – AntonAL

それの違いは使っているWebサービスの違いではないかと後々になって気が付きました。

Nginxを使っているので、nginxが読める環境設定すればいいよね〜と思い、いろいろなところで設定してみました。
参考5.で指摘された/etc/default/nginxや/etc/nginx/sites-enabled/default、/etc/nginx/nginx.confにexport SECRET_KEY_BASE= secretのように設定してみたり、env SECRET_KEY_BASE=secret;で設定してみたりしましたが、いずれもダメでした。後者2箇所はnginx configtestで失敗です。

よく考えると、nginxの設定ファイルに設定すると、同じサーバーに異なるRailsのアプリを動かすと、そのシークレットキーもが同じになり、なんだか良い解決法ではないように思えます。

そして参考2, 3あたりで議論されdotenvのgemをプロジェクトに取り込むことにしてみました。
そのgemを提供しているGithubのサイトでは(参考4.)では、Can I use dotenv in production?のようにあまり推奨ではない的なこと書かれ、使おうと思えば使えるということ書かれてると思います。
それではなあぁ、なんだか違う気もしづつ、とりあえず動くかどうか参考3.のやり方で試してみたところ、効果なかったように見えました。

そこで、.envや.env.productionをプロジェクトルートに入れなくてはいけない点にも引っかかりました。
なぜなら、デプロイするたびにcurrentディレクトリーにあるように調整しなくていけないことになってしまうからです。

なんならリンクファイルにすればいいよねと思い、capistranoの設定ファイルconfig/deploy.rbを開いてみたら、コメントアウトされたappend :linked_filesのことろに例としてconfig/secrets.yml入れられたことに初めて気付きました。
あっ!これでいいじゃん〜と、dotenvのgemを消し、冒頭の解決法にたどり着いた次第です。

参考:
  1. How to solve error “Missing `secret_key_base` for ‘production’ environment” (Rails 4.1)
  2. Where to put environment variables when using nginx and Passenger on Ubuntu
  3. A better way to manage the Rails secret token
  4. bkeepers/dotenv
  5. Making environment variables permanent
  6. nginx.conf で環境変数を読み込む #試してませんが、nginxのperl module
  7. Environment Variables in Nginx Config #試してませんが、nginxのlua module
  8. Rails5.2からsecrets.yml*が廃止されcredentials.yml.encに統合されるよ (2018/10/17追記)

Railsプロダクション環境のsecret_key_base取得

RailsのProduction環境で下記のエラー出たら、~/.bash_profileにSECRET_KEY_BASEを設定すればよい(追記:と思ったら、大間違いだった。詳しくはNginxのsecret_key_base設定)ですが、その秘密鍵の取得方法についてまとめました。

app error: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit` (ArgumentError)

取得方法2つあるようです。

    1. $ bundle exec rails c
    2. > Rails.application.secrets

  1. $ RAILS_ENV=production bundle exec rake secret

後者のほうが短くて良さそうですね。

参考:
  1. How to solve error “Missing `secret_key_base` for ‘production’ environment” (Rails 4.1)
  2. secret_key_baseを取得する

Rails 5.0.6から5.2.1へアップグレード時のhalt_callback_chains_on_return_false問題

Railsのバージョンを5.0.6から現時点の最新版5.2.1へアップグレードした時のエラーですが、以下のが出ました。

{project name}/config/initializers/new_framework_defaults.rb:18:in `<top (required)>': undefined method `halt_callback_chains_on_return_false=' for ActiveSupport:Module (NoMethodError)

調べたところ、config/initializers/new_framework_defaults.rbの18行あたりにある以下の一行を削除(コメントアウト)すると解決です。

ActiveSupport.halt_callback_chains_on_return_false = false
参考:
  1. Obsoleted method `halt_callback_chains_on_return_false` still called in Rails 5.2

Unityでコールバックの実装

Unity使い始めて各種処理はフレームベースのようで、cocos2d-xのようなコールバックが恋しくてたまりませんでした。
コンポーネントごとにスクリプトを付けて単独に動くパーツを作るやり方が望ましいと思いますが、それでもあっちこっちにコールバック使えたらなぁ〜runAction的なものがあればなぁ〜なんて思います。

そこでC#でdelegateのやり方でcallbackを実装するとこうなるかと思います。

    public delegate void MyDelegate(GameObject obj);
    protected MyDelegate callback;

    public void SetMyDelegate(MyDelegate myDelegate)
    {
        callback = myDelegate;
    }

    private void OnCallback()
    {
        if (callback != null)
            callback(gameObject);
    }

この場合、スクリプト自分自身のオブジェクトを送り返してます。

参考:

  1. How to make a callback function
  2. Using Delegates (C# Programming Guide)