keterでデプロイした場合yesodアプリケーションが生成するURLがhttpsではなくhttpになってしまう問題を解決しました

yesodアプリのketerへの切り替えを試しましたが,icuライブラリのバージョンが一致せず,静的リンクもできなかったので,切り替えができませんでした - ncaqの続きです.

自分の問題解決のために時系列順に書き殴ったメモなので纏まっていません.ご了承下さい.

httpsがhttpになってしまう

harendra-kumar/unicode-transforms: Fast Unicode normalization in Haskellを使うことによってICUライブラリへの依存を消滅させました.なので,ubuntuにデプロイすることが出来るようになりました.

そこで,デプロイしてみたのですが,何故かyesodのstaticファイルが全てhttpで配信されるようになってしまいました.

アプリケーションはhttpsで配信されるので,混在コンテンツのエラーでscriptファイルが読み込まれなくなってしまいました.

URLに直にアクセスすると応答するので,配信自体は上手く行っているのに,何故かscript srcのリンクがhttpsではなくhttpになってしまっているのが原因のようです.

keterのrequires-secure: trueの効果でリダイレクトはされるようになっているようです.

よく見ると,他のaによるリンクもリダイレクトによって気が付かないだけでhttpでのリンクになっているため,これはAPPROOTがhttpベースになってしまっているようですね.

試しにketer-config.yamlを編集して,環境変数APPROOTをhttpsバージョンに設定してあげれば,上手く読み込みがされました.

keterは複数のアプリケーションを本来取り扱えるので,全体に影響するketer-config.yamlAPPROOTをベタ書きするのは良くないのですが.この場合他のアプリケーションをデプロイしたいときは,他にサーバを用意するか,仮想環境を立ち上げる他ないようですね.今回はEC2を使っているので,他にアプリケーションを別居させたりはしないので,問題はありませんが…

TLSをwarpが解除しているせいでした

問題は一応解決しましたが,どうもダーティな方法なので,バグかどうかsnoyberg/keter: Web app deployment managerのissueで報告および質問をしておこうと思ってissueを検索しました.

そしたら,このページを見つけました.Overriding approot · yesodweb/yesod Wiki

このページの文章を読んで気がついたのですが,nginx,ELB,warpなどでTLSを使う場合,X-Forwarded-Protoを参照してhttpsに切り替えないとダメなようですね.

これまではsystemdのユニットファイルの環境変数上書きでhttpsなURLを書いていたので,nginxを使っていても気が付きませんでした.

ここの最後のコードのようにFoundation.hsapprootを修正したのですが,httpを使ったままになってしまいました.なぜ…

よく英文を見て見たら最後のコードはX-Forwarded-Protoを参照せずに実際にTLSで接続してる場合のみhttpsを使うようでした.参照する方はこっち.

approot = guessApproot

こうするとAPPROOTではなくrequest headerからホストを推測してくれるようになります.他のアプリケーションだとketerでもこの問題発生しなかった気がするので,私がデフォルトから変更してしまったのかな?