Organizing common configs in multiple server blocks

I’ve got a domain that largely got setup by certbot:

server {
    root /var/www/mydomain.com;
    index index.html;

    server_name mydomain.com www.mydomain.com;

    location / {
        try_files $uri $uri/ =404;
    }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mydomain.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
}

I now want to add sudomain.mydomain.com, but obviously want to keep the cert configs. What’s the best way for me to do this? As I understand, I can move

server {
    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mydomain.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
}

to a separate file (maybe mydomain.ssl.conf?) and use include, and create a new server block for the subdomain. Googling SUGGESTS (stupid AI) that I can do it all within one server block? But I can’t find actual code that does that.

Additionally, certbot setup

server {
    if ($host = www.mydomain.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = mydomain.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    listen [::]:80;

    server_name mydomain.com www.mydomain.com;
    return 404; # managed by Certbot
}

but I’m having trouble understanding it a bit. The host blocks at top set up a redirect, then it listens on 80 after? Or does the fact that it listens on 80 and for those domains always take effect, and if the hosts match, then redirect, else 404? I thought the order of the directives matters? And lastly, adding this subdomain, would I need to setup an if block for each subdomain?

EDIT: I tried adding

server {
    server_name personal.rohitsodhia.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
    }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/rohitsodhia.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/rohitsodhia.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
}

But I get an error for duplicate listens options, which makes sense that more than one server block can’t listen on the same port. But yah, not sure how to handle this. Googling for multiple subdomains says to use multiple server blocks, but I’m guessing there’s more to it than that?

1 Like
  • Your error occurred because you kept the ipv6only=on parameter on multiple server blocks. This parameter can only be used once per IP:port combination.

  • You can have multiple server blocks listening on the same port (443) as long as they have different server_name directives

  • You can do a HTTP redirect all in the same server block:

server {
    listen 80;
    listen [::]:80;
    
    server_name mydomain.com www.mydomain.com subdomain.mydomain.com;
    
    return 301 https://$host$request_uri;
}
3 Likes