Password Protect a Dockerized Nginx Server: Step by Step
Tags: nginx, docker, webdev, tutorial
Published: 2022-01-26 00:51:38

Quite often when a site is in development it can be necessary to grant access to users on a case by case basis. Having the opportunity to create custom username/password authentication is extremely useful and is usually taken care of via a web host's control panel. But in more and more circumstances, working directly with web containers is becoming the standard and you'll find yourself creating and deploying your own web server from scratch. I've found the easiest way to do that is through the official Nginx Docker container. 

There are a lot of "Hello World" tutorials on how to quickly spin up a web server using Nginx but as soon as you start trying to add basic authentication in the mix it gets considerably more difficult to figure out. Surprisingly it actually isn't very complicated and once you have the initial config files and Dockerfiles created, it's a pretty quick process.

Let's start by getting the basic server launched to make sure everything is working. First thing is you need a site to serve and as it happens, I just created one for you: 
```
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Cool Site</title>
  </head>
  <body>
    <div
      style="
        display: flex;
        align-items: center;
        justify-content: center;
        height: 500px;
      "
    >
      Welcome to My Cool Site &trade;
    </div>
  </body>
</html>

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uuraapcngllylzaaeegq.png)
(save this file as /dist/index.html)
Our site is taking advantage of all the latest in Web3 features and just needs to be hosted. 

Before we debut it to the world, let's get it working in Docker Desktop. We'll be using the latest build of Nginx using the alpine official image:
```
FROM nginx:alpine
COPY ./dist /usr/share/nginx/html/

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bede1a338cdw2ad0df4q.png)
(save this file as Dockerfile)
We've created our Dockerfile, now we just need to build, run and enjoy. Building is easy:
```
docker build -t cool-site-server-dev:latest .
```
And now we run it:
```
docker run -dp 3000:80 --name CoolSite cool-site-server-dev
```
If you visit localhost:3000 in your browser, your new site is deployed. You can now take that same image and deploy it on any container-base cloud platform like Heroku, Cloud Run, Fargate (if you want to help Bezos build another Blue Origin), etc. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yksw7d7oy61cn97nhrau.png)

Arguably the site is already stunning, but maybe you want to add some new features and run them by a client first. You don't want just anyone stumbling across the site during development so lets add some authentication to the frontend. 

First thing that needs to happen is we need to create a user file for basic authentication. This will be the username/password combo that is required to visit a site. You can roll your own or just visit a site like [Web 2.0 Generators](https://www.web2generators.com/apache-tools/htpasswd-generator) and use theirs. That will generate an MD5 Hashed password that can be used in conjunction with our Nginx config to lock down the site. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2v7xms92b63d7kfvrgbo.png)
In our case, a simple Username of "client" and Password of "password2022" will work. That produces the following UN/PW combination that will need to be saved as an .htpasswd file:
```
 client:$apr1$xu3ntfr2$.bvn2673gIlT4sxAAI0p51
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m8ehqqgeepni2vd71n91.png)
At this point we have a working site, a working container, and a username and password that we want to use. All we need now is to add the authentication. We will need to make some quick alterations to our Dockerfile to add some extra commands during build, but first, lets create a config file for our Nginx server to tell it to require authentication. 

The new file we create is called nginx.conf with the following code:
```
worker_processes auto;

events { worker_connections 1024; }

  http {
    server {
      
        location / {
          root   /usr/share/nginx/html;
          index  index.html index.htm;

          auth_basic "Restricted";
          auth_basic_user_file  /etc/nginx/.htpasswd;

          include  /etc/nginx/mime.types;
    }
  }
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v64p2li44h7f8szbtuio.png)
Once that's saved, we're ready to add it to our Docker build process. We only need to add 2 lines of code to the Dockerfile. 1 line to copy in the nginx config file to the proper place in the container and the second to add the username/password files. The final Dockerfile will be:
```
FROM nginx:alpine
COPY ./dist /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/nginx.conf
COPY .htpasswd /etc/nginx/.htpasswd
```  

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/evtufgqdzqe3e53w9wvd.png)
We're finally ready to deploy version 2.0 our site with the added changes and username/password authentication. We rebuild our container:
```
docker build -t cool-site-server-dev:latest .
```
And run it:
```
docker run -dp 3000:80 --name CoolSite cool-site-server-dev
```
And now we're met with a Sign In message:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2dxavox9n0gwdc70uvnw.png)
We enter the username (client) and password (password2022) combination that we generated on the Web 2.0 Generators site and just like that, we have access to the new and improved site!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jvdbbr4iz47kl56opn0j.png)
I hope that helps the next time you're developing a site and want to only grant access to a certain set of individuals. 

(Shout out to [Mackenzie Marco](https://unsplash.com/photos/8qpFv44zkMc?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink) for the header image)