I have the following setup:

  • Nginx with two virtual hosts
  • two subdomains: sub1.domain.com and sub2.domain.com

sub1.domain.com is working fine. If I enter sub2.domain.com the browser returns a 403. I've set the directories configured for both domains to be owned by www-data (chown -R www-data:www-data /var/www/).

A look at the error logs reveals that /var/log/nginx/sub2.domain.com/error.log is empty whereas /var/log/nginx/sub1.domain.com/error.log contains

2018/03/09 11:29:00 [error] 19024#0: *13009 directory index of "/var/www/sub1.domain.com" is forbidden, client: ip, server: sub1.domain.com, request: "GET / HTTP/1.1", host: "my-host"

Does anyone know why the server includes sub1.domain.com even if I've entered sub2.domain.com in the browser?!

I think the problem might be, that sub2.domain.com always seems to execute the config of sub1.domain.com (which is the default_server). According to the nginx docs:

If its value does not match any server name, or the request does not contain this header field at all, then nginx will route the request to the default server for this port.

Nginx config for sub1.domain.com

server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        root /var/www/sub1.domain.com;
        index index.php index.html index.htm;

        server_name sub1.domain.com;

        access_log      /var/log/nginx/sub1.domain.com/access.log;
        error_log       /var/log/nginx/sub1.domain.com/error.log;

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

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        location ~ /\.ht {
                deny all;

        # pass the PHP scripts to FastCGI server listening on
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param AUTH_SECRET "my-secret";
                include fastcgi_params;


Nginx config for sub2.domain.com

upstream backend{

server {
        listen 80;
        listen [::]:80;

        access_log      /var/log/nginx/sub2.domain.com/access.log;
        error_log       /var/log/nginx/sub2.domain.com/error.log;

        root    /var/www/sub2.domain.com;

        server_name sub2.domain.com;

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        location ~ /\.ht {
                deny all;

        # route /api requests to backend
        location /api/v1 {
                proxy_pass              http://backend;
                proxy_http_version      1.1;
                proxy_redirect          off;
                proxy_set_header Upgrade        $http_upgrade;
                proxy_set_header Connection     "upgrade";
                proxy_set_header Host           $http_host;
                proxy_set_header X-Scheme       $scheme;
                proxy_set_header X-Real-IP      $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-NginX-Proxy  true;

        location / {
                try_files $uri $uri/ /index.html =404;

I have followed the tutorial here https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-server-blocks-virtual-hosts-on-ubuntu-14-04-lts and set up the sym links. So /etc/nginx/sites-available contains the config and /etc/nginx/sites-enabled contains the sym links on those configs.

Also note, that sub1.domain.com serves a php backend whereas sub2.domain.com should serve some static content (single page application) and direct the api requests to a Node.js backend.


nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

My nginx.conf file contains include /etc/nginx/sites-enabled/*;. So the configurations, that I've posted above, should be included. At least nginx -t throws an error if one of the configs has an error.

Edit 2: tl;dr (summary of comments): the DNS was misconfigured. Setting the correct A record for both subdomains solved the problem. The nginx config is working as expected.

  • Use nginx -T to display the configuration that nginx sees. But it looks like the second configuration file is not being read. – Richard Smith Mar 9 '18 at 12:54
  • I've updated my post with the output of nginx -t. – Philipp Mar 9 '18 at 13:09
  • Uppercase T prints out the entire configuration and will identify if your second server block is included. – Richard Smith Mar 9 '18 at 13:17
  • Ah I didn'tt know this. Thought it was a typo. :) Unfortunately the installed nginx version does not support this flag. Right now I'm not sure if we can update the system to a later version. I'll check this. – Philipp Mar 9 '18 at 16:54
  • Looking again at the error message, the fragment host: "my-host" specifies which server_name was being requested. Does this match the server_name of the second server block? – Richard Smith Mar 9 '18 at 17:21

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.