Nginx Proxy の下で GrowthForecast を動かした話

GrowthForecast を動かしたい欲がさきほど突然現れたので、さくらのVPSUbuntuをセットアップして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;
}
GrowthForecast 起動オプション
 $ growthforecast.pl --front-proxy=127.0.0.1


オッケー☆

知っていればなんてことのない話なのだけど、ブログにまとまっているところを見かけないので、ちょっと残してみることにした。

ただ今回の設定だと URL の途中にダブルスラッシュ入ってかっこわるい。リダイレクトルールの書き方とか、もっといい設定がありそう。