How to enable .htaccess?
Having an .htaccess file in your directory does not guarantee that Apache will read it. Apache must be explicitly told to look for and respect these files through its main server configuration. The directive that controls this behavior is AllowOverride, and understanding how it works is essential before writing any .htaccess rules.
This guide covers the AllowOverride directive in detail, explains all of its options, introduces the AccessFileName directive, shows you how to verify that .htaccess processing is active, and walks through the most common hosting scenarios you are likely to encounter.
The AllowOverride Directive
AllowOverride is the gatekeeper for .htaccess files. It determines whether Apache looks for .htaccess files in a given directory tree and, if so, which types of directives those files are allowed to contain.
This directive can only be placed inside a <Directory> block in the main server configuration (httpd.conf, apache2.conf, or a virtual host file). It cannot be used inside .htaccess files themselves, which makes sense: you cannot use an .htaccess file to grant itself permission to exist.
Here is the basic syntax:
<Directory "/var/www/html">
AllowOverride All
</Directory>
This tells Apache: "For the /var/www/html directory and all of its subdirectories, look for .htaccess files and allow every directive they contain."
How It Affects the Directory Tree
The AllowOverride setting applies to the specified directory and everything beneath it. If you set AllowOverride All on /var/www/html, then .htaccess files in /var/www/html/blog/, /var/www/html/admin/, and any deeper subdirectory will all be processed.
You can also set different AllowOverride values for different parts of your directory tree:
<Directory "/var/www/html">
AllowOverride All
</Directory>
<Directory "/var/www/html/static">
AllowOverride None
</Directory>
In this example, .htaccess files work everywhere under /var/www/html except inside the /var/www/html/static directory, where they are completely ignored. This is useful when you have a directory of static assets that should never need per-directory configuration overrides.
AllowOverride Options
AllowOverride accepts several values. You can use a single value or combine multiple values separated by spaces.
All
AllowOverride All
This is the most permissive setting. It tells Apache to allow every type of directive inside .htaccess files. This is what you want during development and in most shared hosting environments.
When AllowOverride All is set, you can use directives related to authentication, URL rewriting, headers, directory indexing, access control, MIME types, and everything else that .htaccess supports.
None
AllowOverride None
This completely disables .htaccess processing for the specified directory. Apache will not even look for .htaccess files, which eliminates the filesystem overhead of scanning directories on every request.
This is the recommended setting for production servers where you have full access to the main configuration. All directives can be placed directly in <Directory> blocks inside the virtual host file instead.
<Directory "/var/www/html">
AllowOverride None
# Place your directives here instead of in .htaccess
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</Directory>
If AllowOverride None is set and you place an .htaccess file in the directory, Apache will silently ignore it. No error will be logged, and your directives simply will not take effect. This is one of the most common reasons .htaccess rules "do not work," so always check this setting first when troubleshooting.
Selective Overrides
Between the extremes of All and None, Apache provides several category-based values that let you enable only specific types of directives in .htaccess files. This gives administrators fine-grained control over what users can and cannot change.
| Value | What It Allows |
|---|---|
AuthConfig | Authorization and authentication directives: AuthType, AuthName, AuthUserFile, Require, and related directives. |
FileInfo | Directives that control document types, metadata, headers, URL rewriting, and error documents: RewriteRule, RewriteCond, ErrorDocument, Header, SetEnvIf, AddType, and more. |
Indexes | Directives that control directory listing appearance: DirectoryIndex, AddIcon, AddDescription, IndexOptions, and related directives. |
Limit | Access control directives for restricting access: Require, Allow, Deny, and Order (legacy 2.2 directives). |
Options | Directives that control directory-level features: Options (which itself controls Indexes, FollowSymLinks, ExecCGI, MultiViews, and others). |
You can combine multiple values to create a tailored permission set:
<Directory "/var/www/html">
AllowOverride AuthConfig FileInfo
</Directory>
This configuration allows .htaccess files to handle authentication and file-related directives (rewrites, headers, error documents) but prevents them from changing directory listing options or toggling features like FollowSymLinks.
Practical Example: Restricting to Rewrites Only
Suppose you want users to be able to set up URL rewrites in .htaccess but nothing else. The RewriteRule and RewriteCond directives fall under the FileInfo category:
<Directory "/var/www/html">
AllowOverride FileInfo
</Directory>
With this setting, an .htaccess file containing a rewrite rule works as expected:
# This works because RewriteRule is a FileInfo directive
RewriteEngine On
RewriteRule ^about$ /about.html [L]
But an .htaccess file trying to disable directory listing will fail:
# This will cause a 500 Internal Server Error
# because Options requires AllowOverride Options (or All)
Options -Indexes
When Apache encounters a directive that is not permitted by the current AllowOverride setting, it returns a 500 Internal Server Error to the visitor and logs an error message similar to:
/var/www/html/.htaccess: Options not allowed here
If you are unsure which AllowOverride category a specific directive belongs to, check the Apache directive documentation. Each directive's reference page lists its Context (where it can be used) and Override (which AllowOverride value enables it in .htaccess).
Combining All and None with Selective Overrides
All and None are mutually exclusive with the selective values. You cannot write something like AllowOverride All Indexes because All already includes everything. Similarly, AllowOverride None FileInfo does not make sense because None disables everything.
If you use All or None, it must be the only value:
# Correct
AllowOverride All
AllowOverride None
AllowOverride FileInfo Indexes
# Wrong: All already includes everything
AllowOverride All Indexes
The AccessFileName Directive
By default, Apache looks for a file named .htaccess. The AccessFileName directive in the main server configuration lets you change this name:
AccessFileName .myconfig
After setting this, Apache will look for .myconfig files instead of .htaccess when walking the directory tree.
You can even specify multiple file names, and Apache will look for each of them in order:
AccessFileName .htaccess .htconfig
In this case, Apache checks for .htaccess first. If it does not exist, it checks for .htconfig.
When Changing AccessFileName Makes Sense
In practice, changing the default name is rare and generally not recommended. Almost every piece of Apache documentation, every tutorial, every framework, and every hosting provider expects the file to be named .htaccess. Changing it introduces confusion and can break compatibility with applications like WordPress, Laravel, or Drupal that generate or modify .htaccess automatically.
There are a few niche scenarios where it might be considered:
- Security through obscurity: Renaming the file so that automated scanners looking for
.htaccessdo not find it. This is a weak security measure and should not be relied upon. - Multiple configuration layers: Using two different file names for different purposes, though this adds complexity that is rarely worth the trade-off.
If you change AccessFileName, remember to update the <FilesMatch> rule in your main configuration that prevents these files from being served to browsers. The default rule only blocks files matching ^\.ht:
<FilesMatch "^\.ht">
Require all denied
</FilesMatch>
If your new file name is .myconfig, you need to add a matching rule:
<FilesMatch "^\.myconfig">
Require all denied
</FilesMatch>
Without this, your configuration file could be downloaded by anyone who guesses its name.
Verifying .htaccess Is Active
After configuring AllowOverride, you need to confirm that Apache is actually reading your .htaccess files. Here are several reliable methods to verify this.
Method 1: A Simple Redirect Test
Create an .htaccess file in your document root with a straightforward redirect:
Redirect 301 /htaccess-test https://www.example.com
Now visit http://localhost/htaccess-test in your browser. If you are redirected to https://www.example.com, .htaccess is working. If you get a 404 error instead, Apache is not reading the file.
After confirming, remove the test directive to keep your configuration clean.
Method 2: Intentional Syntax Error
A quick and definitive test is to place an intentionally invalid directive in your .htaccess file:
ThisIsNotAValidDirective
Save the file and visit any page on your site. If .htaccess is being processed, you will see a 500 Internal Server Error because Apache encounters the invalid directive and cannot continue. If the page loads normally, Apache is ignoring the file entirely.
Remember to remove the invalid directive immediately after testing. Leaving it in place will make your entire site return 500 errors for every request.
Method 3: Check Apache Error Logs
Apache logs .htaccess-related errors to its error log. The log location depends on your system:
- Ubuntu/Debian:
/var/log/apache2/error.log - CentOS/RHEL:
/var/log/httpd/error_log - macOS (Homebrew):
/usr/local/var/log/httpd/error_log
You can monitor the log in real time while testing:
sudo tail -f /var/log/apache2/error.log
If you place the intentional syntax error from Method 2 and then request a page, you should see an error message like:
[core:alert] [pid 12345] /var/www/html/.htaccess: Invalid command 'ThisIsNotAValidDirective'
If nothing appears in the log when you request a page, and the page loads normally, it confirms that Apache is not reading the .htaccess file.
Method 4: Check the Configuration with apachectl
Before restarting Apache after a main configuration change, you can validate the syntax of the entire server configuration:
sudo apachectl configtest
If the output says Syntax OK, your main configuration files are valid. Note that this command only checks the main configuration files, not .htaccess files. .htaccess syntax errors are only caught at request time.
Common Reasons .htaccess Is Not Working
If your verification tests show that .htaccess is being ignored, check the following:
-
AllowOverrideis set toNone. This is the most common cause. Find the<Directory>block for your document root and change it toAllowOverride All. -
Wrong
<Directory>block. YourAllowOverride Allmight be inside a<Directory>block that does not match your actual document root. Make sure the path matches exactly. -
Apache was not restarted. Changes to
AllowOverridein the main config require a restart:sudo systemctl restart apache2 -
File name is wrong. The file must be named exactly
.htaccess(unless you changedAccessFileName). Watch out for typos likehtaccess(missing the dot),.htaccess.txt(extra extension), or hidden characters from copy-pasting. -
File encoding issues. The file should be saved as UTF-8 without BOM, with Unix-style line endings (LF). Windows-style line endings (CRLF) can occasionally cause problems.
-
File permissions. Apache must be able to read the file. On Linux,
chmod 644 .htaccessensures the web server process can read it.
Common Hosting Scenarios
The way .htaccess is configured varies significantly depending on your hosting environment. Here is what to expect in the most common scenarios.
Shared Hosting
On shared hosting, .htaccess is almost always enabled by default with AllowOverride All or at least AllowOverride FileInfo AuthConfig Options. This is because shared hosting providers do not give customers access to the main Apache configuration, so .htaccess is the only mechanism available for per-site customization.
In most shared hosting environments:
- You cannot edit
httpd.confor virtual host files. - You cannot change the
AllowOverridesetting. - You can place
.htaccessfiles in your web root and any subdirectory. - You typically access your files via FTP, SFTP, or a web-based file manager in a control panel like cPanel or Plesk.
If your .htaccess rules are not working on shared hosting, contact your hosting provider's support to confirm that AllowOverride is enabled and that the specific modules you need (like mod_rewrite) are active. Most providers enable the commonly needed modules, but some budget hosts may restrict certain features.
On shared hosting, if you cannot see the .htaccess file in your file manager, look for a setting to "show hidden files" or "show dotfiles." Many file managers hide files starting with a dot by default.
VPS and Dedicated Servers
On a Virtual Private Server (VPS) or a dedicated server, you have full root access to the machine. This means you can edit the main Apache configuration directly and choose exactly how you want to handle .htaccess.
You have two main approaches:
Approach 1: Enable .htaccess (convenience)
Set AllowOverride All in your virtual host configuration and use .htaccess files as needed. This is a good approach if you run multiple sites or applications that expect .htaccess support (like WordPress or other CMS platforms).
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Approach 2: Disable .htaccess (performance)
Set AllowOverride None and place all directives directly in the <Directory> block. This eliminates the per-request overhead of .htaccess file lookups and centralizes your configuration.
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride None
Require all granted
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
ErrorDocument 404 /errors/404.html
</Directory>
</VirtualHost>
After any change to the virtual host file, restart Apache:
sudo systemctl restart apache2
Many administrators use a hybrid approach: they develop and test rules in .htaccess for immediate feedback, then migrate the finalized rules into the virtual host configuration before going to production.
Local Development
In local development environments, whether you installed Apache directly or are using a stack like XAMPP, WampServer, or MAMP, the default AllowOverride setting varies:
- XAMPP: Typically ships with
AllowOverride Allenabled..htaccessworks out of the box. - WampServer: Usually enables
AllowOverride Allby default, but older versions may need manual configuration. - MAMP: Generally enables
.htaccesssupport by default. - Manual Apache install on Ubuntu/Debian: The default
AllowOverrideis often set toNonefor the web root. You need to change it manually. - Manual Apache install on CentOS/RHEL: Similar to Debian, the default may be
Noneand requires manual adjustment.
For a manual installation on Ubuntu/Debian, the AllowOverride setting for the default document root is typically found in /etc/apache2/apache2.conf:
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None # ← Change this to All
Require all granted
</Directory>
Change None to All, save the file, and restart Apache:
sudo systemctl restart apache2
For local development, always using AllowOverride All is the pragmatic choice. The performance difference is negligible on a machine serving only your own requests, and the instant feedback loop of .htaccess makes development faster and more enjoyable.
Always make a backup of your main configuration file before editing it. A single typo can prevent Apache from starting at all:
sudo cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf.bak
If something goes wrong, you can restore the backup and get Apache running again immediately.