2

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!

Little Brain
  • 2,647
  • 1
  • 30
  • 54

3 Answers3

5

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.

flaixman
  • 702
  • 6
  • 14
  • 1
    Thank you for the very detailed answer. Unfortunately it did not work; www.mysite.org still shows the Nginx page. I copied your three server blocks and replaced 'example' with 'mydomainname', and I copied my certificate info from the existing conf file. Otherwise the code is exactly as you wrote above. The https seems fine in both URLs, but the redirect from www to plain domain is not working. – Little Brain Jan 14 '19 at 17:09
  • I have tried your answer on a different app on a different droplet and it worked, but I can't figure out why it doesn't work on my original (Meteor) app, and there is an error message in nginx but I can't see why! I've added details to the end of my question, if you have any ideas? – Little Brain Jan 17 '19 at 17:47
  • Do you have any other server block? I mean, in the whole /nginx/sites-enabled , you may have 2 blocks that listen to 80 with the sae server name, so it conflitcts on where to go. See if you have any hidden file or temp file in there that may double your configuration – flaixman Jan 18 '19 at 07:55
  • https://stackoverflow.com/questions/11426087/nginx-error-conflicting-server-name-ignored – flaixman Jan 18 '19 at 07:55
  • The only way my answer can conflict with server_name and ip is because there is another server block that listens exactly that, and as I see in the error, it conflitcs it all (so there is a configuration doubled for www and non www example, to 80 and 443 ports.). – flaixman Jan 18 '19 at 07:56
  • I've hunted through again and I've finally found some server blocks in /etc/nginx/sites-available/default that listen for the same server as that in my config file. Maybe Certbot created them? Anyway, commenting them out seems to have solved the problem, thank you so much for your help. – Little Brain Jan 19 '19 at 19:29
0

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    
}
sd5869
  • 1
  • 2
  • See the DNS settings in my question: I think I have the correct A record already. I already tried adding 'listen' to the block, as I stated in the question. I just tried adding 'http2' as you suggest, but it made no difference. – Little Brain Jan 09 '19 at 17:11
  • Thanks, I have tried adding that code to my config but it did not make any difference. – Little Brain Jan 14 '19 at 18:56
0

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!!