2

a file within /etc/nginx/sites-enabled has the following

server {

  server_name production.domain.club cspiero.domain.club;
  root /home/deploy/domain/current/public;
[...]
   ssl_certificate /etc/letsencrypt/live/cspiero.domain.club/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/cspiero.domain.club/privkey.pem; # managed by Certbot
[...]
server {
    if ($host = production.domain.club) {
        return 301 https://$host$request_uri;
    }
  listen 80;
  listen [::]:80;
}
server {
    if ($host = cspiero.domain.club) {
        return 301 https://$host$request_uri;
    }
  listen 80;
  listen [::]:80;
}

while nginx -t passes, the actual behaviour of the server is that 3rd level domain production is being rendered as expected, whereas cspiero is not being routed to the same location, but being processed by the default configuration (the browser also receives an http response, thereby ignoring the certificate)

server {
       root /home/deploy/default;
        index index.html;
        server_name _;
        location / {
        try_files $uri $uri/ =404;
        }
}

Why is this happening? There is a desire to maintain the default configuration for all the other fishing expedition requests (rendering something very light and bland). What should be done in this context then?

2
  • 1
    Never use a 301 redirect until your site is working properly. Did you test this in a browser? If so your results are meaningless. A browser will cache a 301 response indefinitely.
    – symcbean
    Commented May 26 at 21:03
  • Yes, in fact, I posted here after testing in browser. The pointer on cached 301 responses is really useful. Also glad the error popped up as @Richard Smith answer helps iron out old junk inherited from certbot edits.
    – Jerome
    Commented May 28 at 6:40

1 Answer 1

2

You have three "default" server blocks, as there are three blocks without a server_name or using the bogus name _. See the documentation on the catch-all server.

So any request appearing on port 80 will be processed by the first of these server blocks. That's all requests irrespective of domain name.

There are many examples using the if ($host = pattern, but these are mostly from auto-generated edits by certbot because it's difficult to do it correctly.

The correct solution is to replace the if blocks with a server_name statement. In fact, you can combine two of them into a single server block.

Replace:

server {
    if ($host = production.domain.club) {
        return 301 https://$host$request_uri;
    }
  listen 80;
  listen [::]:80;
}
server {
    if ($host = cspiero.domain.club) {
        return 301 https://$host$request_uri;
    }
  listen 80;
  listen [::]:80;
}

With:

server {
    server_name production.domain.club cspiero.domain.club;
    return 301 https://$host$request_uri;
    listen 80;
    listen [::]:80;
}
2
  • another one of those certbot curveballs... Interestingly, that pattern exists elsewhere but seem to function. I will be scouring those to fix the syntax.
    – Jerome
    Commented May 26 at 7:42
  • 1
    The pattern works if done correctly. The if blocks should be within a single server block with a server_name and final return 4xx statement to handle the case where none of the if blocks match. Commented May 26 at 8:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .