7

I'm trying to accomplish three things:

  1. Map traffic, by subdomain, to one of several applications on different ports.
  2. If subdomain isn't recognized, redirect to www.
  3. Require HTTPS on all subdomains.

My nginx configuration so far is:

map $subdomain $subdomain_port {
  default    8000;
  www        8000;
  subdomain1 8001;
  subdomain2 8002;
  subdomain3 8003;
}

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

server {
    listen              443 ssl;
    server_name         ~^(?P<subdomain>.+?)\.mydomain\.com$;

    ssl_certificate     <cert>;
    ssl_certificate_key <key>;

    location / {
      # ... various proxy headers, then ...
      proxy_pass http://127.0.0.1:$subdomain_port;
      proxy_redirect off;
    }
}

This almost works (it accomplishes #1 and #3), but instead of redirecting foo.mydomain.com to www.mydomain.com, it just serves the www content without redirecting. I'm not sure how to redirect un-mapped subdomains without splitting the whole thing into separate server blocks, which I'd really rather not do.

Is there a way to redirect all subdomains not explicitly mentioned in the map to www?

Don McCurdy
  • 171
  • 1
  • 4
  • Side note: if you're using LetsEncrypt, part of what I'm asking here is unfortunately impossible. LetsEncrypt doesn't support wildcard certificates (as of 04/2016), so you can only redirect subdomains you have a certificate for: http://serverfault.com/questions/741182/redirect-all-subdomains-to-main-domain-with-https-without-a-wildcard-cert-nginx?rq=1 – Don McCurdy Apr 19 '16 at 02:06

3 Answers3

1

Just implement a default server. Here's mine

server {
  listen      80 default_server;
  server_name _;
  return 302 https://www.example.com;
}

You can do whatever action you want.

Tim
  • 31,888
  • 7
  • 52
  • 78
  • This looks like it would 444 all non-HTTPS traffic, regardless of subdomain. If so, this won't address #2 or #3 above. If not, could you explain what this does? – Don McCurdy Apr 18 '16 at 02:36
  • I changed the last line to a temporary redirect. You could also use a 301 permanent redirect, but I think 302 is better in this case, in case a subdomain is added later. I figured you just needed to know about the default_server directive and could work the rest out from there. – Tim Apr 18 '16 at 02:42
1

Just to say that on AWS, I needed to add an A record "*.staging.mydomain.com" in Route53 pointing to the same EC2 instance IP (like the record for "staging.mydomain.com")

Shadi
  • 121
  • 5
0

The following works for me...

  1. Let the default port be different from port for www.
  2. Let Nginx listen in the default port and redirect all traffic to www.

Here is the change in Nginx config to make it work...

map $subdomain $subdomain_port {
  default    8888;
  www        8000;
  subdomain1 8001;
  subdomain2 8002;
  subdomain3 8003;
}

server {
    listen 8888;
    server_name _;
    return 301 https://www.domainname.com/$request_uri;
}

# other configs remain the same

I used 8888 as the default port. Any unused port should work.

Pothi Kalimuthu
  • 6,117
  • 2
  • 26
  • 38