Basic Authentication in subfolders with nginx on Synology

I am using nginx as default webserver on my Synology. Here is how to configure a login/password prompt on a subfolder of the WebStation.

Click to Read More

First, open a SSH console on your Synology and enter the root (See here)

Notice that you cannot change the config file of nginx (/etc/nginx/nginx.conf). Even if you do so, your changes will be removed automatically. But in the config file of nginx, for the server listening on the port of your WebStation (port 80 by default), you can see it is loading extra config named www.*.conf under the folder /usr/syno/share/nginx/conf.d/

include /usr/syno/share/nginx/conf.d/www.*.conf;

So, go to that folder : cd /usr/syno/share/nginx/conf.d

There, create a password file with your login and password

Type : htpasswd -c -b .htpasswd YourLogin YourPassword

the parameter -c is to create the file. Only use it if the file does not yet exist otherwise you will clean its current content!!

Look at the content if the file: cat .htpasswd

It should be similar to this: 

YourLogin:$apr3$hUZ87.Mo$WUHtZHjtPWbBCD4jezDh72

Now, create and edit a file name like : www.protected.conf (Ex.: using vi)

Assuming that you want to protect a subfolder You/Sub/Folder existing in the root of your WebStation, you should theoretically this into www.protected.conf :

location /Your/Sub/Folder {
auth_basic “Any Prompt Message You Want”;
auth_basic_user_file /usr/syno/share/nginx/conf.d/.htpasswd;
}

Next, you have to restart nginx with the command : nginx -s reload

Or even better to be 100% sure: synoservicecfg –restart nginx

 

But for some reason, this is not working on Synology (at least on mine ?!). It seems that the block location does not work without a modifier like = or ~

It searched for hours why it was not working, without answer. 

For example, I tested first that the following webpage was working fine on my NAS: http://MyNas/SubFolder/index.php

Next, I edited the www.protected.conf with the following block before restarting nginx, deleting the cache ofh my browser and restarting my browser (THIS IS MANDATORY each time one changes the location):

location /SubFolder/index.php {
return 301 https://www.google.be/search;
}

But opening http://MyNas/SubFolder/index.php didn’t return me to Google.

Next, I tried with :

location = /SubFolder/index.php {
return 301 https://www.google.be/search;
}

And this was working! So, I thought that the path used as location was possibly was incorrect. To see the path capture as location I tried next with 

location ~ (/SubFolder/index.php) {
return 301 http://Fake$1;
}

Opening now http://MyNas/SubFolder/index.php, I got the (unvailable) page  http://Fake/SubFolder/index.php

So, the path /SubFolder/index.php was definitively correct. 

I think that my directive is included before another one which overwrite it. Possibly this one, found in /etc/nginx.nginx.conf:

location / {
rewrite ^ / redirect;
}

So, I have no choice but use the modifier = (exact match) or ~ (matching a regular expression). Unfortunately, doing so, another problem arise… the php pages are not reachable anymore :(

If you look at the log file of nginx: cat /var/log/nginx/error.log

You see:

2019/11/30 21:22:12 [error] 25657#25657: *50 open() “/etc/nginx/html/SubFolder/index.php” failed (2: No such file or directory), client: 192.168.0.1, server: _, request: “GET /SubFolder/index.php HTTP/1.1”, host: “MyNas”

This is because nginx is using its default root folder /etc/nginx/html/ instead of inheriting the one define for the WebStation.

The solution is to simply specify the root in the location block : root /var/services/web;

But now, instead of being executed, the php script is downloaded.. Harg !

The following location works, by redefining the execution of the php page:

location = /SubFolder/index.php {
  root /var/services/web;

  try_files $uri /index.php =404;
  fastcgi_pass unix:/var/run/php-fpm/php73-fpm.sock;
  fastcgi_index index.php;
  include fastcgi.conf;
}

Pay attention, corrupting the config of nginx will make you DSM unable to run anymore ! Always check that your config is correct with the command : nginx -t

 

Ok, now, to handle both folders and php pages, one can use this variant of the location above:

location ~ /SubFolder/ {
  root /var/services/web;

  location ~ \.php$ {
    try_files $uri /index.php =404;
    fastcgi_pass unix:/var/run/php-fpm/php73-fpm.sock;
    fastcgi_index index.php;
    include fastcgi.conf;
  }
}

In the sub-location above, use php73-fpm.sock, php70-fpm.sock, php50-fpm.sock, etc… according to the version of php used by default with your nginx in your WebStation !

This is more or less working fine… I still have issues as some server variables are not passed to the php pages… But it’s working enough for my purpose. We are now only missing the basic authentication !!! Here is the final location block:

location ~ /You/Sub/Folder/ {
  root /var/services/web;

  location ~ \.php$ {
    try_files $uri /index.php =404;
    fastcgi_pass unix:/var/run/php-fpm/php73-fpm.sock;
    fastcgi_index index.php;
    include fastcgi.conf;
  }

  auth_basic “Any Prompt Message You Want”;
  auth_basic_user_file /usr/syno/share/nginx/conf.d/.htpasswd;

}

Once in place, nginx restarted, your browser cleaned and restarted too, you finally got the prompt for your login and password.

If you type a wrong login or password, you could see the error in the nginx log file: cat /var/log/nginx/error.log

2019/11/30 17:51:47 [error] 12258#12258: *145 user “mystery” was not found in “/usr/syno/share/nginx/conf.d/.htpasswd”, client: 192.168.0.1, server: _, request: “GET /err/You/Sub/Folder/ HTTP/1.1”, host: “MyNas”

2019/11/30 17:59:52 [error] 20130#20130: *3 user “mystery”: password mismatch, client: 192.168.0.1, server: _, request: “GET /You/Sub/Folder/ HTTP/1.1”, host: “MyNas”

Et voilà… Not perfect, not clear why it’s not wokring out of the box as documented here… But 

Leave a Reply

Your email address will not be published. Required fields are marked *