Setting up HTTP basic authentication on Apache or Nginx requires an .htpasswd file — a plain text file where each line pairs a username with a hashed password. Generating these hashes correctly is the first hurdle. This guide explains what htpasswd is, which algorithm to choose, how to wire it into Apache and Nginx, and how our htpasswd generator produces hashes entirely in your browser.
Quick Answer: htpasswd Generator
Create an htpasswd entry online →
| Need | Recommended choice |
|---|---|
| Production basic auth | Use bcrypt ($2y$) with a cost of 10 or higher. |
| Apache compatibility with old systems | APR1 MD5 ($apr1$) is supported but weaker than bcrypt. |
| Nginx basic auth | Use the same .htpasswd file format with auth_basic_user_file. |
| Testing only | Plaintext is only for local tests; never use it for production credentials. |
What Is an .htpasswd File?
An .htpasswd file stores username–password pairs for HTTP basic authentication. Each line follows this format:
username:$hashed_password
Apache reads this file when it needs to validate a request. Nginx uses the same format via the auth_basic_user_file directive. The file can contain multiple users — one per line.
Example .htpasswd file:
alice:$2y$10$abcdefghijklmnopqrstuuVwXyZabcdefghijklmnopqrstuuVwXyZ
bob:$apr1$xyz12345$abcdefghijklmnopqrstuvwx
carol:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
htpasswd Algorithm Comparison
Choosing the right algorithm matters for security. Here is what each option looks like and how they compare:
| Algorithm | Prefix | Security | Notes |
|---|---|---|---|
| bcrypt | $2y$ | Recommended | Work factor is tunable; slow by design |
| APR1 MD5 | $apr1$ | Acceptable | Apache-specific MD5 variant with stretching |
| SHA1 | {SHA} | Weak | No salt; vulnerable to rainbow tables |
| Plaintext | (none) | None | Never use in production |
Use bcrypt. It is the only algorithm here that includes a configurable work factor, meaning you can increase its cost as hardware gets faster. SHA1 provides no salt and is trivially defeated by precomputed hash tables. Plaintext stores the password directly — there is no recovery if the file leaks.
What the bcrypt Hash Looks Like
$2y$10$Rlm8Mzv3bKNv1Pz5h3W1Ou6G7SjkUzW9C5h4RpYNi6TmVjD8sLYi
Breaking it down:
$2y$— bcrypt, Apache-compatible variant10— cost factor (2^10 = 1024 rounds)- The remaining 53 characters encode salt + hash
Setting Up Apache Basic Auth
Step 1 — Generate the htpasswd file using our htpasswd generator or the htpasswd CLI:
# Create new file with first user
htpasswd -cB /etc/apache2/.htpasswd alice
# Add more users (no -c flag — that would overwrite)
htpasswd -B /etc/apache2/.htpasswd bob
The -B flag forces bcrypt. Without it, the CLI defaults to MD5 on most systems.
Step 2 — Configure the virtual host or directory:
<Directory "/var/www/html/private">
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
Or use an .htaccess file in the protected directory (requires AllowOverride AuthConfig in your server config):
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
Step 3 — Reload Apache:
sudo systemctl reload apache2
# or on older systems:
sudo service apache2 reload
Setting Up Nginx Basic Auth
Nginx does not ship with an htpasswd command, but it reads the same file format.
Step 1 — Create the password file. Use our browser-based generator or the Apache htpasswd utility if available:
htpasswd -cB /etc/nginx/.htpasswd alice
Step 2 — Configure the Nginx location block:
server {
listen 80;
server_name example.com;
location /private/ {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
}
To protect the entire server, move the directives outside of any location block into the server block.
Step 3 — Test and reload:
sudo nginx -t
sudo systemctl reload nginx
Security Considerations
Use HTTPS. HTTP basic auth sends credentials as a Base64-encoded header, which is trivially decoded. Without TLS, credentials travel in cleartext over the network. Basic auth over HTTP is not authentication — it is a suggestion.
Restrict file permissions. The .htpasswd file should only be readable by the web server process:
sudo chown root:www-data /etc/apache2/.htpasswd
sudo chmod 640 /etc/apache2/.htpasswd
Keep the file outside the web root. If it ends up in a publicly accessible directory, anyone can download it.
Rotate passwords periodically. To update a password for an existing user without touching other entries:
htpasswd -B /etc/apache2/.htpasswd alice
Do not use basic auth for sensitive applications. It has no built-in rate limiting, no session management, and no multi-factor support. For anything beyond simple access control, use a proper authentication layer.
Why Use a Browser-Based Generator?
The standard way to generate htpasswd entries is the CLI tool htpasswd from the apache2-utils package. That requires installing the package and having terminal access. Developers often need to create or update passwords on a machine where the Apache utilities are not installed — or they want to generate entries for a server they are configuring remotely.
Online generators solve this — but most send your password to a server for hashing. That is the wrong model for passwords.
Our htpasswd generator at zerotool.dev runs entirely in the browser. The bcrypt hashing (and all other algorithm implementations) execute in JavaScript on your machine. Your password never leaves your browser. There is no server request, no logging, no analytics on the input field. You can verify this by opening the browser’s network tab while generating a hash — no outbound request will appear for the password field.
This makes it safe to use even for production credentials, and appropriate in environments where pasting passwords into third-party web services is against security policy.
Generate htpasswd Entries
ZeroTool’s htpasswd generator supports:
- bcrypt (recommended,
$2y$prefix) - APR1 MD5 (
$apr1$prefix, Apache-compatible) - SHA1 (
{SHA}prefix) - Plaintext (for testing only)
Enter a username and password, select the algorithm, and copy the resulting line directly into your .htpasswd file. All computation is local — no data leaves your browser.