Password-protect a directory with htpasswd on a VPS

2 min
VPS/VDS Hosting

Basic authentication is the quickest way to hide a staging site, an admin folder or a private tool behind a login prompt. This guide covers both Apache and Nginx on your VPS Linux Infrawire, using a password file created with htpasswd.

📋 Prerequisites

  • A Linux VPS (Ubuntu 24.04 / Debian 12 or AlmaLinux 9 / Rocky 9) with root SSH access. The IP and the root password are in your customer area.
  • Apache or Nginx already serving a site.
  • A valid HTTPS certificate for example.com. Basic authentication sends the password encoded in Base64, which is not encryption: never use it over plain HTTP.

ðŸ“Ķ Install the htpasswd tool

The htpasswd command comes from a small package, even if you use Nginx:

Bash
# Debian / Ubuntu sudo apt install -y apache2-utils # AlmaLinux / Rocky sudo dnf install -y httpd-tools

🔐 Create the password file

Store the file outside any web root, so nobody can download it:

Bash
sudo mkdir -p /etc/htpasswd sudo htpasswd -c -B /etc/htpasswd/example.com USER

-B uses bcrypt. -c creates the file: use it only for the first user, because on an existing file it overwrites everything (destructive). Add more users without -c:

Bash
sudo htpasswd -B /etc/htpasswd/example.com USER2

The web server must be able to read the file:

Bash
# Debian / Ubuntu (Apache and Nginx run as www-data) sudo chown root:www-data /etc/htpasswd/example.com # AlmaLinux / Rocky: group apache (Apache) or nginx (Nginx) sudo chmod 640 /etc/htpasswd/example.com

To remove a user: sudo htpasswd -D /etc/htpasswd/example.com USER2.

ðŸŠķ Option A: Apache with .htaccess

Place a .htaccess file in the folder to protect, for example /var/www/example.com/private/.htaccess:

Apache
AuthType Basic AuthName "Restricted area" AuthUserFile /etc/htpasswd/example.com Require valid-user

.htaccess files are ignored unless the virtual host allows them. In your <Directory> block (file in /etc/apache2/sites-available/ on Debian/Ubuntu, /etc/httpd/conf.d/ on AlmaLinux/Rocky):

Apache
<Directory /var/www/example.com> AllowOverride AuthConfig </Directory>

Then test and reload:

Bash
sudo apachectl configtest sudo systemctl reload apache2 # Debian / Ubuntu sudo systemctl reload httpd # AlmaLinux / Rocky

If you prefer not to use .htaccess, put the four authentication lines directly inside a <Directory> or <Location> block: it is faster and safer.

🚀 Option B: Nginx with auth_basic

Nginx does not read .htaccess. Add the directives to the server block:

Nginx
1server { 2 listen 443 ssl; 3 server_name example.com; 4 # ssl_certificate lines here 5 6 location /private/ { 7 auth_basic "Restricted area"; 8 auth_basic_user_file /etc/htpasswd/example.com; 9 } 10}

To protect the whole site, put the two lines in the server block instead. To leave one path public inside a protected site (for example a webhook), add auth_basic off; in its own location. Then:

Bash
sudo nginx -t && sudo systemctl reload nginx

✅ Test

Without credentials you must get a 401, with credentials a 200:

Bash
curl -I https://example.com/private/ curl -I -u USER https://example.com/private/

Expected first answer:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Restricted area"

curl prompts for the password when you give -u USER alone, which keeps it out of your shell history.

🛠ïļ Troubleshooting

No prompt appears in Apache. AllowOverride is still None, or the .htaccess is in the wrong folder. Re-check the <Directory> block and reload.

Always 401 with the right password. The file is unreadable by the web server (check chown and chmod), or the path in AuthUserFile or auth_basic_user_file is wrong. The error log tells which: /var/log/apache2/error.log, /var/log/httpd/error_log or /var/log/nginx/error.log.

500 Internal Server Error after adding .htaccess. A directive is invalid or the needed module is missing. On Debian/Ubuntu auth_basic is built in; run sudo apachectl configtest and read the message.

Password prompt over HTTP. Redirect HTTP to HTTPS first, so credentials never travel in the clear.


🎉 Your private folder now asks for a login, with hashed passwords stored out of reach and served only over HTTPS.

Stay up to date with the latest offers, discounts and special promotions.

View promotions

We use cookies

We use analytics cookies to improve your experience on our site. No data is sold to third parties. Learn more in our privacy policy.