Google Cloud Storage をnginx でhttpsで公開する

Google Cloud Storage(GCS) は独自ドメインでファイルを公開する機能が付いているが、http のみしか対応していない。 https で対応するには以下のようにnginxでプロキシするなどの方法を取る必要がある。

config

画像用ドメイン: static.kmn.jp バケット名: static.kmn.jp (※ https化にはlet's encrypt を利用しているため、そのための設定も入っている。)

$ cat /etc/nginx/conf.d/static.kmn.jp
# Cache 10GB for 1 Month
proxy_cache_path           /var/cache/nginx levels=1:2 keys_zone=GS:10m inactive=720h max_size=10240m;

upstream gs {
    server                   'storage.googleapis.com:443';
    keepalive                100;
}

server {
    set $my_domain "static.kmn.jp";
    server_name static.kmn.jp;

    ###
    # <tls setting>
    ###

    listen 443 ssl;
    # nginx 1.9.5 以降の場合
    # listen 443 ssl http2;

    server_name static.kmn.jp;
    server_tokens off;

    ssl_certificate     /etc/letsencrypt/live/static.kmn.jp/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/static.kmn.jp/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    # 環境によっては off にすると動かないので注意 (default は on)
    ssl_session_tickets on;

    # 2048bit 推奨
    ssl_dhparam /etc/ssl/private/dhparam.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_prefer_server_ciphers on;

    ###
    # </tls setting>
    ###


    # Logs
    access_log off;
    error_log /var/log/nginx/static.kmn.jp.error.log error;

    # Cache Control
    expires max;
    add_header Cache-Control "public, max-age=31536000";

    # Nameserver
    resolver                   8.8.8.8 valid=300s;
    resolver_timeout           10s;

    # Proxy Cache
    proxy_temp_path /tmp/nginx;
    proxy_cache_lock on;
    proxy_cache_key "$uri"; # Ignore Parameters

    ## https://github.com/FRiCKLE/ngx_cache_purge
    #proxy_cache_purge on from 127.0.0.1;

    # Limit Request Methods to GET|HEAD|PURGE
    if ( $request_method !~ "GET|HEAD|PURGE" ) {
        return 405;
    }

    location / {
        proxy_set_header    Host storage.googleapis.com;
        proxy_hide_header   x-goog-hash;
        proxy_hide_header   x-goog-generation;
        proxy_hide_header   x-goog-metageneration;
        proxy_hide_header   x-goog-stored-content-encoding;
        proxy_hide_header   x-goog-stored-content-length;
        proxy_hide_header   x-goog-storage-class;
        proxy_hide_header   x-xss-protection;
        proxy_hide_header   accept-ranges;
        proxy_hide_header   alternate-protocol;
        proxy_hide_header      Set-Cookie;
        proxy_ignore_headers   "Set-Cookie";
        proxy_intercept_errors on;

        proxy_cache            GS;
        proxy_cache_valid      200 720h; # Cache For 1 Month
        proxy_cache_bypass     $http_cache_purge;
        add_header              X-Cache $upstream_cache_status;

        proxy_http_version     1.1;
        proxy_set_header       Connection "";
        proxy_pass             https://gs/$my_domain$uri;
    }
}

# let's encrypt の自動更新用の設定
server {
  listen        80;
  server_name   static.kmn.jp;

  location      '/.well-known/acme-challenge' {
  default_type  "text/plain";
    root        /tmp/letsencrypt-auto;
  }

  location / {
    return      301 https://$server_name$request_uri;
  }
}

設定反映

sudo service nginx configtest && sudo service nginx reload

参考

touhonoob/gs.nginx.conf