2

I have an nginx server running. I want it to redirect http://www.example.com to https://www.example.com, but not touch any other subdomains like http://foo.example.com.

For some reason, no matter what I add in the subdomain, it still gets rerouted. My webpage shows on www.example.com (as it should), but also on foo.example.com and example.com (as it shouldn't)

This is my example.com config file:

server {
  listen 80;
  server_name www.example.com;

  # For debug
  add_header X-debug-message "listen:80, server_name:www.example.com, redirect:https://$host$request_uri" always;

  # Riderect
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;
  server_name www.example.com;

  # For debug
  add_header X-debug-message "listen:443, server_name:www.example.com, redirected:https://$host$request_uri" always;

  # SSL
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
  root /var/www/example.com;

  # Redirect
  location / {
    proxy_pass http://192.168.1.224:80;
  }
}

Going to www.example.com shows me my webpage as expected. But going to foo.example.com also gives me my webpage - which it shouldn't. example.com also gives me the webpage.

Opening www.example.com in my browser, I see the following http header (as expected):

X-debug-message: DEBUG: listen:443, server_name:www.example.com, redirected:https://www.example.com/

Opening foo.example.com in my browser, I see the following http header (not as expected):

X-debug-message: DEBUG: listen:443, server_name:www.example.com, redirected:https://foo.example.com/

How can I make my nginx only redirect www.example.com ?

1

4 Answers 4

2
  1. Ensure that the dns record for foo.yourdomain.com is actually created with dns provider

  2. Create a second server block for the subdomain 'foo.example.com' otherwise all request to port 80 will be redirected to available server block, which in your case www.example.com - the server block should look like this:

         server {
            server_name foo.example.com;
            location / {
                 root path/to/foo/index.html;
                 index index.html index.htm;
                 proxy_http_version 1.1;
                 proxy_set_header Upgrade $http_upgrade;
                 proxy_set_header Connection 'upgrade';
                 proxy_set_header Host $host;
                 proxy_cache_bypass $http_upgrade;
                 try_files $uri $uri/ /index.html;
            }
    
          listen 443 ssl; # managed by Certbot
          ssl_certificate 
          /etc/letsencrypt/live/example.com/fullchain.pem; # n 
            managed by Certbot
          ssl_certificate_key 
          /etc/letsencrypt/live/nextoma.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
        }
    
  3. Add ssl certificate to the foo.example.com with the command:

    certbot --nginx -d foo.example.com
    
  4. Restart nginx and recheck foo.example.com again

Sign up to request clarification or add additional context in comments.

Comments

2

Thank you for all the comments!

For other readers, and future reference, this is now my enlightened understanding.

nginx treats the first entry in it's enabled-sites conf as a default route. Thus, the first entry

server {
    listen      80;
    server_name example.net www.example.net;
    ...
}

is in fact treated as

server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}

So, my mistake, was to add *.example.com -> MyIP to my DNS, and assuming nginx would just 404 all routes I didn't explicitly define. When in fact, it looks for a route that matches foo.example.com, and if it doesn't, routes it to the default route.

So, I now changed my DNS to explicitly handle all subdomains I want routed, and I list all of them explicitly in nginx.

Now - how I achieve my original plan - to just route *.example.com to my IP, and have nginx 404 all requests except the ones I excplicitly define - I still don't understand.

Explicitly routing all subdomains in the DNS is a bit less flexible, as I need to update the DNS and wait for the change to propagate if I want to test a new service internally. But, I guess that is fine for now.

1 Comment

Did you add a DNS rule to accept all subdomains (e.g., *.example.com) and configure Nginx to handle the subdomains, where any non-configured subdomains automatically redirect to a 404 page?
2

You need to make the first entry listen on 443 for HTTPS and server name _ and return 404.

server {
        listen 443 ssl;
        server_name _;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        ssl_certificate /etc/nginx/certs/nginx-selfsigned.crt;
        ssl_certificate_key /etc/nginx/certs/nginx-selfsigned.key;

        location / {
                return 404;
        }
}

By having the typical HTTP to HTTPS redirect in the file (I have it as the last entry):

server {
        listen 80 default_server;
        server_name _;
        return 301 https://$host$request_uri;
}

Then all HTTP requests get converted to the HTTPS counterparts. Then, if you request a subdomain that has not been configured in the NGINX configuration file, it will default to the first entry which returns a 404. All other configured subdomains, and the root domain, if you have that as an entry, will resolve correctly.

Also you can keep your wildcard DNS, which is more practical than having to add each subdomain as an entry, as you point out in your answer.

Comments

1

To route all the subdomains but the specified ones to 404 you can use:

   server {
        listen 443 ssl http2;
        server_name *.domain.com;
        
        location / {
                return 404;
        }
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.