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

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](http://clubmate.fi/protect-a-directory-or-a-domain-with-a-password-on-nginx-server/#Protect_WordPress_wpadmin_and_wploginphp).

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. The related
[NGINX location directive guide](/understunding-ngix-location-directive-and-redirects)
explains how those request matching blocks work.

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:

```shell
$ 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:

```shell
$ 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`.

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

And add in a second `location` there:

```nginx
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:

```nginx
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:

```shell
$ 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:

```nginx
# 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](http://wiki.nginx.org/HttpCoreModule#location).

## Conclusions

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