Nginx giving precedence to subdomains based in alphabetical order of config files

TLDR: Nginx is giving precedence to subdomains in alphabetical order of the config files, and I want to know a way to prevent this from happening. This is similar to this question, but I am more interested in improving my system.

I (had) two sections on my server: One for a static website, and one for my dokuwiki instance. I wanted dokuwiki to load when someone went to example.com, and the static website to load when someone went to static.example.com. Finally, I wanted wiki.example.com to always point to dokuwiki, in case the default changed.

To accomplish this, I had two files in /etc/nginx/sites-available.

dokuwiki (This is just a common dokuwiki config with certbot run on it)

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


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


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

    listen               80;
    listen                   [::]:80;
    server_name          wiki.example.com example.com www.example.com;
    return 301 https://$server_name$request_uri;
}
 
server {
    listen [::]:443 ssl;
    listen 443 ssl;
 
    server_name example.com www.example.com wiki.example.com;
 
    # Maximum file upload size is 4MB - change accordingly if needed
    client_max_body_size 4M;
    client_body_buffer_size 128k;
 
    root /dokuwiki/dokuwiki-2020-07-29;
    index doku.php;
 
    #Remember to comment the below out when you're installing, and uncomment it when done.
    location ~ /(conf/|bin/|inc/|install.php) { deny all; }
 
    #Support for X-Accel-Redirect
    location ~ ^/data/ { internal ; }
 
    location ~ ^/lib.*\.(js|css|gif|png|ico|jpg|jpeg)$ {
        expires 365d;
    }
 
    location / { try_files $uri $uri/ @dokuwiki; }
 
    location @dokuwiki {
        # rewrites "doku.php/" out of the URLs if you set the userwrite setting to .htaccess in dokuwiki config page
        rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last;
        rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last;
        rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last;
        rewrite ^/(.*) /doku.php?id=$1&$args last;
    }
 
    location ~ \.php$ {
        try_files $uri $uri/ /doku.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param REDIRECT_STATUS 200;
        fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
        # fastcgi_pass unix:/var/run/php5-fpm.sock; #old php version
    }
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
}

static

server {
    root /var/www/example;
    index index.html index.htm index.nginx-debian.html;
    server_name static.example.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/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.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
}

This system worked exactly as I expected it to. However, I then added commafeed to my server. My goal was to access commafeed via rss.example.com. Commafeed runs on port 8082, so I did a proxy_pass to example.com/8082 in this file

commafeed

server {
    listen 443;
    listen [::]:443;
    
    root /var/www/commafeed;
    index index.html index.htm index.nginx-debian.html;
    server_name rss.example.com www.rss.example.com;
    location / {
        proxy_pass http://example.com:8082/;
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

When I did this, I got a reset connection on my browser for all example.com domains, and this error message logged

example:/etc/nginx/sites-available# tail -f /var/log/nginx/error.log -n 0
2021/09/28 03:10:36 [error] 32479#32479: *2317 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: <my ipv6 address>, server: [::]:443
2021/09/28 03:10:36 [error] 32479#32479: *2318 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: <my ipv6 address>, server: [::]:443

However, when I renamed the file to "zcommafeed", everything worked as intended. That is, all of the old subdomains worked as they did before, as well as rss.example.com pointing to commafeed.

Now, while this works, this seems to imply that there's a better way of doing this that doesn't involve paying attention to the alphabetical order of files. I am new to NGINX, so I would really appreciate the help!!


The error message clearly says that the configuration is missing a TLS certificate for rss.example.com. Create a proper certificate / key pair for rss.example.com and www.rss.example.com, then the configuration will work properly.