1

I just changed my config from a regular to a wildcard certificate. Now my nginx is misbehaving.

# redirect http to https
server {
  listen      80 default_server;
  listen      [::]:80 default_server;
  return      301 https://$host$request_uri;
}

# redirect naked to www
server {
  listen      443 ssl http2;
  listen      [::]:443 ssl http2;
  server_name example.com;
  include     ssl.conf;
  return      301 https://www.$host$request_uri;
}

# serve subdomain www
server {
  listen      443 ssl http2;
  listen      [::]:443 ssl http2;
  server_name www.example.com;
  include     ssl.conf;
  # ...
}

# serve subdomain mmm
server {
  listen      443 ssl http2;
  listen      [::]:443 ssl http2;
  server_name mmm.example.com;
  include     ssl.conf;
  # ...
}

# ...etc.

The above works, but fails for non-existent subdomains (instead of returning 404). So if I try notexist.example.com it will redirect me to www.notexist.example.com and give me a certificate warning. If I click ok, it will redirect to www.www.notexist.example.com, and then www.www.www.notexist.example.com, etc.

What am I doing wrong?

lonix
  • 14,255
  • 23
  • 85
  • 176
  • You should add one extra server block at the end and mark it as default - it will catch all subdomains which are not already handled by any other server block. You do not need to set `server_name` for this default server block. – IVO GELOV May 29 '20 at 17:58
  • The second server block is wrong. The `$host` variable is set to the requested domain name, so the `return` statement just keeps adding another `www.` in front of it. Use: `return 301 https://www.$server_name$request_uri;`. – Richard Smith May 29 '20 at 18:34
  • @RichardSmith Thanks. I tried that but it redirects to the `www` subdomain. I think it strips the subdomain from `foo.example.com` (it only looks at `server_name`) and then matches the second server block, and then redirects to `www.example.com`. If I follow @IVOGELOV's idea of adding a "catch all" server block at the very bottom it seems to work though. – lonix May 30 '20 at 05:19
  • @IVOGELOV Thanks. That seems to work for me! If you add as an answer I'll close. – lonix May 30 '20 at 05:20

1 Answers1

1

Since you want to catch all non-existent subdomains you need an extra server block at the end, marked as default - like listen 443 ssl default_server; The server_name for this block does not matter - as long as it does not match any of the other server blocks (so you can simply use server_name _;)

Any domain that is not already handled by another server block will be handled by the default one - you can either redirect to your canonical domain or just return 404.

IVO GELOV
  • 13,496
  • 1
  • 17
  • 26
  • Do you mind taking a look at this [related question](https://stackoverflow.com/q/72600765/9971404), if you have a chance? – lonix Jun 13 '22 at 09:47