Basic auth done properly
HTTP Basic authentication remains the fastest way to put a password on a staging site, an internal dashboard, or a metrics endpoint: two lines of nginx config and an htpasswd file. The weak link is usually how that file gets generated, either the htpasswd binary isn't installed (it ships with Apache, not nginx), or someone pastes a real password into a random website with a backend. This generator runs bcrypt entirely in your browser; open the network tab and verify no request is made.
Why bcrypt, and what cost to pick
htpasswd files support several formats, most of them historical: plain crypt() truncates at 8 characters, and the MD5-based $apr1$ is fast to brute-force on a GPU. Bcrypt ($2y$) is the current recommendation: Apache 2.4 and nginx both verify it natively. The cost parameter doubles the work per increment: cost 12 takes ~0.2–0.3 s per verification on typical hardware, which is imperceptible on login and ruinous for offline cracking. Use 12 as the default; 10 for high-traffic endpoints where auth happens on every request; 14 for rarely-used admin gates.
Deploying the line
Append the output to a file readable by the web server but nobody else (chown root:www-data; chmod 640), then in nginx: auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd;. Two caveats: Basic auth sends credentials with every request base64-encoded, not encrypted (it is only acceptable over HTTPS) and it has no rate limiting of its own, so pair it with limit_req on sensitive endpoints.