bcrypt vs APR1 vs SHA for htpasswd
An htpasswd line is user:hash. The hash prefix decides the algorithm. Pick bcrypt unless your server literally cannot verify it.
bcrypt ($2y$ / $2b$ / $2a$)
Slow by design, salted, supported by Apache htpasswd -B and by Nginx on glibc systems that expose bcrypt in crypt().
Cost 10–12 is typical. Every request with basic auth pays that cost, so do not set it absurdly high on busy sites.
Apache MD5 ($apr1$)
A salted MD5 variant Apache invented for htpasswd. Weaker than bcrypt, but still far better than {SHA}. Use it only when bcrypt is unavailable (some Alpine/musl Nginx builds).
{SHA} (unsalted SHA-1)
A single SHA-1 of the password, Base64-encoded, no salt. Two users with the same password get the same hash. Do not use it for new files.
Nginx and Apache config sketch
Keep the file outside the web root. Basic auth sends the password on every request (Base64, not encrypted) — HTTPS only.
# Nginx
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
# Apache
AuthType Basic
AuthName "Restricted"
AuthUserFile /etc/apache2/.htpasswd
Require valid-userQuestions
- Why does Nginx reject my bcrypt line?
- Your libc may lack bcrypt in crypt(). Switch to $apr1$ on that host, or hash on a machine whose crypt() supports bcrypt and confirm the server build.
- Are $2y$ and $2b$ different?
- Same algorithm. $2y$ is what Apache and PHP prefer to write; verifiers usually accept both.
Related tool: htpasswd generator. Runs in your browser; input is not uploaded.