← Back to Blog

How to Generate htpasswd File for Apache and Nginx (2026)

HTTP Basic Authentication is the fastest way to put a password gate in front of a staging server, internal tool, or admin panel. This guide covers everything: what an htpasswd file is, all supported hash formats, how to generate it on the command line or online, and how to configure Apache and Nginx to use it.

What Is an htpasswd File?

An htpasswd file is a plain text file that stores username and hashed password pairs for HTTP Basic Authentication. Each line contains one user entry in the format:

username:hashed_password

A real htpasswd file looks like this:

alice:$2y$10$XvFkEjQWJP1Yd7.kKJx2N.5XlR9b8kOqnMtV0WsYP4Rg3AhUqLDe
bob:$apr1$xyz12345$AbCdEfGhIjKlMnOpQrStUv.
charlie:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

Apache's mod_auth_basic and Nginx's ngx_http_auth_basic_module both read this file format to authenticate HTTP requests. The web server reads the file, extracts the stored hash for the given username, computes the hash of the supplied password, and grants access if they match.

Hash Algorithms Supported in htpasswd

The Apache htpasswd tool supports several hashing algorithms with very different security profiles:

bcrypt (recommended)

Prefix: $2y$. Apache 2.4+, Nginx 1.3.14+. The most secure option. bcrypt is intentionally slow (configurable work factor), which makes brute force attacks computationally expensive. Always use bcrypt for new setups.

# Generate bcrypt hash (cost factor 10)
htpasswd -nbB -C 10 alice mysecretpassword
# Output: alice:$2y$10$XvFkEjQWJP1Yd7.kKJx2N.5XlR9b8kOqnMtV0WsYP4Rg3AhUqLDe

MD5 (apr1) - avoid for new deployments

Prefix: $apr1$. Apache's own MD5 variant with a random salt. Widely supported across Apache versions including very old ones, but MD5 is cryptographically weak. Use only for compatibility with legacy systems.

htpasswd -nbm alice mysecretpassword
# Output: alice:$apr1$randSalt$AbCdEfGhIjKlMnOpQrStUv.

SHA-1 (deprecated)

Prefix: {SHA}. Stores the SHA-1 hash of the password, base64-encoded. No salting, no key-stretching - identical passwords produce identical hashes. SHA-1 is broken and should never be used for new htpasswd entries.

crypt (DES) - legacy only

The original Unix crypt function. 8-character password limit, weak by modern standards. Only use this if you are running Apache on a very old system that does not support bcrypt.

Always use bcrypt (-B flag) for new htpasswd files. It is the only algorithm that adequately resists modern cracking hardware.

Step-by-Step: Generate an htpasswd File on the Command Line

Install Apache utils (if needed)

# Ubuntu / Debian
sudo apt-get install apache2-utils

# CentOS / RHEL / Amazon Linux
sudo yum install httpd-tools

# macOS (Homebrew)
brew install httpd

# macOS has htpasswd built-in at /usr/bin/htpasswd

Create a new htpasswd file with the first user

# -c creates the file (use ONLY for the first user -- overwrites existing file)
# -B uses bcrypt
# -C 12 sets the bcrypt cost factor (higher = slower = more secure, 10-12 recommended)
htpasswd -cbB -C 12 /etc/nginx/.htpasswd alice

# You will be prompted for a password, or pass it as the last argument:
htpasswd -cbB -C 12 /etc/nginx/.htpasswd alice 'MySecureP@ssw0rd'

Add additional users to the same file

# Omit -c to append (adding -c would overwrite the file and delete existing users)
htpasswd -bB -C 12 /etc/nginx/.htpasswd bob 'AnotherStr0ngPassword'
htpasswd -bB -C 12 /etc/nginx/.htpasswd charlie 'YetAnotherP4ssword'

Update a user's password

# htpasswd overwrites the entry for an existing user
htpasswd -bB -C 12 /etc/nginx/.htpasswd alice 'NewPasswordForAlice'

Delete a user

htpasswd -D /etc/nginx/.htpasswd bob

Verify a password

htpasswd -vb /etc/nginx/.htpasswd alice 'MySecureP@ssw0rd'
# Output: Password for user alice correct.

Generate htpasswd Hashes Online

No server access? Generate bcrypt, MD5, and SHA htpasswd entries instantly in your browser. 100% client side - your passwords are never sent anywhere.

Open Htpasswd Generator

Configure Apache to Use an htpasswd File

Once you have the htpasswd file, configure Apache to require authentication for a directory or location. You can do this in either httpd.conf / a virtual host config, or in a per-directory .htaccess file.

Option 1: Virtual host or httpd.conf (preferred)

<Directory "/var/www/html/admin">
    AuthType Basic
    AuthName "Restricted Area"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

After editing the config, test it and reload Apache:

apache2ctl configtest   # or: apachectl configtest
sudo systemctl reload apache2

Option 2: .htaccess file

Create a .htaccess file inside the directory you want to protect:

AuthType Basic
AuthName "Staging Server"
AuthUserFile /var/www/html/staging/.htpasswd
Require valid-user

For .htaccess files to work, the Apache virtual host must have AllowOverride AuthConfig (or AllowOverride All) set for that directory. Without this, Apache ignores .htaccess files silently.

<Directory "/var/www/html">
    AllowOverride AuthConfig
</Directory>

Configure Nginx to Use an htpasswd File

Nginx uses the same htpasswd file format as Apache. Add the auth_basic directives to the location or server block you want to protect:

server {
    listen 80;
    server_name staging.example.com;
    root /var/www/staging;

    # Protect the entire server
    auth_basic "Staging Server";
    auth_basic_user_file /etc/nginx/.htpasswd;

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

# Or protect just a specific path:
location /admin {
    auth_basic "Admin Panel";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://localhost:8080;
}

Test and reload Nginx:

sudo nginx -t
sudo systemctl reload nginx

Protect Kubernetes Ingress with htpasswd

If you use Kubernetes with the NGINX Ingress Controller, you can add basic authentication using a Kubernetes Secret that contains the htpasswd data:

# Generate the htpasswd content
htpasswd -nbB -C 12 alice 'MyPassword' > auth

# Create a Kubernetes secret from the file
kubectl create secret generic basic-auth \
  --from-file=auth \
  -n my-namespace

# Reference it in the Ingress annotation
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Restricted Access"
spec:
  # ... your rules

Security Best Practices

  • Store the htpasswd file outside the web root. If it is inside the public directory, a misconfigured server could serve it as a plain text file. Use /etc/nginx/.htpasswd or /etc/apache2/.htpasswd instead of /var/www/html/.htpasswd.
  • Use bcrypt with cost factor 10–12. Cost factor 10 takes ~100ms per verification on modern hardware, which is acceptable for users but too slow for automated brute force attacks.
  • Combine with HTTPS. HTTP Basic Authentication sends credentials in a base64-encoded Authorization header. Without TLS, the credentials are transmitted in plaintext and easily captured by network sniffing. Always use HTTPS when using Basic Auth.
  • Restrict htpasswd file permissions. Set the file to be readable only by the web server user: chmod 640 /etc/nginx/.htpasswd && chown root:www-data /etc/nginx/.htpasswd
  • Do not use Basic Auth as the sole security layer for sensitive systems. It has no built-in rate limiting, brute force protection, or session management. For production apps, use a proper identity provider. Basic Auth is appropriate for staging servers and low-risk internal tools.

Frequently Asked Questions

What is the difference between htpasswd and htdigest?

Both are Apache password file formats. htpasswd is used with HTTP Basic Authentication, which sends credentials as base64 (not encrypted) - it is only secure over HTTPS. htdigest is used with HTTP Digest Authentication, which performs a challenge-response using MD5 hashing so credentials are not sent in plaintext, but Digest Auth is complex, rarely used, and MD5 is weak. In practice, Basic Auth over HTTPS (using htpasswd with bcrypt) is both simpler and more secure than Digest Auth.

Can I create an htpasswd file without installing Apache?

Yes. You can use our online Htpasswd Generator to create bcrypt-hashed entries entirely in your browser without installing anything. You can also use Python's passlib library: python3 -c "from passlib.hash import bcrypt; print('alice:' + bcrypt.using(rounds=12).hash('password'))". The output line format is the same as the htpasswd command produces.

Why does my Nginx basic auth always return 401 even with the correct password?

Most likely causes: (1) The hash algorithm in the htpasswd file is not supported by Nginx. Nginx does not support Apache's apr1 MD5 variant in all versions - use bcrypt or SHA-1 (SHA-1 is insecure but widely supported). (2) The auth_basic_user_file path is wrong or the file is not readable by the nginx worker process user. Check /var/log/nginx/error.log for permission errors. (3) Trailing whitespace in the htpasswd file on a user's line can cause authentication to fail.

How do I password-protect only certain IP addresses or exempt certain IPs?

In Apache 2.4+ you can combine IP-based access and Basic Auth using the Satisfy approach or the newer RequireAny / RequireAll directives. In Nginx, use the satisfy any directive combined with allow/deny and auth_basic:

location /admin {
    satisfy any;
    allow 10.0.0.0/8;   # Internal network - no auth needed
    deny all;           # Everyone else must authenticate
    auth_basic "Admin";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

Can multiple users share the same htpasswd file for different directories?

Yes. A single htpasswd file can be referenced by multiple Apache <Directory> blocks or Nginx location blocks. You can then use Require user alice bob instead of Require valid-user to restrict specific directories to specific users from the shared file. This is a clean approach for multi-user staging environments where different users should access different areas.

Use Our Free Htpasswd Generator

If you do not have access to a terminal or need to quickly generate a single bcrypt entry to paste into an existing file, use our free Htpasswd Generator. Enter a username and password, choose your hash algorithm (bcrypt recommended), and get the ready-to-paste line.

Use our free tool here → Htpasswd Generator at SecureBin.ai

UK
Written by Usman Khan
DevOps Engineer | MSc Cybersecurity | CEH | AWS Solutions Architect

Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.