https,nginx,リバースプロキシ使用でWordPressがリダイレクトループにハマった時

   

やっとクリアした…何回目のアタックだっただろう。昨日夕方にリトライして3時間…。意味を理解。

そもそもなんでこんなことになるのかというと、nginxのconfファイルの設定の意味を詳細に理解していないという所にあるのだけど。同様にハマる人もいると思うのでシェア。情報が意外と少なくて困った。

ハマる条件

  • WordPressをまるごとSSL化する
  • nginxをつかっている
  • リバースプロキシ

発生する事象

  • サイト及び管理画面におけるリダイレクトループの発生

実行したいこと

  • httpでアクセスがあったらhttpsにリダイレクトする
  • 問題なくWordpressが稼働する

解決方法

  1. サーバーブロックはhttpとhttpsで分ける
  2. httpsのサーバーブロックにヘッダ情報を追加

サーバーブロックはhttpとhttpsで分ける

httpのアクセスをhttpsにリダイレクトする為にそうする。海外のフォーラムなんかを見ていても、これは色んな所に書いてあった。具体的には以下の様にする。

server {
listen 80;
server_name 設定したいドメイン(例:yourdomain.com);
return 301 https://yourdomain.com$request_uri;
}

server {
listen 443 ssl;

以下https設定

httpsのサーバーブロックにヘッダ情報を追加

ここでドハマりした。

そもそものnginxの設定はUKlabさんのを使ってる。

さくらのVPSでWordPressを動かそう – nginx設定編 - - UKLab開発者ブログ


WordPress用に細かな設定がされていて良いのだけど、それ故にハマった。
やらなくてはいけないことはここにかいてある。

WordPressをhttps化してnginx reverse proxy配下で使うには | 家鯖構築日記


nginxのconfファイルを書き換えることと、Wordpressのwp-config.phpに追記をするという二点。まずはnginxの方から。
httpsのサーバーブロックに以下を追記する。
重要なのはここだ

        ssl_ciphers             HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;
    
        location / {
                proxy_redirect                          off;
                proxy_set_header Host                   $host;
                proxy_set_header X-Forwarded-Proto      https;
                proxy_set_header X-Forwarded-Server     $host;
                proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;
                proxy_pass                       http://backend.hogehoge.site/;
        }

これ。全部必要。
httpsのサーバーブロック全体はこんな感じ。

server {
    listen 443 ssl;

    # example.com、example.com/wordpress、wp.example.comなどを指定する。
    server_name yourdomain.com;
    # ドキュメントルートの設定
    root        /var/www/html/yourdomain.com;
    index       index.html index.htm;
    charset     utf-8;

    # 秘密鍵 (cert. key)
    ssl_certificate_key /etc/nginx/ssl/秘密鍵.key;
    # 合体証明書
    ssl_certificate  /etc/nginx/ssl/合体証明書.crt;

    ssl_protocols           TLSv1 TLSv1.1 TLSV1.2;
    ssl_ciphers             HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    access_log  /var/log/nginx/$host.access.log  main;
    error_log   /var/log/nginx/$host.error.log;

    # アクセスログ、Not Foundログを無効にするための設定を読み込みます
    include     /etc/nginx/conf.d/common/drop.conf;

    rewrite /wp-admin$ $scheme://$host$uri/ permanent;

    # 変数の初期化
    set $mobile '';
    # 携帯やスマートフォンを別々にキャッシュしたい場合は先頭の#を外す
    #include /etc/nginx/conf.d/common/mobile-cache.conf;

    location ~* ^/wp-(content|admin|includes) {
        index   index.php index.html index.htm;
        if ($request_filename ~ .*.php) {
            break;
            proxy_pass http://backend;
        }
        # expiresヘッダー用の設定を読み込みます。
        include /etc/nginx/conf.d/common/expires.conf;
    }

    location / {
        # PHPファイルへのアクセスの場合バックエンドに処理が投げられる。
        if ($request_filename ~ .*.php) {
            break;
            proxy_pass http://backend;
        }
        # expiresヘッダー用の設定を読み込みます。
        include /etc/nginx/conf.d/common/expires.conf;

        # デフォルトではキャッシュするように変数に0をセットする。
        set $do_not_cache 0;
        # WordPressにログインしている場合はキャッシュしないように変数に1をセットする。
        if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
            set $do_not_cache 1;
        }
        # POSTアクセスの場合もキャッシュしないように変数に1をセットする。
        if ($request_method = POST) {
            set $do_not_cache 1;
        }
        proxy_no_cache     $do_not_cache;
        proxy_cache_bypass $do_not_cache;

        proxy_redirect     off;
        proxy_cache        czone;
        proxy_cache_key    "$scheme://$host$request_uri$mobile";
        proxy_cache_valid  200 0m;

        # do_not_cacheの値が1の場合バックエンドに処理が投げられる。
        proxy_pass http://backend;
    }

        proxy_set_header Host                   $host;
        proxy_set_header X-Forwarded-Proto      https;
        proxy_set_header X-Forwarded-Server     $host;
        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;

    # phpMyAdmin用設定を読み込む(このドメインで使用する場合のみ先頭の#を外して下さい。)
    #include     /etc/nginx/conf.d/common/phpmyadmin.conf;

    # postfixadmin用設定を読み込む(このドメインで使用する場合のみ先頭の#を外して下さい。)
    #include     /etc/nginx/conf.d/common/postfixadmin.conf;

    # 50x系のページ設定/usr/share/nginx/htmlにあるファイルが使用される
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

17〜20行目と76〜79行目が追記した部分。

次にwp-config.phpについて。
これは以下の通り

<?php

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
    && $_SERVER['HTTP_X_FORWARDED_PROTO'] === "https") {
  $_SERVER['HTTPS'] = 'on';
}

define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

〜ここから下は元々書かれている部分〜

以上で完成です。めでたしめでたし。

オススメNginx本

nginx実践入門 (WEB+DB PRESS plus) 単行本(ソフトカバー) – 2016/1/16

nginxを現場で活用するための知識を、実践的なノウハウを交えて解説した書籍です。nginxのインストール方法や基本的な設定方法からはじめ、nginxを利用した「静的コンテンツ配信サーバ」「HTTPSサーバ」「Webアプリケーションサーバ」「大規模コンテンツ配信システム」の構築方法をそれぞれ詳しく紹介しています。後半ではnginxサーバのモニタリングやログの収集、そして軽量スクリプト言語Luaでnginxを拡張する方法について解説しているので、nginxをこれから使う方はもちろん、さらに活用したい方にもお勧めです。

 - Tips, Wordpress