www domain incorrectly redirects to subdomain

I have two sites on nginx - my primary domain and a wordpress blog subdomain. When I visit `https://www.mysite.com`, I am redirected to `https://blog.mysite.com`. I'm sure there is something wrong with my server blocks, but I'm very new to nginx. Google hasn't been too helpful thus far, though I did add a `default_server` config from looking at a post on StackOverflow.

default_server.conf

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;

return 444;
}

mysite.conf

server
{
server_name mysite.com;

location /
{
root /home/ubuntu/mysite/build/;
try_files $uri /index.html;
}

location /api/
{
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_pass http://localhost:5000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server
{
server_name mysite.com;
access_log /var/log/nginx/insecure-redirect.access.log;
error_log /var/log/nginx/insecure-redirect.error.log;
location /
{
return 301 https://$host$request_uri;
}

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server
{
if ($host = www.mysite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot

if ($host = mysite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot

listen 80;
server_name mysite.com www.mysite.com;
return 404; # managed by Certbot
}

blog.conf

server {
root /var/www/blog;
server_name blog.mysite.com;
access_log /var/log/nginx/wp_client_access.log;
error_log /var/log/nginx/wp_client_error.log;

location / {
index index.php index.html;
try_files $uri $uri/ /index.php?$args;
}

# Specify a charset
charset utf-8;
# GZIP
gzip off;

# Add trailing slash to */wp-admin requests.
rewrite /wp-admin$ $scheme://$host$uri/ permanent;

# Prevents hidden files (beginning with a period) from being served
location ~ /\. {
access_log off;
log_not_found off;
deny all;
}

###########
# SEND EXPIRES HEADERS AND TURN OFF 404 LOGGING
###########

location ~* ^.+.(xml|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}

# Pass all .php files onto a php-fpm or php-cgi server
location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_read_timeout 3600s;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 128k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
#fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
}

# ROBOTS

location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

# RESTRICTIONS
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
if ($host = blog.mysite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot

listen 80;
server_name blog.mysite.com;
return 404; # managed by Certbot
}

Redirect analyzer
>>> https://www.mysite.com

> --------------------------------------------
> 301 Moved Permanently
> --------------------------------------------

Status: 301 Moved Permanently
Code: 301
Server: nginx
Date: Sun, 13 Mar 2022 22:04:30 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
X-Redirect-By: WordPress
Location: https://blog.mysite.com/

>>> https://blog.mysite.com/

> --------------------------------------------
> 200 OK
> --------------------------------------------

Status: 200 OK
Code: 200
Server: nginx
Date: Sun, 13 Mar 2022 22:04:31 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Link: ; rel=shortlink

2 thoughts on “www domain incorrectly redirects to subdomain”

  1. I’d consider myself with basic knowledge of NGINX, but from having a look, your configs look a little confusing, using the if statements etc.

    My default\_server conf looks like this (note, I use nginx 1.21.6):

    server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 default_server;
    listen [::]:443 default_server;
    ssl_reject_handshake on;

    return 444;
    }

    ssl\_reject\_handshake (available in nginx 1.19.4+) makes visiting https://SERVERIP inaccessible without throwing SSL errors, while 444 instructs NGINX to send no data via http or https via direct IP access.

    My main conf looks a little something like this

    server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name domain.com;

    ssl_certificate /etc/nginx/ssl/domain.com.crt;
    ssl_certificate_key /etc/nginx/ssl/domain.com.key;


    }

    To redirect www requests to non-www I include

    server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name http://www.domain.com;

    ssl_certificate /etc/nginx/ssl/domain.com.crt;
    ssl_certificate_key /etc/nginx/ssl/domain.com.key;

    return 301 https://domain.com$request_uri;
    }

    To redirect http to https I then include

    server {
    listen 80;
    listen [::]:80;
    server_name domain.com http://www.domain.com;

    return 301 https://domain.com$request_uri;
    }

    This is all in my domain.com.conf.All subdomains have a similar conf structure, although, I don’t redirect www, it would use the same kind of block.

    You also have two location / { }, one with root and try files, one with perm redirect, for the same block.

    Edits: formatting.

    Reply
  2. In `mysite.conf`, you have two server contexts listening on `443 ssl`, both configured with the same `server_name`. You need to remove one of the server contexts, and in the context you decide to keep, you should change the `server_name` to:

    server_name mysite.com http://www.mysite.com;

    Right now, no server context has a `server_name` set for http://www.mysite.com, so it defaults to the first loaded server context on that ip:port. You can see details on how nginx selects the server context here: https://nginx.org/en/docs/http/server_names.html

    Reply

Leave a Comment