Nginx が non-www を www にリダイレクトしない

Nginx が non-www を www にリダイレクトしない

ユーザーがブラウザに example.com と入力した場合に、ユーザーを www.example.com にリダイレクトするように Nginx を設定する必要があります。その理由は、SEO コンサルタントが、優先ドメインは 1 つだけにすべきだと言ったためです。そうでないと、Google はそれをコンテンツの重複と見なします。とにかく...

つまり、サーバーに Letsencrypt の SSL も設定していますが、example.com から www.example.com へのリダイレクトを実現できません (サーバーは両方のバージョンを受け入れます)。私が使用している構成は次のとおりです。

server {
    listen 80; 
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    server_name example.com www.example.com;
    root /home/my_site;
    index index.php index.html index.htm;

    # for letsencrypt
    location ~ /.well-known {
        allow all;
    }   

    location / { 
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }   

    error_page 404 /404.html;

    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

==== 更新 ====

私は、次の質問に対する回答の 1 つでTim がアドバイスしたように (そして私は常に と にしnginx -tています) 、設定を に変更しました。restart

server {
    listen 80; 
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://www.example.com$request_uri;
}    

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.example.com;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    root /home/ankush/wp_ankushthakur;
    index index.php index.html index.htm;

    # for letsencrypt
    location ~ /.well-known {
        allow all;
    }   

    location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    error_page 404 /404.html;

    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

すべてのバリエーションの出力curl -kとアクセス ログは次のとおりです (よりシンプルなソリューションを望んでおり、サーバーを混乱させたくないため、Nginx をソースからビルドしませんでした)。

curl -k http://example.com
Curl output: 301 - Moved permanently
Access logs: "GET / HTTP/1.1" 301 194 "-" "curl/7.47.0"

curl -k http://www.example.com
Curl output: 301 - Moved permanently
Access logs: "GET / HTTP/1.1" 301 194 "-" "curl/7.47.0"

curl -k https://example.com
Curl output: 301 - Moved permanently
Access logs: "GET / HTTP/1.1" 301 194 "-" "curl/7.47.0"

curl -k https://www.example.com
Curl output: <Blank>
Access logs: "GET / HTTP/1.1" 301 5 "-" "curl/7.47.0"

最後のセクションに注意してください。CURL 出力は空白ですが、アクセス ログには永続的なリダイレクトが示されています。

面白いことに、2 番目のブロックをコメント アウトしてserverNginx を再起動すると、期待とは逆の効果、つまり www が非 www にリダイレクトされるという結果になります。この (3 番目の) バージョンの構成では、www.example.com の HTTPS バージョンはどこにも記載されていないため、このようなことが起こるのは驚きです。

答え1

おそらく、HTTP のみでリダイレクトしており、HTTPS ではリダイレクトしていないことが原因です。リダイレクトする vhost に HTTPS を追加し、example.com名前だけを残してください。

さらに、あなたがやっていることは、現代の人々が実際にやっていることと正反対です。一般的なアプローチは、遺産を葬り去ることです。www古い時代のプレフィックスを廃止し、www

答え2

ここで重要なのは、4つのURL(wwwドメインと非wwwドメインのhttpバージョンとhttpsバージョン)を扱う必要があることです。問題は、wwwドメインと非wwwドメインのhttpバージョンを次のURLに転送していることです。https://wwwドメインですが、メインサーバーブロックは両方をリッスンしていますhttps://example.comそしてhttps://www.example.com

必要なのは、別のサーバーブロックを作成して転送することだけです。https://example.comhttps://www.example.comサーバー。これには https セットアップを含める必要があります。

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  include snippets/ssl-example.com.conf;
  include snippets/ssl-params.conf;

  server_name example.com;
  return 301 https://www.example.com$request_uri;
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  include snippets/ssl-example.com.conf;
  include snippets/ssl-params.conf;

  server_name  www.example.com;

  # Main server block for main server continues
}

標準的な例

私は持っているチュートリアルダウンロード可能な設定ファイル付き。標準的な例を以下に示します。

これがうまくいかない場合は、各バリエーション (http と https、www と non-www) を -k オプションで curl してヘッダーを表示し、質問を編集してヘッダーを含めます。

# Main server
server {
  server_name www.example.com;
  listen 443 ssl http2;
  # etc, add all locations, call PHP or servers, etc
}


# Forward http requests to https www server
server {
  listen       80;
  server_name  example.com www.example.com;
  return       301 https://www.example.com$request_uri;
}

# Forward https non-www requests to the https www server
# Requires https setup for this server
server {
  listen 443 ssl http2;
  server_name example.com;

  ssl_certificate /var/lib/acme/certs/***CERT_DIRECTORY/fullchain;
  ssl_certificate_key /var/lib/acme/certs/***CERT_DIRECTORY/privkey;

  # Set up preferred protocols and ciphers. TLS1.2 is required for HTTP/2
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;
  ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

  return 301 https://www.example.com$request_uri;
}

問題解決 問題を診断する最良の方法は次のとおりです。

  • アクセス ログと併せて、各ドメイン バリアントに対して「curl -k」(ヘッダーの表示) を使用します。返される http ステータス コードから、何が起こっているかがわかります。200 はページ、301 は永続的なリダイレクト、302 は一時的なリダイレクトです。
  • Nginxにheaders_moreモジュールがあることを確認します。ソースからNginxを構築する非常に簡単です。これにより、レスポンスにhttpsヘッダーを追加できます。これは優れた診断ツールです。このようなステートメントを使用して、どのブロックが実行されているかを調べることができます。

add_header Z_DEBUG "場所名またはメッセージ";

答え3

最終的に、SEO 担当者を説得して、www なしのドメインをプライマリとして扱うようにできました。www を www なしのドメインにリダイレクトするのに機能した構成は次のとおりです。逆の試みでも同様の構成でしたが、何が妨げになっているのかはわかりません。

server {
    listen 80; 
    listen [::]:80;

    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    server_name example.com;

    root /home/mysite;
    index index.php;

    location ~ /.well-known {
        allow all;
    }

    location / {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        try_files $uri $uri/ /index.php?$query_string;
        set $path_info $fastcgi_path_info;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
    }
}

関連情報