Protect a directory or a domain with a password on NGinx server

How to feel more safe in the internet.

2015.05.02 — Added better WordPress related backend protection.

It’s nice to protect a directory every now and then, sometimes a staging site is good to be under a password, or to have an extra layer of security by blocking access to a login screen. Most web servers have a password gate built in, including NGinx.

Let’s imagine a site example.com and a directory in it called /somethingsecret.

Make the password file

Username and an encrypted password pair are stored in a file. OpenSSL has a password encryption command:

$ openssl passwd
Password: macgyver
Verifying - Password: macgyver
clW5vVOB6cHYE

Just type it in when prompted and copy the result, we’re gonna need it later on.

Make an authentication file, replace nano with your editor of choice:

$ sudo nano /etc/nginx/pw_file

In the newly created file, we need to have the user and password separated by a colon :, like so:

bob:clW5vVOB6cHYE

Save and exit. Next, tell NGinx about the file.

Setup NGinx server block

Pop open the server block file that’s responsible for making the server. The default file is here: /etc/nginx/sites-available/default, or if the configuration is split into multiple files, it might be something like /etc/nginx/sites-available/example.com.cnf.

$ sudo nano /etc/nginx/sites-available/example.com.cnf

And add in a second location there:

server {
    ...
    location / {
        try_files $uri $uri/ =404;
    }

    # Here's the dir that you want to protect
    location /somethingsecret {

    }
    ...
}

We’ll need to use two directives here:

  1. auth_basic — Authentication message for the user.
  2. auth_basic_user_file — Path to the authentication file.

Now the file should look something like:

server {
    ...
    location / {
        try_files $uri $uri/ =404;
    }

    location /somethingsecret {
        auth_basic "Admin Login"; # The message for the user requesting to login
        auth_basic_user_file /etc/nginx/pw_file; # Path to the password file
    }
    ...
}

Realod or restart NGinx:

$ sudo service nginx reload
# Or restart
$ sudo service nginx restart

Protect WordPress wp-admin/ and wp-login.php

It’s nice to know that your WP login screen and backend are not exposed to the world. Here’s a little file that can be included into the main server block, it protects the wp-admin directory and the wp-login.php file:

# Protect wp-admin
location /wp/wp-admin {
    auth_basic "Admin Login";
    auth_basic_user_file /etc/nginx/pma_pass;
}

# Protect wp-login.php script
location /wp {
    location ~wp-login\.php$ {
        auth_basic "Admin Login";
        auth_basic_user_file /etc/nginx/pma_pass;

        # Have to enable php here cause of the password protection
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

# Allow access to the admin-ajax.php, all the ajax calls
# are routed this way in WordPress
location /wp/wp-admin/admin-ajax.php {
    allow all;
}

I like to put it in /etc/nginx/global, and then include it in the server block I want:

server {
    ....
    include global/wp-protect.conf;
    ....
}

Also, see the locations chapter in the NGInx manual.

Conclusions

Now you can comfortably tuck yourself into the fuzzy, soft feeling of being a bit safer in the wild and dangerous interwebs.

Comments

  • Lucas Ferraz says:

    Well done! Thanks for sharing

  • kamal says:

    Thanks for sharing this. Your explanation is one of the simplest to follow of all the ones I have come across in my search today so far. :)

    Also, you have got a pretty unique website. Very refreshing to see something out of the box.

Club-Mate, the beverage → club-mate.fi