Little Brain
Little Brain

Reputation: 2855

Redirect from www to non-www not working in Nginx with ssl on Ubuntu 16.04

I have a Meteor 1.6 site on a DigitalOcean Ubuntu 16.04 droplet, deployed using Phusion Passenger and Nginx.

I've set up ssl on my server.

http://mysite redirects to https://mysite and the site works fine.

However http://www.mysite redirects to https://mysite and all that shows is the default Nginx page "Welcome to nginx!".

I've followed tutorials and tried things from other forum posts, and I can't find what's wrong with my setup.

DNS records from the DigitalOcean control panel:

A   www.mysite.org directs to xxx.xx.xx.xx 3600
A   mysite.org directs to xxx.xx.xx.xx 1800

I then configured ssl using Certbot and LetsEncrypt following this tutorial: https://www.digitalocean.com/community/tutorials/how-to-set-up-let-s-encrypt-with-nginx-server-blocks-on-ubuntu-16-04

And I added a server block to redirect www to the plain domain by following this tutorial: https://www.digitalocean.com/community/tutorials/how-to-redirect-www-to-non-www-with-nginx-on-ubuntu-14-04

Here's my nginx config:

sudo nano /etc/nginx/sites-enabled/mysite.conf

server {
    server_name mysite.org www.mysite.org;

    ...Meteor app config

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

}

# added by me
server {
    server_name www.mysite.org;
    return 301 $scheme://mysite.org$request_uri;
}

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

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

I tried adding this to my server redirect block but it made no difference:

listen 80;
listen 443 ssl;

Any ideas how I can get the www.mysite -> mysite redirect to work? Thank you!

Update: I tried flaixman's answer on a different app, a Django app on a different droplet, and it worked. But I still can't get redirect to work on my Meteor app. Both sites have A and CNAME records configured the same way.

Here's my Meteor config based on flaixman's answer:

server {
    listen 80;
    server_name example.org www.example.org;
    return 301 https://example.org$request_uri;
}

server {
    listen 443 ssl http2; #https of www*, 301 to right domain.
    server_name www.example.org;

    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.org/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

    return 301 https://example.org$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.org;

    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.org/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

    # Tell Nginx and Passenger where your app's 'public' directory is
    root /var/www/example/bundle/public;

    # Turn on Passenger
    passenger_enabled on;
    # Tell Passenger that your app is a Meteor app

    passenger_app_type node;
    passenger_startup_file main.js;

    # Tell your app where MongoDB is
    passenger_env_var MONGO_URL mongodb://localhost:27017/example;
    passenger_env_var MONGO_OPLOG_URL mongodb://localhost:27017/local;

    # Tell your app what its root URL is
    passenger_env_var ROOT_URL http://example.org;
}

In my nginx error log /var/log/nginx/error.log, I see this message:

2019/01/17 17:30:52 [warn] 7786#7786: conflicting server name "www.example.org" on 0.0.0.0:80, ignored
2019/01/17 17:30:52 [warn] 7786#7786: conflicting server name "www.example.org" on 0.0.0.0:443, ignored
2019/01/17 17:30:52 [warn] 7789#7789: conflicting server name "www.example.org" on 0.0.0.0:80, ignored
2019/01/17 17:30:52 [warn] 7789#7789: conflicting server name "www.example.org" on 0.0.0.0:443, ignored

I would expect this to mean that I have a duplicate listen directive in my conf file, but I can't see any? I've checked with ls -a and there is not a second copy of the conf file in the folder.

The error may be connected with the failure of redirect, but I can't see what is causing the error?

Edit again: I finally found the duplicate listen directives, in /etc/nginx/sites-available/default. Not sure if Certbot inserted them or if I put them there myself way back when I set up the server...anyway, commenting them out seems to have fixed the problem. It's possible that something in the Phusion Passenger instructions for setting up server blocks, conflicts with the LetsEncrypt instructions? Anyway yay for nginx error log!

Upvotes: 3

Views: 7694

Answers (3)

Choop Miklon
Choop Miklon

Reputation: 53

I know a lot of time has passed. But I had this exact same issue, and I dare to say that, in my case, the problem was at the A registry, not in the Nginx sites-available file. Ionos A registry

I use Ionos for my hosting, language is spanish, but it's still easy to understand, I'll explain:

  1. The type of registry must be A for Ipv4 addresses, if it's IPv6, it should be a type AAAA
  2. Here's the important part related to the question, if you want any subdomain, i.e. "www.mydomain.com" or "en.mydomain.com", (including non-www "mydomain.com") to be directed to your domain, you should fill this space with an "@" symbol; If, in change, you want every subdomain except empty (mydomain.com), you should fill with an "*" symbol.
  3. Fill the "points to" space with your IP address
  4. And finally, for the TTL I would recommend to put the lowest value possible only during test and development, in production, I'd prefer to leave it at 1 hour.

Late to the party, hope it helps someone though!!

Upvotes: 0

flaixman
flaixman

Reputation: 732

Stackoverflow told me that mysite was not a right domain to use as example, so I changed everything to "example" instead of "mysite"

I suppose that what you want is everything to redirect to https example.org, don't you? This is what your code should look like:

Requests coming from http,it doesn't really matter if the host comes as www* or without www. Everything will be redirected to the host without www, and through https

server {
    listen 80; 
    server_name example.org www.example.org;
    return 301 https://example.org$request_uri;
}

If the host is www* and comes through https, redirect to https without www. By the way, here you will need to use a certificate for www.example.org, because without certificate the connection is non secured.

server {
    listen 443 ssl http2; #https of www*, 301 to right domain.
    server_name www.example.org;
    #are you sure those 2 paths are right? with the final $.
    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem$
    ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.p$
    include /etc/letsencrypt/options-ssl-nginx.conf; 
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 

    return 301 https://example.org$request_uri;
}

And finally, if it comes with the right scheme, and with the right host, do whatever you want.

server {
    listen 443 ssl http2;
    server_name example.org;

    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem$
    ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.p$
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    #do what you want to do here.
}

If you have any doubt or anything I have missed on your explanation, just comment it and I'll fix it as fast as I can.

Upvotes: 6

sd5869
sd5869

Reputation: 1

Check your DNS settings. You must have CNAME or A entry "www".

www A   ip

or

www CNAME   domain.com

also you need to add listen param in your block

listen 443 ssl http2;

EDIT: Based on comments.

Add this to top in your conf

server {
  server_name mysite.org www.mysite.org;
  if ($server_name ~* \.mysite.org$) {
    return 301 $scheme://mysite.org$request_uri;
  }
  ...Meteor app config    
}

Upvotes: 0

Related Questions