Password Protecting a Directory Using NGINX

Coming from an Apache world, I was familiar with setting up a simple password protected directory using .htaccess rules.

However, in setting up a bare-bones LEMP server on Digital Ocean I wasn’t installing Apache, so I didn’t have access to the htpasswd utility. So, pulling together information from a number of different sources:

I came up with this workflow:

Determine the Directory To Protect

Since you are reading this post, you probably already know this. However for the sake of this walk through let’s be thorough.

In a default LEMP stack on Ubuntu 14.04, the NGINX document root is found at:

/usr/share/nginx/html/

You can verify this by taking a look at the sites that are enabled. Open any files found in /etc/nginx/sites-enabled and look for lines that say root /usr/some/path;

For this post I’ll create a new folder and webpage under /usr/share/nginx/html/ to test and make sure things work correctly:

cd /usr/share/nginx/html
mkdir private
echo "A Protected Webpage" > private/index.html

Navigating to the url http://example.com/private/ should give you a white page with the text ‘A Protected Webpage’.

Create The Password

Since this is a LEMP stack we have PHP, so we have an easy way to generate the password to use on our protected directory:

php -r 'echo crypt("password", "salt");echo PHP_EOL;'

The resulting string of text is what we will use in our password file. It should go without saying — don’t use the word password as your password. As for salt part, that helps by giving some random magic to your password. For more info, checkout the manpage for the crypt: man crypt

So, if we did in fact use the above values of ‘password’ and ‘salt’, the resulting string should give us sa3tHJ3/KuYvI

We simply need to store this string in a file so that NGINX can access this. It is important to create this file outside of the server root. I prefer to put this near the HTML root so that it is easily accessible:

cd /usr/share/nginx
nano .passwords

Now add the user and password to that .passwords file. For NGINX the syntax is username:passwordhash:anycomments, and the resulting text to paste is:

benjamin:sa3tHJ3/KuYvI:Protecting the private folder

Save and exit nano.

Update NGINX Server Conf to Actually Protect the Folder

Finally we need to let NGINX know which folder to protect, and what file to check for valid user/password combinations. Edit the site configuration file for our site found in the sites-enabled folder. If it is an out of the box setup, that would be the default file:

nano /etc/nginx/sites-enabled/default

Within the server block, you should see a location block that looks something like:

location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}

Directly below this block (but still within the server block) add another location rule for any URLs that match our private folder, and which points to our passwords file:

location ^~ /private/ {
auth_basic "Restricted";
auth_basic_user_file /usr/share/nginx/.passwords;
}

Save this file and exit nano.

Now restart NGINX:

service nginx restart

If all went well, visiting your protected folder in a browser should prompt you for your password!