Gyazo、便利ですよね。大変便利なので、社内でプライベートなGyazoサーバを用意して使っている会社も多いと思います。
うちでもサーバのパフォーマンスは特に必要ないので社内に適当なVMを立てて運用していたのですが、数年単位で運用していると画像ファイルが増えていくためdiskをなんとかする必要に迫られました。
ここでどんどん増えるファイルはAmazon S3に逃がそう、という自然な発想に至るわけですが、Gyazoサーバアプリが投稿を受けたときにS3にアップロードするような改修をするのは年末の忙しい時期に面倒。楽したい。
ということで S3 と nginx を組み合わせていいかんじに運用できるようにしてみました。
Gyazoに限らず、
- ローカルに書き込んだファイルをhttpで閲覧する
- 一度書き込まれたファイルには変更がない
- ファイルは消えないでどんどん増える
ようなものには応用できると思います。
S3 に bucket を用意
普通に S3 に bucket を作ります。ここでは internal-gyazo.example.com とします。
社内のみにアクセス制限している画像なので、S3から直接一般に公開してしまうわけにはいきません。しかし、S3 API をちゃんと実装して nginx から画像を取得するのは面倒なので、IPアドレス制限をして特定のIPアドレス(ここでは社内gyazoサーバ) からのみ閲覧を許可します。
bucket policy の設定を開いて、AWS Policy Generator で生成した以下のようなJSONを記述します。
{ "Version": "2008-10-17", "Id": "Policy1", "Statement": [ { "Sid": "Stmt138795173604", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::internal-gyazo.example.com/*", "Condition": { "IpAddress": { "aws:SourceIp": "192.0.2.1/32" } } } ] }
- s3:::internal-gyazo.example.com/* に対して
- 192.0.2.1/32 から
- s3:GetObject を許可する
というルールです。
nginxの設定
try_files を利用して、
- ローカルファイル (/usr/local/gyazo/data/*) がある場合はそれを返す
- ない場合は S3 に proxy_pass
という設定をします。
実際は別途Basic認証を掛けているため、AuthorizationヘッダをS3に送ってしまうと認証エラーになるので proxy_pass する前に削除しています。
S3 のホスト名を proxy_pass に直書きしないで一旦変数に set している記述については、Nginxでproxy_passにホスト名を書いた時の名前解決のタイミング - (ひ)メモ を参照してください。
また、無駄に S3 にリクエストを飛ばさないために proxy_cache も設定しています。
proxy_cache_path /var/lib/nginx/tmp/proxy levels=1:2 keys_zone=gyazo:500m max_size=1000m inactive=24h; server { listen 80 default_server; resolver 127.0.0.1; location /gyazo/data { root /usr/local; try_files $uri @s3; } location @s3 { set $s3_host "internal-gyazo.example.com.s3-ap-northeast-1.amazonaws.com"; proxy_set_header Host $s3_host; proxy_set_header Authorization ""; proxy_set_header Cookie ""; proxy_cache gyazo; proxy_cache_valid 404 1m; proxy_cache_valid any 24h; proxy_pass https://$s3_host; } location /gyazo { proxy_pass http://127.0.0.1:5000; } }
運用
- Gyazoサーバに投稿があるとローカルファイルが生成されます。その後の閲覧はローカルファイルから配信されます
- 適当なタイミングで、ローカルファイルを S3 にアップロードして削除します
- ローカルファイルが削除された後は、S3 から GET したファイルが配信されます
これで、ローカルファイルは適宜削除できるので disk 容量を気にする必要がなくなりました。年末にdisk 掃除ができてすっきりです。