clubmate.fi

A good[ish] website

Web development blog, loads of UI and JavaScript topics

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

Filed under: Server— Tagged with: nginx

If you have a login form that you don’t want people accessing, or other private service, it’s good to block access to it.

2015.05.02 — Added better WordPress related backend protection.

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.

Think of a site example.com, and a directory in it called /something-secret.

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 /something-secret {

  }
  ...
}

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 /something-secret {
    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
  }
  ...
}

Reload 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 form 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

This isn’t a silver bullet by no means, just an extra password layer.

Comments would go here, but the commenting system isn’t ready yet, sorry.

  • © 2022 Antti Hiljá
  • About
  • All rights reserved yadda yadda.
  • I can put just about anything here, no one reads the footer anyways.
  • I love u!