背景
本番環境を設定したあとにrails s
ができなくなった話。
AWS(EC2)/NGINXの設定を行った後、本番環境の.envをローカルの開発環境の.envにもコピペしてしまいrails sによってローカルのRailsサーバーを起動することができなくなってしまいました。
そこで、解決した手順をまとめました。
開発環境
Ruby 2.7.2
Ruby on Rails 6.1.3
PostgreSQL 13.3
環境変数はcredentialsだと復号化されていて、開発者側からもわかりづらかったため、.envで設定し直しました。
環境変数には、database.ymlで使う以下の変数を設定しました。
- DBホスト名
- DB名
- DBユーザー名
- DBパスワード
database.ymlは以下の感じです。
デフォルトとしてホスト名、DB名、DBユーザー名、DBパスワードをセットし、開発/本番/ステージングのそれぞれの環境で使えるように設定しました。
default: &default
adapter: postgresql
pool: 5
host: <%= ENV['DATABASE_HOST'] %>
database: <%= ENV['DATABASE_NAME'] %>
username: <%= ENV['DATABASE_USER'] %>
password: <%= ENV['DATABASE_PASSWORD'] %>
development:
<<: *default
production:
<<: *default
staging:
<<: *default
結論
まず結論から言うと、以下の2つが原因でした。。
・環境変数の理解不足
・データベースの理解不足
発生したエラー
OpenSSL::Cipher::CipherError
ActiveSupport::MessageEncryptor::InvalidMessage (ActiveSupport::MessageEncryptor::InvalidMessage)
このエラーで調べると、APIキー等の秘匿情報を.envで管理しているにも関わらず、master.keyとかcredentialsが存在していることが問題という記事が出てきたので、
何か怖かったので大元のmaster.keyではなく、credentialsの方を削除しました。
これで直ったっしょ!!
お、rails sできる!!
localhost:3000……あれ。つながらない。。なんで。。。
ここでメンターさんに泣きついて解説してもらいました。
.env内の内容がこんな感じ。
DB_HOST = 本番環境のもの
DB_NAME = 本番環境のもの
DB_USER = postgres
DB_PASSWORD = 本番環境のもの
環境変数についての勉強不足
うーん、当たり前。
ローカルの場合、host名はlocalhost
だと思います。
なのに、本番環境のホスト名を記載してしまっていた!!
何故かわからないけど、本番環境とローカル開発環境の環境変数が共通と思い込んでしまっていたんですね。
なのでローカル側の.envを以下のように修正。
DB_HOST = localhost
DB_NAME = アプリ名_dev *ここはわかりやすければ何でも良い
DB_USER = DBユーザー名
DB_PASSWORD = DBにログインするためのパスワード
合わせて、開発者しか見ることができないかつ、普通の変数(定数)管理なのでわかりやすいため.envで管理することを選択。
この時点でmaster.keyを使う必要がなかったので消す必要があった。
残しておくと、credentialsがmaster.keyを読み取ろうとしてしまうため。なのでmaster.keyは思い切って削除。
これで上記エラーが解決できました。
master.key / credentials.ymlとは?
この2つのファイルは、秘密情報を管理するためのものでRails5.2から導入された仕組みです。
要は大事なデータを復号化して流出しないようにするためのものです。
Rails5.1までは、秘密情報(=環境変数)はお互いのローカル環境に各自で設定する必要がありました。
git push & git pullと合わせて、環境変数を設定したメンバーが他のメンバーに直接伝える必要があったんですね。
この手間を節減かつ、手軽にチーム内共有できるようにするためにこの仕組みが追加されました。
データベースの勉強不足
上記を修正後、確認のdb:migrate!!
rails aborted!
ActiveRecord::ConnectionNotEstablished: FATAL: role "postgres" does not exist
(略)
・
・
・
Caused by:
PG::ConnectionBad: FATAL: role "postgres" does not exist
(略)
・
・
・
postgresというroleがないぜ!!って怒られました。
role(=ロール)というのは postgresqlを使うユーザーやグループのデータベースにアクセス権を管理する機能。
これの設定ができてませんよと言われている。
postgreSQL設定の流れについては以下にまとめました!
PostgreSQLのインストール~DBの作成
ロールの設定方法
今回はローカルかつポートフォリオ開発なのでそこまで厳重にはやりませんでした。
細かく設定したい場合は以下を参考にしてください。
参考: エンジニアの入り口
CREATE ROLE 名前 SUPERUSER;
スーパーユーザー状態にして、
ログイン以外の操作もできるように権限付与
CREATE ROLE 名前 CREATEROLE;
上記のコマンドでロールを作成。
\qでpsqlから抜け出せる
これでrails s成功!!
まとめ
今回のエラーの真の原因は2つあると思う。
この反省を活かして次に活かしたいです。
-
自分の理解不足。
開発環境、本番環境、テスト環境という複数の環境があり、.envファイルはgithub上には上がらない設定にしているので、本番環境とは別の設定のはずであるというところに気がつけなかった点。環境変数の意味や.envとcredentials & master.keyの違いは把握しておくべきだった。 -
データベースの理解不足
postgresqlのロールという機能の理解不足。MySQLやpostgresql、Oraqleなど複数のRDBMS製品が存在している以上、それぞれが何かしらの独自性を持っているはず。(じゃなきゃ淘汰される)自分が使うツールについては必ずどんな機能を持つのかを理解すべき。