Nginx no redirige no www a www

Nginx no redirige no www a www

Necesito mi configuración de Nginx para redirigir a los usuarios a www.example.com si escriben example.com en el navegador. La razón es que nuestro consultor SEO dijo que debería haber solo un dominio preferido; de lo contrario, Google lo verá como una duplicación de contenido. De todos modos . . .

El punto es que también tengo SSL de Letsencrypt configurado en el servidor, pero no puedo lograr la redirección de example.com a www.example.com (el servidor acepta ambas versiones). Aquí está la configuración que estoy usando:

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;
    }
}

==== Actualización ====

Ahora cambié mi configuración según lo recomendado por Tim (y siempre lo hago nginx -ty restart) en una de las respuestas a lo siguiente:

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;
    }
}

Aquí está el resultado curl -ky los registros de acceso para todas las variaciones (no compilé Nginx desde el código fuente porque espero una solución más simple y no quiero estropear el servidor):

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"

Observe la última sección, donde la salida de CURL está en blanco y los registros de acceso aún brindan una redirección permanente.

Curiosamente, si comento el segundo serverbloque y luego reinicio Nginx, termino con el efecto opuesto al que quería: ¡www redirige a no www! Me sorprende que esto esté sucediendo, porque la versión HTTPS de www.example.com no se menciona en ninguna parte de esta (tercera) versión de la configuración.

Respuesta1

Probablemente se deba a que está redirigiendo solo en HTTP, pero no en HTTPS. Debe agregar un HTTPS a su vhost de redireccionamiento y dejar allí solo example.comel nombre.

Además, lo que estáis haciendo es lo contrario de lo que la gente hace hoy en día: el enfoque habitual es enterrar el legado.wwwprefijos de la era antigua y utilizan sólo nombres de dominio simples, sin elwww.

Respuesta2

La clave aquí es que debe trabajar con cuatro URL: versiones http y https de los dominios www y no www. Su problema es que está reenviando la versión http del dominio www y no www alhttps://wwwdominio, pero su bloque de servidor principal está escuchando amboshttps://ejemplo.comyhttps://www.ejemplo.com

Todo lo que necesita hacer es crear un bloque de servidor separado para reenviar elhttps://ejemplo.comhaciahttps://www.ejemplo.comservidor. Debe incluir la configuración https en esto.

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
}

Ejemplo estándar

Tengoun tutorialcon archivos de configuración descargables. A continuación se muestra un ejemplo estándar.

Si esto no le funciona, enrolle cada variación (http y https, www y no www) con la opción -k para mostrar los encabezados y editar su pregunta para incluirlos.

# 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;
}

Resolución de problemas La mejor manera de diagnosticar problemas es:

  • utilice "curl -k" (mostrar encabezados) en cada una de las variantes del dominio, junto con el registro de acceso. Los códigos de estado http devueltos le indican lo que está pasando. 200 es la página, 301 es la redirección permanente, 302 es la redirección temporal
  • Asegúrese de que Nginx tenga el módulo headers_more, lo cual puede hacer medianteconstruyendo Nginx desde la fuente, lo cual es bastante fácil. Esto le permite agregar encabezados https a la respuesta. Esta es una gran herramienta de diagnóstico. Puede utilizar declaraciones como esta para determinar qué bloques se están ejecutando

add_header Z_DEBUG "ubicación_nombre_o_mensaje";

Respuesta3

Finalmente pude convencer a nuestra persona de SEO para que considerara el dominio que no es www como principal. La configuración que funcionó para redirigir www a no www fue la siguiente. Aunque mi intento de lograr lo contrario tenía una configuración similar, no estoy seguro de qué lo impedía.

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;
    }
}

información relacionada