Tutorial

How To Set Up Password Authentication with Nginx on Ubuntu 14.04

Published on August 10, 2015
How To Set Up Password Authentication with Nginx on Ubuntu 14.04
Not using Ubuntu 14.04?Choose a different version or distribution.
Ubuntu 14.04

Introduction

When setting up a web server, there are often sections of the site that you wish to restrict access to. Web applications often provide their own authentication and authorization methods, but the web server itself can be used to restrict access if these are inadequate or unavailable.

In this guide, we’ll demonstrate how to password protect assets on an Nginx web server running on Ubuntu 14.04.

Prerequisites

To get started, you will need access to an Ubuntu 14.04 server environment. You will need a non-root user with sudo privileges in order to perform administrative tasks. To learn how to create such a user, follow our Ubuntu 14.04 initial server setup guide.

If you haven’t done so already, install Nginx on your machine by typing:

  1. sudo apt-get update
  2. sudo apt-get install nginx

Create the Password File

To start out, we need to create the file that will hold our username and password combinations. You can do this by using the OpenSSL utilities that may already be available on your server. Alternatively, you can use the purpose-made htpasswd utility included in the apache2-utils package (Nginx password files use the same format as Apache). Choose the method below that you like best.

Create the Password File Using the OpenSSL Utilities

If you have OpenSSL installed on your server, you can create a password file with no additional packages. We will create a hidden file called .htpasswd in the /etc/nginx configuration directory to store our username and password combinations.

You can add a username to the file using this command. We are using sammy as our username, but you can use whatever name you’d like:

  1. sudo sh -c "echo -n 'sammy:' >> /etc/nginx/.htpasswd"

Next, add an encrypted password entry for the username by typing:

  1. sudo sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd"

You can repeat this process for additional usernames. You can see how the usernames and encrypted passwords are stored within the file by typing:

  1. cat /etc/nginx/.htpasswd
Output
sammy:$apr1$wI1/T0nB$jEKuTJHkTOOWkopnXqC1d1

Create the Password File Using Apache Utilities

While OpenSSL can encrypt passwords for Nginx authentication, many users find it easier to use a purpose-built utility. The htpasswd utility, found in the apache2-utils package, serves this function well.

Install the apache2-utils package on your server by typing:

  1. sudo apt-get update
  2. sudo apt-get install apache2-utils

Now, you have access to the htpasswd command. We can use this to create a password file that Nginx can use to authenticate users. We will create a hidden file for this purpose called .htpasswd within our /etc/nginx configuration directory.

The first time we use this utility, we need to add the -c option to create the specified file. We specify a username (sammy in this example) at the end of the command to create a new entry within the file:

  1. sudo htpasswd -c /etc/nginx/.htpasswd sammy

You will be asked to supply and confirm a password for the user.

Leave out the -c argument for any additional users you wish to add:

  1. sudo htpasswd /etc/nginx/.htpasswd another_user

If we view the contents of the file, we can see the username and the encrypted password for each record:

  1. cat /etc/nginx/.htpasswd
Output
sammy:$apr1$lzxsIfXG$tmCvCfb49vpPFwKGVsuYz. another_user:$apr1$p1E9MeAf$kiAhneUwr.MhAE2kKGYHK.

Configure Nginx Password Authentication

Now that we have a file with our users and passwords in a format that Nginx can read, we need to configure Nginx to check this file before serving our protected content.

Begin by opening up the server block configuration file that you wish to add a restriction to. For our example, we’ll be using the default server block file installed through Ubuntu’s Nginx package:

  1. sudo nano /etc/nginx/sites-enabled/default

Inside, with the comments stripped, the file should look similar to this:

/etc/nginx/sites-enabled/default
server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name localhost;

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

To set up authentication, you need to decide on the context to restrict. Among other choices, Nginx allows you to set restrictions on the server level or inside a specific location. In our example, we’ll restrict the entire document root with a location block, but you can modify this listing to only target a specific directory within the web space:

Within this location block, use the auth_basic directive to turn on authentication and to choose a realm name to be displayed to the user when prompting for credentials. We will use the auth_basic_user_file directive to point Nginx to the password file we created:

/etc/nginx/sites-enabled/default
server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
        auth_basic "Restricted Content";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

Save and close the file when you are finished. Restart Nginx to implement your password policy:

  1. sudo service nginx restart

The directory you specified should now be password protected.

Confirm the Password Authentication

To confirm that your content is protected, try to access your restricted content in a web browser. You should be presented with a username and password prompt that looks like this:

Nginx password prompt

If you enter the correct credentials, you will be allowed to access the content. If you enter the wrong credentials or hit “Cancel”, you will see the “Authorization Required” error page:

Nginx unauthorized error

Conclusion

You should now have everything you need to set up basic authentication for your site. Keep in mind that password protection should be combined with SSL encryption so that your credentials are not sent to the server in plain text. To learn how to create a self-signed SSL certificate to use with Nginx, follow this guide. To learn how to install a commercial certificate, follow this guide.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
10 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

This guide needs updating; You need to chown the .htpasswd file to www-data, otherwise it cannot read it

chown www-data:www-data /etc/nginx/.htpasswd

Why are we recommending to use MD5 hash generation with the aprl option? Please update to use -5 or -6 for SHA256/SHA512. I understand this is an older article, but it came up as the first result in a search.

Is it possible to force the authentication dialog to appear every time the web page, or the web browser for that matter, is closed and opened again?

How about being able to login without a password, e.g. using a client ssh key like ssh does. It’s certainly more convenient, and I often read that ssh auto-login is much safer than using an ssh password.

I followed the guide and am having a similar problem: everything under my.ip.address/ is protected, but when I access a different port, say my.ip.address:1234/, nothing is protected.

I tried jellingwood’s suggestion on Aug 24, 2015, but got the same result.

How can I protect all ports under my.ip.address? It doesn’t seem like the location / location block is catching it.

@jtittle @hansen @jellingwood

i am having a small problem.

i added a password before using openssl, but i forgot it. i know i could add a new user, but i want to edit password for my old user or at least delete old one and create a new one.

also there is one password without any user in my htpasswd file

username@host:~$ cat /etc/nginx/.htpasswd
user$apr1$146S4Nar$Rm8HTS/13VbjMI61ovBnl1
$apr1$sbP3SD30$roRPzaPfYA8B.nbnEce.x0

how can i delete that password without user.

another issue is, i am trying to protect adminer.php. but unfortunately, when i protect that file using http authentication, after giving the password im prompted to download the file. how can i work around this?

this is my server block

       location = /adminer.php {
               try_files $uri $uri/ =404;
               auth_basic "Restricted";
               auth_basic_user_file /etc/nginx/.htpasswd;
       }

You could reduce this article content by 95%. I don’t know why there is a need to explain this for each platform where it isn’t specific to a platform but rather having openssl and nginx installed

Step 1:

Method 1: openssl passwd -apr1 Method 2: htpasswd -c /etc/nginx/.htpasswd sammy

Step 2:

Put it in your nginx file, use the auth_basic directive into the location block.

As others have mentioned, the config (if done incorrectly) can lead to php files being accessible after trying to protect a directory. This is due to the way nginx config prioritises each part of the config.

As most servers have a single php section within their server block, when the request comes in for a php file nginx uses that config, skipping the folder / directory protection section, and serves the resulting html. Bad times.

The correct way to do this is to include a copy of the php section within your password protected section, as follows:

location /admin/ {
  auth_basic    "Admin-Section";
  auth_basic_user_file /myfolder/.htpasswd;
  location ~ \.php$ {
   fastcgi_pass  127.0.0.1:9000;
   fastcgi_index index.php;
   fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
   include       fastcgi_params;
  }
}

Make a copy of the php section i.e. don’t delete the block from your server config, else you will lose php from the rest of your site.

Credit: http://stackoverflow.com/users/1476414/fisharebest Original Answer: http://stackoverflow.com/questions/4697010/nginx-auth-basic-and-php

You can generate a password without a prompt by piping text into openssl and passing a new flag. For example:

echo "password" | openssl passwd -apr1 -stdin

This will echo to stdout. This way you can write a script or something instead of having to use the prompt to type in the password.

If you still wanted to append the output to the /etc/nginx/.htpasswd file, then you would do the following:

echo "password" | openssl passwd -apr1 -stdin >> /etc/nginx/.htpasswd

I got this working but now I think it would be cool to have a nicely designed login page for my site rather than the default browser dialogue. Is there a way to change the username and password prompt from a browser dialogue to a web form?

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel