【オブジェクトストレージ × Nginx】オブジェクトストレージとNginx でブログを作る

この記事は [NIFTY Advent Calendar]()2日目の記事です。
1日目は、[fuku2014](http://qiita.com/fuku2014)さんの「[【Swift × Node.js】サーバーレスアーキテクチャでアプリにガチャを実装してみた](http://qiita.com/fuku2014/items/ec36e752007c502b2f9f)」、3日目は[yaaamaaaguuu](http://qiita.com/yaaamaaaguuu)さんの「[レガシーなPHPを改善する為に(新入社員が勝手に)取り組んだ3つの事](http://qiita.com/yaaamaaaguuu/items/6d1e84babe21992b721a)」です。

# 概要

ニフティクラウドの[オブジェクトストレージ](http://cloud.nifty.com/service/obj_storage.htm)とNginxを使ってブログを構築しました。
その中で、オブジェクトストレージをWEBサーバーのバックエンドとして利用する方法をご紹介します。

ニフティクラウド オブジェクトストレージは単体で静的コンテンツの保管・配信が可能ですが、WEBコンテンツ配信サーバーとしては少々機能不足です。
そこで、オブジェクトストレージにコンテンツを入れて、Nginx をリバースプロキシとしてフロントに設置します。
そうすることで、ユーザーからのリクエストに応じて後ろのオブジェクトストレージからコンテンツを取得してレスポンスを返したり、アクセス頻度の高いコンテンツはNginx サーバー内にキャッシュするといったことが可能になりました。

# 成果物紹介

http://blog.conhumi.net/
今回構築したブログです。
まだ記事は少ないですが、徐々に増やしていきたいと思っています。

# 準備

## 記事の準備

ブログ記事を準備します。
自分でHTMLやCSSを書いても良いですが、markdown などからいい感じのブログページを出力できる静的サイトジェネレータというものがあります。
上記のブログでは、go言語で実装された静的サイトジェネレータの[Hugo](https://gohugo.io/)を使いました。

任意の方法で記事を作成し、HTML, CSS, JavaScript 等のファイル群を準備します。

## オブジェクトストレージへのアップロード

オブジェクトストレージに記事を配置します。
ニフティクラウド オブジェクトストレージ は Amazon の Simple Storage Service (S3) の API と互換性のあるAPIが使えるため、記事の作成に利用したPCからS3のツールを利用して簡単にアップロードすることができます。

aws cli を使って記事をアップロードする例を示します。
アクセスキーとシークレットキーをニフティクラウドのコントロールパネルで確認しておき、

```
$AWS_ACCESS_KEY_ID
$AWS_SECRET_ACCESS_KEY
```

という環境変数に設定しておきます。


記事が `./contents/` に格納されているとすると、

```
aws --endpoint-url http://jp-east-2.os.cloud.nifty.com s3 sync --delete contents/ s3://blogbucket/
```

というコマンドで、`contents/` 配下の記事が全てオブジェクトストレージの `blogbucket` というバケット配下にアップロードされます。
`sync` サブコマンドを使っていますので、2回目以降は `contents/` ディレクトリと `blogbucket` 配下が同じになるようにアップロード・削除をしてくれますので便利ですね。

## Nginx サーバーの準備

Nginx とオブジェクトストレージを連携するために、Nginx のサーバーを立てる必要があります。

ニフティクラウドでも簡単にサーバーが立てられるので、上記のブログではそちらを利用し CentOS 7.1 のサーバーを利用しています。

[サーバーの作成方法はこちら](http://cloud.nifty.com/help/server/new.htm)

# Nginx × オブジェクトストレージ の連携

オブジェクトストレージ側でコンテンツを公開設定にして保存しておくと、Nginx のプロキシ機能を使うだけで簡単に連携することが可能です。
ただ、そうするとNginxを経由しなくてもオブジェクトストレージのコンテンツにアクセスする事ができるため、何かと不便な気もします。

そこで、オブジェクトストレージではコンテンツを非公開設定にしておきつつ、Nginx でシグネチャを解決する方法で連携する方法を紹介します。

Nginx は下記の感じで設定・ビルドしました。
必要なモジュールは適宜追加してください。

```
# export LUAJIT_LIB=/usr/local/lib
# export LUAJIT_INC=/usr/local/include/luajit-2.0

# ./configure \
    --prefix=/usr/local/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --with-pcre=/usr/local/src/pcre-8.39 \
    --with-zlib=/usr/local/src/zlib-1.2.8 \
    --with-openssl=/usr/local/src/openssl-1.0.2h \
    --with-http_ssl_module \
    --with-stream_ssl_module \
    --with-ld-opt="-Wl,-rpath,/usr/local/lib" \
    --add-module=/usr/local/src/ngx_devel_kit-0.3.0 \
    --add-module=/usr/local/src/headers-more-nginx-module-0.31 \
    --add-module=/usr/local/src/lua-nginx-module-0.10.6 \
    --add-module=/usr/local/src/set-misc-nginx-module-0.31

# make
```

Nginx をオブジェクトストレージのフロントサーバーとして
プロキシ且つ認証を解決する設定はこんな感じです。（`Server` コンテキストだけ。）

```
server {
    listen      80;
    server_name <WEB Page Domain>;

    charset utf-8;

    more_clear_headers  'x-amz-*';
    more_clear_headers  'ETag';

    location / {

        set $os_backend     'jp-east-2.os.cloud.nifty.com';
        set $os_bucket      '<BUCKET_NAME>';
        set $os_access      '<ACCESS_KEY>';
        set $os_secret      '<SECRET_KEY>';
        set $url_full       $uri;
        set_by_lua $now     "return ngx.cookie_time(ngx.time())";
        set $string_to_sign "$request_method\n\n\n\nx-amz-date:${now}\n/$os_bucket$url_full";
        set_hmac_sha1       $os_signature  $os_secret   $string_to_sign;
        set_encode_base64   $os_signature  $os_signature;

        proxy_ignore_headers Cache-Control;
        proxy_set_header    Host    $os_bucket.$os_backend;
        proxy_set_header    x-amz-date  $now;
        proxy_set_header    Authorization 'AWS $os_access:$os_signature';

        resolver    8.8.8.8;

        proxy_pass http://$os_bucket.$os_backend$uri;
    }

}
```

上記の設定を nginx.conf 等に記述すると、
Nginx で受けたリクエストに応じて、オブジェクトストレージからオブジェクトを取得してクライアントに返却するプロキシとして動作させることができます。

# まとめ

オブジェクトストレージ と Nginx を使って簡単なWEBサイトを構築しました。

オブジェクトストレージを使うことで、配置したファイルをニフティクラウドのコンソールから確認することができて、ちょっと便利だなと思います。
![参考画像](https://qiita-image-store.s3.amazonaws.com/0/49886/1f319e93-652c-dd3a-e3b1-404d54c9488c.png)


また、Nginx のプロキシサーバーをニフティクラウドのリージョン毎に配置する事で簡易的なCDNのような使い方も考えられます。
オブジェクトストレージとニフティクラウドの他の機能を組み合わせる事で、様々な活用方法が考えられると思います。

既にニフティクラウドを使っている方もそうでない方も、便利な使い方を探してみてください。