Nginx redirect www domain to non-www

I want www.example.app to go to example.app for SEO, and I followed several tutorials and problem solutions but can't seem to get it working.

I added a separate server block that redirects to the non-www domain and restarted nginx several times, also accessing my site from an incognito window.

Here is my /etc/nginx/sites-available/default configuration file.

Any help would be appreciated!

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


    root /var/www/html/;

    index index.php index.html index.htm index.nginx-debian.html;

    server_name exampe.app;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~*  \.(jpg|jpeg|png|gif|ico|css|js)$ {
            expires 365d;
        }

        location ~*  \.(pdf)$ {
            expires 30d;
        }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    }

    location ~ /\.ht {
     deny all;
    }

    error_page 404 /customerror_404.html;
    location = /customerror_404.html {
        root /usr/shar/nginx/html;
        internal;
    }

}
server {
    root /var/www/html/;
    index index.php index.html index.htm index.nginx-debian.html;
    server_name example.app; # managed by Certbot


    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }


    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.app/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.app/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 = example.app) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80 ;
    listen [::]:80 ;
    server_name example.app;
    return 404; # managed by Certbot

}

9 Replies

@Ed_ --

Wow. This seems like an awful lot of work for something that only takes two lines of configuration in apache2(1):

<VirtualHost _default_:80>

  # Server name
  #
  ServerName  example.app
  ServerAlias www.example.app
...
</VirtualHost>

and two DNS A/AAAA records!     ;-)

Perhaps you forgot the DNS part?

-- sw

@stevewi

You can do the same in Nginx with 1 line :-D

server_name example.app www.example.app

However both this and your Apache solution does not trigger a redirect from one to the other (unless code running within that app does this, such as Wordpress.)

In my nginx config, I have 2 server blocks, one answering on www.example.app and one on example.app.

Whichever one I want to redirect (I redirect the www version to the non-www) simply does

return 301 https://example.app

The other one actually serves the app.

In my Apache days, I used a rewrite rule with a condition that the hostname matches www.example.com and performs a 301 redirect, but I do find the nginx way far simpler.

I also have a global server block that listens on port 80 (any hostname) and redirects to the HTTPS version of the same hostname.

@Ed_

It’s a bit tricky to really see your config. Please can you edit your post and surround the code/file snippets in three “back tick” characters before and after each snippet.

Also if you post actual domain names, we can look at things like DNS to help guide you. Assuming you’re eventually going to want visitors to your website, your domain and IP will be public information :-)

@andysh --

You write:

However both this and your Apache solution does not trigger a redirect from one to the other (unless code running within that app does this, such as Wordpress.)

You're right. If you set up the DNS A/AAAA records:

Hostname        IP Address      TTL 
example.app     <your_IP_addr>  Default
www             <your_IP_addr>  Default

it saves two things:

  • the configuration required for the redirect; and
  • the server from having to issue the redirect (another http protocol exchange).

Both example.app and www.example.app resolve to <your_IP_addr> and the web server sorts out the request URL (using the VirtualHost configuration).

-- sw

it saves two things:

the configuration required for the redirect; and
the server from having to issue the redirect (another http protocol exchange).

From an SEO-perspective, the same piece of content should have a unique URL. Not serving a redirect gives that same piece of content 2 URLs (a www and non-www one.) Factor in HTTP/HTTPS, and you could have 4 different URLs for the same piece. 301 redirects solve this problem, ensuring however a user formats the URL, they arrive at the same, unique URL.

Also if the user had previously visited your site, the 301 will have been cached by their browser, so a further visit by them won’t trigger an additional request to your site.

@andysh & @stevewi - Thanks a lot! I appreciate your help and have added the code blocks so hopefully, it's a bit more readable.

@stevewi - Regarding the DNS records, I have the DNS A/AAAA records for both example.app & www already set up.

@andysh - you mentioned that:

In my nginx config, I have 2 server blocks, one answering on www.example.app and one on example.app.

Whichever one I want to redirect (I redirect the www version to the non-www) simply does return 301 https://example.app

I understand what you're saying, but isn't that the same as my current configuration file?

In the first server block, I serve the www.example.app by also re-directing it, while in the other server blocks I serve the non-www example.app .

Thank you both again for your help!

@Ed_

It does look similar yes, but I struggled to see that with the formatting!

You’ve got a few bits here; can you clarify what happens in each of these cases so we can narrow down where the problem is likely to be?

I’m assuming based on your config each of these should redirect to (or leave you at) https://example.app?

Also if you are able to post a real domain for us to look at, please do so, it makes it much easier to try and work out what’s going on when we can see it happening. Instead we can only guess and surmise or have to ask “what does this do”…!

@andysh

Yeah sure.

The http gets always redirected to https, while the www and the non-www remain the same for some weird reason.

I would like the www to be redirected to the non-www domain.

So if you insert:
[http://www.example.app]
It will get redirected to: [https://www.example.app], not to [https://example.app] .

The domain for the website is https://fakebusters.app - hopefully this can help!

@Ed_

Thanks, ok strange thing is that there isn’t actually a server block for https://www.fakebusters.app.

Your first server block is for www but is missing the listen directive, so it will listen on port 80 by default.

However the site is answering on this address, so there must be a config for it somewhere. Also the HTTP site for www should match the first server block, but it isn’t as it isn’t redirecting.

Are there any other config files in /etc/nginx/sites-enabled?

@andysh

No that is the only configuration file in /etc/nginx/sites-enabled!
Would it be possible that the website is following another configuration? And if so, how do I locate it?

Update: When I run nginx -t to locate the configuration file, this is what I get.

nginx: [warn] conflicting server name "www.fakebusters.app" on 0.0.0.0:80, ignored
nginx: [warn] conflicting server name "fakebusters.app" on 0.0.0.0:80, ignored
nginx: [warn] conflicting server name "fakebusters.app" on [::]:80, ignored
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

But then again, the only server blocks included by that file is what I previously posted :( .

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct