Jak skonfigurować uwierzytelnianie Apache htpasswd na Ubuntu
Apache's `htpasswd` authentication provides HTTP Basic Authentication — a server-side access control mechanism that challenges any browser request with a username/password prompt before serving content. It requires zero application-layer code, operates entirely within Apache's module system, and is enforced at the web server level before any PHP, Python, or Node.js backend logic executes.
This makes it the fastest, most reliable method for protecting staging environments, internal admin panels, development builds, and any directory that must be hidden from the public internet without deploying a full identity provider.
When htpasswd Is the Right Tool — and When It Is Not
Before touching a single command, understand the threat model. HTTP Basic Authentication transmits credentials as a Base64-encoded string in the `Authorization` header. Base64 is not encryption — it is trivially reversible. This means htpasswd authentication is only secure when deployed over HTTPS. Without TLS, credentials are exposed in plaintext to any network observer.
Appropriate use cases:
- Staging and pre-production environments
- Internal developer tools and dashboards
- Temporarily restricting a site during maintenance
- Adding a secondary authentication layer in front of an application with its own login
- Protecting WordPress `wp-admin` or `xmlrpc.php` at the server level
Inappropriate use cases:
- Primary authentication for public-facing applications handling sensitive user data
- Environments where credential rotation must be audited and logged
- Multi-tenant systems requiring role-based access control
If your use case involves production user accounts, consider OAuth2, LDAP, or application-level session management instead.
Prerequisites
- An Ubuntu 20.04, 22.04, or 24.04 server with root or `sudo` access
- Apache 2.4 installed or installable via `apt`
- A registered domain with DNS pointing to your server (strongly recommended for SSL)
- Basic familiarity with the Linux command line and text editors
If you are starting from scratch, a VPS Hosting environment gives you full root access and a clean Ubuntu image — the ideal baseline for this configuration.
Step 1: Install Apache2
If Apache is not yet installed, update the package index and install it:
“`bash
sudo apt update && sudo apt install apache2 -y
“`
Verify the installation and confirm the service is running:
“`bash
sudo systemctl status apache2
apache2 -v
“`
Enable Apache to start automatically on reboot:
“`bash
sudo systemctl enable apache2
“`
Apache's default document root is `/var/www/html`. The primary site configuration lives at `/etc/apache2/sites-available/000-default.conf`.
Step 2: Install the apache2-utils Package
The `htpasswd` binary is part of the `apache2-utils` package. On most Ubuntu installations this package is installed alongside Apache, but confirm its presence explicitly:
“`bash
which htpasswd
“`
If the command returns nothing, install the package:
“`bash
sudo apt install apache2-utils -y
“`
The `apache2-utils` package also provides `htdigest` (for Digest Authentication), `ab` (Apache Bench for load testing), and `htdbm` (for DBM-format password files). For most scenarios, `htpasswd` with the default bcrypt or MD5 hashing is sufficient.
Step 3: Create the .htpasswd File and Add Users
Choosing a Password Hashing Algorithm
This is a detail the original documentation almost universally omits. The `htpasswd` utility supports multiple hashing schemes, and the choice has real security implications:
| Algorithm | Flag | Security Level | Notes |
|---|
| ———– | —— | ————— | ——- |
|---|
| bcrypt | `-B` | Strong | Recommended; computationally expensive by design |
|---|
| SHA-256/512 (apr1-md5) | `-m` | Moderate | Default on most Linux systems; acceptable |
|---|
| MD5 (legacy) | `-m` on some builds | Weak | Do not use for new deployments |
|---|
| Plaintext | `-p` | None | Never use in production |
|---|
| SHA-1 | `-s` | Weak | Deprecated; vulnerable to brute force |
|---|
Always use bcrypt for new `.htpasswd` files:
“`bash
sudo htpasswd -cB /etc/apache2/.htpasswd your_username
“`
Breaking down the flags:
- `-c` — Creates a new file. Critical warning: If the file already exists, `-c` silently overwrites it, deleting all existing users. Only use `-c` once, when first creating the file.
- `-B` — Forces bcrypt hashing
- `/etc/apache2/.htpasswd` — The target file path, intentionally outside the web root
- `your_username` — Replace with the actual username
You will be prompted to enter and confirm the password. The resulting file entry looks like:
“`
your_username:$2y$05$randomsaltandhashedpasswordstring
“`
Adding Additional Users
To add more users to an existing file, omit the `-c` flag:
“`bash
sudo htpasswd -B /etc/apache2/.htpasswd second_user
sudo htpasswd -B /etc/apache2/.htpasswd third_user
“`
Removing a User
“`bash
sudo htpasswd -D /etc/apache2/.htpasswd username_to_remove
“`
Verifying the File Contents
“`bash
sudo cat /etc/apache2/.htpasswd
“`
Each line represents one user in the format `username:hashed_password`.
Step 4: Configure Apache for Password Protection
There are two methods for applying htpasswd authentication: via `.htaccess` files or directly in the virtual host configuration. Each has distinct performance and maintenance implications.
Method Comparison
| Factor | .htaccess Method | Virtual Host Config Method |
|---|
| ——– | —————– | ————————— |
|---|
| Requires Apache restart | No | Yes |
|---|
| Performance impact | Higher (Apache reads on every request) | Lower (loaded once at startup) |
|---|
| Granularity | Per-directory, delegated | Centralized in config file |
|---|
| Recommended for | Shared hosting, dynamic per-dir config | Dedicated/VPS servers with root access |
|---|
| Security posture | Slightly weaker (file must be readable by web process) | Stronger (config not web-accessible) |
|---|
On a Dedicated Server or VPS where you have full root access, the virtual host configuration method is always preferable for performance and maintainability.
Option 1: Using .htaccess Files
This method requires `AllowOverride` to be enabled for the target directory. First, edit the site configuration:
“`bash
sudo nano /etc/apache2/sites-available/000-default.conf
“`
Locate or add the `<Directory>` block for your web root and set `AllowOverride All`:
“`apache
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
Options -Indexes +FollowSymLinks
Require all granted
</Directory>
</VirtualHost>
“`
Restart Apache to apply the configuration change:
“`bash
sudo systemctl restart apache2
“`
Now create the `.htaccess` file inside the directory you want to protect:
“`bash
sudo nano /var/www/html/.htaccess
“`
Add the following authentication directives:
“`apache
AuthType Basic
AuthName "Restricted Access — Authorized Personnel Only"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
“`
Directive breakdown:
- `AuthType Basic` — Activates HTTP Basic Authentication. The alternative is `Digest`, which avoids sending credentials in Base64 but has broader compatibility issues.
- `AuthName` — The realm string displayed in the browser's login dialog. Make it descriptive enough that legitimate users understand what they are accessing.
- `AuthUserFile` — Absolute path to the `.htpasswd` file. Must be readable by the Apache process user (`www-data`).
- `Require valid-user` — Grants access to any user present in the `.htpasswd` file. You can restrict further with `Require user alice bob` to allow only specific accounts.
Save and close the file. No Apache restart is needed — `.htaccess` changes take effect immediately.
Option 2: Direct Virtual Host Configuration (Recommended)
This is the production-grade approach. Edit the virtual host configuration file directly:
“`bash
sudo nano /etc/apache2/sites-available/000-default.conf
“`
Add a `<Directory>` block with authentication directives inside the `<VirtualHost>` block:
“`apache
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ServerName yourdomain.com
<Directory "/var/www/html/protected">
AuthType Basic
AuthName "Internal Tools"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
Options -Indexes
</Directory>
</VirtualHost>
“`
Note the use of `/var/www/html/protected` rather than the entire web root. Scoping authentication to a subdirectory is far more common in practice — you protect `/admin`, `/staging`, or `/api-docs` while leaving the public site accessible.
Validate the configuration syntax before restarting:
“`bash
sudo apachectl configtest
“`
You should see `Syntax OK`. If there are errors, Apache will describe them precisely. Never restart Apache without passing this check in production.
Restart Apache:
“`bash
sudo systemctl restart apache2
“`
Protecting Specific File Types Instead of Directories
A lesser-known but highly practical pattern is using `<FilesMatch>` to restrict access to specific file extensions rather than entire directories:
“`apache
<FilesMatch ".(env|log|sql|bak)$">
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</FilesMatch>
“`
This is particularly useful for blocking direct access to `.env` files, database dumps, or log files that may exist in the web root for legacy reasons.
Step 5: Enable SSL Before Going Live
As established earlier, HTTP Basic Authentication over plain HTTP is insecure. Before exposing any htpasswd-protected resource to the internet, enforce HTTPS.
Install Certbot for Let's Encrypt certificates:
“`bash
sudo apt install certbot python3-certbot-apache -y
sudo certbot –apache -d yourdomain.com
“`
Certbot will automatically modify your Apache configuration to redirect HTTP to HTTPS and install the certificate. Alternatively, you can provision a commercial certificate through SSL Certificates for domains requiring extended validation or wildcard coverage.
After enabling SSL, add an HTTPS redirect to your HTTP virtual host:
“`apache
<VirtualHost *:80>
ServerName yourdomain.com
Redirect permanent / https://yourdomain.com/
</VirtualHost>
“`
Step 6: Harden .htpasswd File Permissions
The `.htpasswd` file contains hashed credentials. Even though bcrypt hashes are computationally expensive to crack, the file must be protected at the filesystem level.
Set ownership to the Apache process user and restrict read permissions:
“`bash
sudo chown root:www-data /etc/apache2/.htpasswd
sudo chmod 640 /etc/apache2/.htpasswd
“`
This configuration means:
- `root` owns the file and can read/write it
- `www-data` (the Apache process) can read it
- All other users have no access
Verify the permissions:
“`bash
ls -la /etc/apache2/.htpasswd
“`
Expected output:
“`
-rw-r—– 1 root www-data 89 Jan 15 10:23 /etc/apache2/.htpasswd
“`
Blocking Direct Web Access to .htpasswd
If for any reason the `.htpasswd` file is inside the web root, add an explicit denial rule to your Apache configuration or `.htaccess`:
“`apache
<Files ".htpasswd">
Require all denied
</Files>
“`
This is a defense-in-depth measure. The file should never be inside the web root, but this rule ensures that even if it is, Apache will return a 403 Forbidden response rather than serving the file.
Step 7: Test the Authentication
Open a browser and navigate to the protected URL:
“`
http://your_server_ip_or_domain/protected/
“`
You should see a native browser authentication dialog. Enter the credentials you created with `htpasswd`. Successful authentication grants access; incorrect credentials return an HTTP 401 Unauthorized response.
Testing from the Command Line
Use `curl` to verify authentication behavior without a browser:
“`bash
Test with correct credentials — should return 200 OK
curl -u your_username:your_password -I http://yourdomain.com/protected/
Test without credentials — should return 401 Unauthorized
curl -I http://yourdomain.com/protected/
Test with wrong credentials — should return 401 Unauthorized
curl -u your_username:wrongpassword -I http://yourdomain.com/protected/
“`
This is particularly useful in CI/CD pipelines or automated monitoring scripts where you need to verify that authentication is enforced correctly after deployments.
Advanced Configuration Patterns
Combining htpasswd with IP-Based Access Control
You can combine password authentication with IP whitelisting using `RequireAll` or `RequireAny` blocks:
“`apache
<Directory "/var/www/html/admin">
AuthType Basic
AuthName "Admin Panel"
AuthUserFile /etc/apache2/.htpasswd
Allow access if EITHER condition is met
<RequireAny>
Require ip 192.168.1.0/24
Require valid-user
</RequireAny>
</Directory>
“`
Or require BOTH conditions simultaneously (IP must match AND credentials must be valid):
“`apache
<RequireAll>
Require ip 203.0.113.0/24
Require valid-user
</RequireAll>
“`
This pattern is extremely effective for admin panels: internal network users get password-prompted access, while external IPs are blocked entirely regardless of credentials.
Rate Limiting Authentication Attempts
HTTP Basic Authentication has no built-in brute-force protection. Mitigate this with `mod_evasive` or `fail2ban`:
“`bash
sudo apt install fail2ban -y
“`
Create a custom Fail2ban filter for Apache authentication failures at `/etc/fail2ban/filter.d/apache-auth.conf`:
“`ini
[Definition]
failregex = ^<HOST> -.*"(GET|POST|HEAD).*" 401
ignoreregex =
“`
Add a jail configuration at `/etc/fail2ban/jail.local`:
“`ini
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/access.log
maxretry = 5
bantime = 3600
findtime = 600
“`
Restart Fail2ban:
“`bash
sudo systemctl restart fail2ban
“`
This bans any IP that generates five 401 responses within ten minutes for one hour — a significant deterrent against automated credential stuffing.
Using Location Blocks for URL-Based Protection
For applications where the protected content is served from a specific URL path rather than a filesystem directory, use `<Location>` instead of `<Directory>`:
“`apache
<Location "/api/internal">
AuthType Basic
AuthName "Internal API"
AuthUserFile /etc/apache2/.htpasswd
Require user api_user service_account
</Location>
“`
Note the use of `Require user` with specific usernames rather than `Require valid-user` — this restricts the endpoint to only those two accounts even if the `.htpasswd` file contains additional users.
Practical Decision Matrix
Use this matrix to determine the right configuration approach for your scenario:
| Scenario | Recommended Approach |
|---|
| ———- | ——————— |
|---|
| Protecting a staging subdirectory on a VPS | Virtual host `<Directory>` block with bcrypt |
|---|
| Shared hosting with no Apache config access | `.htaccess` method |
|---|
| Admin panel accessible only from office IP | `RequireAll` combining IP + valid-user |
|---|
| Blocking `.env` and `.sql` files in web root | `<FilesMatch>` with `Require all denied` |
|---|
| High-traffic site needing auth on one path | `<Location>` block in virtual host config |
|---|
| Any public-facing protected resource | Mandatory SSL + htpasswd + Fail2ban |
|---|
Key Technical Takeaways
- Always use bcrypt (`-B` flag) when creating `.htpasswd` files. Legacy MD5 and SHA-1 hashes are crackable with modern GPU hardware in seconds.
- Never deploy htpasswd over HTTP in any environment accessible from the internet. The Base64 encoding of Basic Auth credentials provides zero confidentiality.
- Prefer virtual host configuration over `.htaccess` on any server where you have root access. The performance difference is measurable under load because Apache re-reads `.htaccess` files on every single request.
- Scope protection to the minimum necessary directory or URL path. Protecting `/var/www/html` entirely when only `/var/www/html/admin` needs protection adds unnecessary friction.
- Set `.htpasswd` permissions to `640` with `root:www-data` ownership. The file should never be world-readable.
- Implement Fail2ban to prevent brute-force attacks. HTTP Basic Auth has no native rate limiting or account lockout mechanism.
- Validate Apache configuration with `apachectl configtest` before every restart in production environments.
- Pair htpasswd with your domain infrastructure. A properly configured domain with DNS and SSL is the foundation — manage yours through Domain Registration to keep all infrastructure components under one provider.
For teams managing multiple protected environments, a VPS with cPanel provides a graphical interface for managing password-protected directories without direct command-line access, which can reduce configuration errors in less technical teams.
FAQ
Does htpasswd authentication work with all browsers?
Yes. HTTP Basic Authentication is defined in RFC 7617 and is supported by every modern browser, including Chrome, Firefox, Safari, and Edge. Mobile browsers also support it. The native browser dialog appearance varies by browser and operating system, but the underlying protocol behavior is identical.
What happens if the .htpasswd file path is wrong in the Apache configuration?
Apache will return a 500 Internal Server Error for any request to the protected resource and log an error similar to `Could not open password file: /path/to/.htpasswd` in `/var/log/apache2/error.log`. Always verify the absolute path is correct and that the `www-data` user has read permission on the file.
Can I use htpasswd to protect a WordPress site's admin area?
Yes, and it is a recommended hardening practice. Adding htpasswd protection to `/wp-admin/` and restricting access to `xmlrpc.php` adds a server-level authentication layer before WordPress's own login logic executes, blocking automated bots and brute-force scripts that never reach PHP. Configure it as a `<Directory>` block in your virtual host rather than `.htaccess` for better performance.
How do I update a user's password in an existing .htpasswd file?
Run `htpasswd` without the `-c` flag and specify the existing username: `sudo htpasswd -B /etc/apache2/.htpasswd existing_user`. You will be prompted for the new password. The command overwrites only that user's entry, leaving all other users intact.
Is there a limit to how many users can be stored in a .htpasswd file?
There is no hard limit imposed by Apache. However, because Apache performs a linear scan of the file for each authentication request, performance degrades noticeably with very large files — typically above several hundred users. For environments requiring authentication for dozens or hundreds of users, consider `mod_authn_dbd` with a database backend, or LDAP authentication via `mod_authnz_ldap`, which are designed for scale.
