我需要我的 Nginx 设置,当用户在浏览器中输入 example.com 时,将用户重定向到 www.example.com。原因是我们的 SEO 顾问说应该只有一个首选域,否则 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;
}
}
====更新====
我现在按照 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 输出是空白的,并且访问日志仍然提供永久重定向。
有趣的是,如果我注释掉第二个server
块,然后重新启动 Nginx,我最终会得到与我想要的相反的效果:www 重定向到非 www!我很惊讶会发生这种情况,因为 www.example.com 的 HTTPS 版本在此(第三)版配置中没有被提及。
答案1
这可能是因为您只在 HTTP 上重定向,而不是在 HTTPS 上重定向。您应该将 HTTPS 添加到重定向虚拟主机,并只保留其example.com
名称。
此外,你所做的与现在人们实际所做的正好相反——常见的做法是埋葬遗产万维网旧时代的前缀,只使用简单的域名,没有万维网。
答案2
这里的关键是您需要处理四个 URL - www 和非 www 域的 http 和 https 版本。您的问题是您正在将 www 和非 www 域的 http 版本转发到https://www域,但您的主服务器块正在监听这两个https://example.com和https://www.example.com
您需要做的就是创建一个单独的服务器块来转发https://example.com到https://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
}
标准示例
我有教程带有可下载的配置文件。下面是一个标准示例。
如果这对您不起作用,请使用 -k 选项卷曲每个变体(http 和 https、www 和非 www)以显示标题,并编辑您的问题以包含它们。
# 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 标头添加到响应中。这是一个很棒的诊断工具。您可以使用这样的语句来确定正在执行哪些块
添加标题 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;
}
}