Nginx Proxy の下で GrowthForecast を動かした話
GrowthForecast を動かしたい欲がさきほど突然現れたので、さくらのVPSにUbuntuをセットアップしてGrowthForecastを設定してみた。
インストール方法はさておいて、設定するときに注意すべき点が幾つかあったので、それらについて列挙してく。
目的
127.0.0.1:5125 で立てた GrowthForecast を、同ホスト上に立てた Nginx でリバースプロキシし、 http://example.com/growthforecast という URL で見られるようにすること。
サブドメインを使いたくないようなケースね。
想定してるのは、外部に GrowthForecast のグラフを見せ、データの挿入は 127.0.0.1 以外から許さないような用途。
Nginx での基本的な Proxy 設定
とりあえず GET/HEAD だけ許容して 127.0.0.1:5125 に Proxy しとこう。
location /growthforecast { if ($request_method !~ ^(GET|HEAD)$) { return 403; } proxy_pass http://127.0.0.1:5125; }
って思うじゃん。
ダメなんです
原因は、ページ内のすべてのリンクが http://127.0.0.1:5125/ を向いてしまっていること。実にロケンロー。
ただ、こんな問題を本家が認識していないはずもなく、 https://github.com/kazeburo/GrowthForecast/issues/3 には対処法が書かれている。
GrowthForecast で行うべき設定
GrowthForecast では、前段に proxy が挟まる場合にはその設定を行う必要がある。と言っても、起動オプションを一つ追加するだけだ。
$ growthforecast.pl --front-proxy=127.0.0.1
こっちはこれで問題ない。
Nginx で行うべき設定
Nginx 側としては、次の二点を行うことになる。
- パスの書き換え
- ホスト名の書き換え
パスの書き換え
Nginx で特に設定を行わない場合、 http://example.com/growthforecast/ にアクセスすると、GrowthForecast 側には /growthforecast/ というパスが伝わる。ここは当然 / であることを期待しているわけなので、 Rewrite が必要となる。
rewrite ^/growthforecast/(.+) /$1 break; rewrite ^/growthforecast / break;
書き換えルールくらい一行で書けそうなものだけど、なぜかうまくいかなかったので二行で無理やり解決。
ホストの通知
GrowthForecast では、HTML中にある各種リンクがすべてフルパスで指定されている。で、プロキシの裏側にいる場合は 127.0.0.1:5125 で立っているもんだから、ページ内のリンクはすべて http://127.0.0.1:5125/ に対するリンクになってしまう。
先ほどの --front-proxy オプションをつけるのは、これを解決させるためだ。
ここで指定されたアドレスからの接続であった場合、先ほどの 127.0.0.1:5125 の代わりに指定されたホスト名を使用するようになる。
つまり、 Nginx 側でも渡すホスト名を指定してやらねばならない。
proxy_set_header Host $host/growthforecast;
この設定を入れることで、このアドレス問題が解決されるわけ。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html" charset="utf-8"> <link rel="stylesheet" href="http://example.com/growthforecast//css/bootstrap.min.css"> <style type='text/css'> body {
そんな感じ。
何が起きているか?
Nginx からのメッセージを netcat とかで適当にキャプチャすればよくわかる。
$ nc -l 5125 GET /growthforecast HTTP/1.0 Host: 127.0.0.1:5125 ...
適当に設定した Nginx では GrowthForecast に対してこういうメッセージが来ていたところ、
$ nc -l 5125 GET / HTTP/1.0 Host: example.com/growthforecast ...
こんな HTTP Request が来るようになるわけ。
まとめ
以上まとめると、次のような感じになる。
Nginx 設定
location /growthforecast { if ($request_method !~ ^(GET|HEAD)$) { return 403; } rewrite ^/growthforecast/(.+) /$1 break; rewrite ^/growthforecast / break; proxy_pass http://127.0.0.1:5125; proxy_set_header Host $host/growthforecast; }