Security

Password protect a site or folder in Nginx and Apache with htpasswd

Add HTTP Basic authentication to a staging site, admin area or folder: create an htpasswd file with bcrypt, configure Nginx auth_basic or Apache AuthType Basic, and combine it with IP allow lists.

BeginnerLinux VPS3 min read

HTTP Basic authentication puts a browser login prompt in front of a whole site or a single folder. It is the quickest way to keep a staging site out of search engines, add a second lock in front of an admin panel, or share files privately. This guide shows how to password protect a directory on Nginx and Apache using an htpasswd file.

Before you start

  • Root access to the server, with HTTPS enabled. Basic auth sends the password with every request, encoded but not encrypted, so never use it over plain HTTP.
  • On cPanel hosting, use cPanel → Files → Directory Privacy instead; it creates the same files for you.

Create the htpasswd file

  1. Install the tool:
    • Ubuntu/Debian: sudo apt install apache2-utils
    • AlmaLinux/Rocky: sudo dnf install httpd-tools
  2. Create the file with a first user, using bcrypt (-B):
    sudo htpasswd -c -B /etc/nginx/.htpasswd alice
  3. Add more users without -c (which would overwrite the file):
    sudo htpasswd -B /etc/nginx/.htpasswd bob
  4. Remove a user: sudo htpasswd -D /etc/nginx/.htpasswd bob.
  5. Restrict permissions so only root and the web server can read it:
    sudo chown root:www-data /etc/nginx/.htpasswd && sudo chmod 640 /etc/nginx/.htpasswd

Keep the file outside the web root so it can never be downloaded. For Apache, /etc/apache2/.htpasswd or /etc/httpd/.htpasswd are common locations.

Nginx: protect the whole site

server {
    server_name staging.example.com;
    auth_basic "Staging - authorised users only";
    auth_basic_user_file /etc/nginx/.htpasswd;
    # rest of the server block
}

Nginx: protect one folder

location ^~ /admin/ {
    auth_basic "Admin area";
    auth_basic_user_file /etc/nginx/.htpasswd;
    try_files $uri $uri/ /index.php?$args;
}

If the folder contains PHP, the PHP files must also be handled inside this location (with its own fastcgi_pass) or by a nested PHP location; otherwise the general \.php$ regex location matches them first and skips the password. The ^~ modifier plus a nested location avoids that. See location matching order.

Apache: protect a folder

In the vhost (preferred) or an .htaccess inside the folder:

<Directory /var/www/example.com/public/admin>
    AuthType Basic
    AuthName "Admin area"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

In .htaccess, leave out the <Directory> lines. The folder needs AllowOverride AuthConfig. The same .htaccess rules work on LiteSpeed.

Skip the password for trusted IPs

Nginx

satisfy any;
allow 203.0.113.10;
deny all;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;

Requests from 203.0.113.10 get in directly; everyone else must log in. Use satisfy all to require both the IP and the password.

Apache

<RequireAny>
    Require ip 203.0.113.10
    Require valid-user
</RequireAny>

Exclude paths that must stay public

Let's Encrypt validation and health checks must not hit the password prompt:

location ^~ /.well-known/acme-challenge/ { auth_basic off; }

In Apache, a <Location "/.well-known/acme-challenge/"> block with Require all granted does the same.

Test

curl -sI https://staging.example.com/ | head -1
curl -sI -u alice:YOURPASSWORD https://staging.example.com/ | head -1

The first should be 401, the second 200.

Troubleshooting

  • 500 error after adding auth: wrong path to the htpasswd file, or the web server can't read it.
  • Login prompt keeps reappearing: the password hash format isn't supported (use -B), or the user doesn't exist.
  • PHP pages bypass the password in Nginx: the PHP regex location matched first. Nest PHP handling inside the protected location.
  • WordPress admin-ajax breaks: front-end features call /wp-admin/admin-ajax.php; exclude it from protection.

FAQ: password protecting folders

Is Basic auth secure enough?

Over HTTPS with strong passwords and rate limiting, it's a solid extra layer, but not a replacement for app login security.

Will search engines index a protected site?

No. They get 401 and can't see content.

Can I log out of Basic auth?

Browsers cache the credentials until closed; there is no proper logout.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.