Nginx Server Blocks: https, non-www, & non-ssl subdomain

301-redirectnginxredirectssl

Here's my scenario:

Two sites:

  1. https://example.com
  2. http://dev.example.com

Site 1 has a ssl certificate.
Site 2 does not.
(In other words, I don't have a wildcard ssl certificate.)

Via Nginx I'm trying to establish the necessary www and HTTP redirects.

Goal for site 1 is to direct

example.com, www.example.com and https://www.example.com

…to

https://example.com

Goal for site 2 is to simply let http://dev.example.com direct to itself.

What I've tried for goal 1

# SSL Redirect
server {
  listen 80;
  server_name example.com;
  return 301 https://filethemes.com$request.com;
}

# WWW Redirect
server {
  listen 80;
  listen 443 ssl;
  server_name www.example.com
  ssl_certificate <my-path-here>.crt;
  ssl_certificate_key <my-path-here>.key;
  return 301 https://example.com$request_uri
}

# Site's Primary Server Block
server {
  listen 443 ssl;
  root /var/www/example.com;
  index index.html;
  server_name example.com;
  ssl_certificate <my-path-here>.crt;
  ssl_certificate_key <my-path-here>.key;  
}

With the above code, example.com goes to 'https://example.com' but that's it. The www redirect is not working. Any ideas as to why?

Also, with a simple server block for site 2 (the subdomain dev.example.com) it redirects to https://example.com. So it seems that I'm inadvertently redirecting my subdomain to the main domain. Ideas?

I know there are already a slew of Nginx questions and answers out there but I couldn't find any solutions that helped me to get things working as desired.

For such a seemingly simple goal its surprising how challenging this is proving.

I'm grateful for any insight folks can offer.

PS: Yes, my ssl certificate supports www and non-www.

UPDATE:
The subdomain issue (site 2 above) is no longer an issue… I failed to re-linked the appropriate file from sites-available to sites-enabled.

Still having the same issues with site 1 not redirecting from www – naked, with http and with https.

SOLVED(!)
The problem? No DNS CNAME entry (face palm!).
Many thanks to @BE77Y for helping me find the problem. Also, in case it helps others, here's my current and fully working nginx config, consisting of two server blocks, with one that takes care of all the redirecting to the non-www and https (and uses the NGINX best practices of no re-writes and no if statements):

# MAIN SERVER BLOCK
server {
  listen 443 ssl;
  root /var/www/example.com;
  index index.html;
  server_name example.com;
  ssl_certificate <my-path-here>.crt;
  ssl_certificate_key <my-path-here>.key;  
}

# REDIRECTS (send everything to non-www https)
server {
  listen 80;
  listen 443;
  server_name www.example.com example.com;
  ssl_certificate <my-path-here>.crt;
  ssl_certificate_key <my-path-here>.key;
  return 301 https://example.com$request_uri;
}

Gotchas (for others who don't usually work with servers):

  • clear cache (or open and close incognito windows) between tests
  • make sure you have a CNAME DNS entry (www example.com.)!

Best Answer

You're nearly there from what I can see; I would just configure things slightly differently (based on your described requirements), just to simplify things a bit. One thing I'd note for clarification is that you don't seem to have included a dev.example.com segment in your configuration?

Regardless, here's how I'd improve your current configuration:

# Primary block including SSL redirect
server {
  listen 80;
  listen 443 ssl;
  server_name example.com;

  root /var/www/example.com;
  index index.html;

  ssl_certificate <my-path-here>.crt;
  ssl_certificate_key <my-path-here>.key;

  if ( $scheme = http ){
            rewrite ^ https://$server_name$request_uri? permanent;
            }
 }

# WWW Redirect
server {
  listen 80;
  listen 443 ssl;
  server_name www.example.com
  ssl_certificate <my-path-here>.crt;
  ssl_certificate_key <my-path-here>.key;
  rewrite ^ https://example.com$request_uri? permanent;
}

To clarify the above: this is a 'cleaner' way of doing things; if someone requests your site at http://example.com, they will be redirected to https://example.com via the if statement, and likewise they will correctly be served the site if they request it via https (which would be an issue with separate statements as you had before). If they try to access the site via http://www.example.com it will be redirected, or via https://www.example.com it will correctly negotiate SSL but still be redirected as above.

As I've noted, you haven't included any dev.example.com related segments in your config file - I assume this is because you have these working already, but if not please feel free to comment on this and I'll be happy to assist in including them with the above.

Hope that helps!

Related Topic