Score:0

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

in flag

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!!

Score:2
us flag

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.

Michael Hampton avatar
cz flag
And `listen` directives do not include `ssl` .
Score:0
za flag

Nginx is sorting the file includes containing the virtual hosts indeed. Because that's more comfortable to use and to understand the logic of selecting the default one - and this would be the first vhost include file when sorted alphabetically.

In fact you're looking for the default option to listen directive, that is used to terminate all other sites not matching the server_name mentioned in your server {} blocks.

Add the default option to the listen directive of the virtual host that should terminate all the requests if none server_name matched.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.