.htaccess best practices
Performance, security, and maintainability recommendations for Apache .htaccess files, including when to use httpd.conf instead.
- Use httpd.conf Instead of .htaccess When Possible
- Keep .htaccess Files to a Minimum
- Set AllowOverride to the Minimum Required Classes
- Enable HTTP Strict Transport Security (HSTS) in .htaccess
- Use Apache 2.4 Syntax in .htaccess
- Wrap Rewrite Rules in IfModule Checks in .htaccess
- Test .htaccess Changes in a Staging Environment
Opinionated recommendations for writing secure, performant, and maintainable
.htaccessconfigurations in Apache HTTP Server.
Use httpd.conf Instead of .htaccess When Possible
Apache HTTP Server reads
.htaccess files on every request, which creates per-request file system overhead. Directives placed in
httpd.conf or inside a
<VirtualHost> block load once at server startup and avoid repeated disk lookups. Move
.htaccess directives into the main configuration whenever root access to the server is available.
The
httpd.conf file uses
<Directory> blocks to apply the same per-directory rules that
.htaccess provides. This approach delivers identical functionality without the performance cost of per-request file parsing.
<VirtualHost *:443>
DocumentRoot "/var/www/example_com/public_html"
ServerName example.com
<Directory "/var/www/example_com/public_html">
Require all granted
Options +FollowSymLinks -Indexes
</Directory>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com%{REQUEST_URI} [R=301,L]
</VirtualHost>Keep .htaccess Files to a Minimum
Apache HTTP Server searches for
.htaccess files in every directory along the request path. Multiple
.htaccess files increase the number of disk reads per request and make debugging harder. Consolidate all directives into a single
.htaccess file in the document root (such as
public_html/) whenever possible.
A scattered collection of
.htaccess files across nested directories creates inheritance conflicts. A child
.htaccess file can silently override a parent's directives, which leads to unexpected behavior that is difficult to diagnose.
Set AllowOverride to the Minimum Required Classes
The
AllowOverride All setting in Apache HTTP Server permits every directive category in
.htaccess files. Restrict
AllowOverride to only the directive classes the site requires. This limits the attack surface if an attacker gains write access to a
.htaccess file.
<Directory "/var/www/example_com/public_html">
AllowOverride AuthConfig FileInfo Options
</Directory>The
AuthConfig class enables authentication directives. The
FileInfo class enables
mod_rewrite and MIME type directives. The
Options class controls directory features such as
FollowSymLinks and
Indexes. Grant only what the application requires.
Enable HTTP Strict Transport Security (HSTS) in .htaccess
The
.htaccess
mod_headers module sets the
Strict-Transport-Security header, which instructs browsers to use HTTPS exclusively for future requests. HSTS prevents man-in-the-middle attacks and SSL-stripping attacks on sites that serve HTTPS.
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>The
max-age value specifies the duration in seconds. Common values:
| Duration | Seconds |
|---|---|
| 1 hour | 3600 |
| 1 day | 86400 |
| 7 days | 604800 |
| 30 days | 2630000 |
| 1 year | 31536000 |
Remove
includeSubDomains if the site has subdomains that do not support HTTPS. Adding
includeSubDomains to a site with HTTP-only subdomains breaks access to those subdomains in browsers that enforce HSTS.
Use Apache 2.4 Syntax in .htaccess
Apache HTTP Server 2.4 replaced the
Order,
Allow, and
Deny directives with the
Require directive from
mod_authz_core. The old directives still function when
mod_access_compat is loaded, but they are deprecated. New
.htaccess files should use
Require exclusively.
Mixing Apache 2.2 and 2.4 access control directives in the same
.htaccess file causes unpredictable behavior. Use
<IfModule> conditionals only when the same
.htaccess file must work across both Apache versions.
Wrap Rewrite Rules in IfModule Checks in .htaccess
The
.htaccess
<IfModule> directive prevents a 500 Internal Server Error when a required Apache module is not loaded. Wrap
mod_rewrite directives in an
<IfModule mod_rewrite.c> block so Apache skips the rules gracefully instead of returning an error.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>Test .htaccess Changes in a Staging Environment
Apache HTTP Server does not validate
.htaccess syntax before applying directives. A single syntax error causes a 500 Internal Server Error for every request to the affected directory. Test
.htaccess changes on a staging server or development environment before deploying to production.
Use the
apachectl configtest command to validate the main server configuration. This command does not check
.htaccess files directly, but it verifies that the modules referenced by
.htaccess directives are loaded.
apachectl configtest