Fix Apache mod_rewrite Not Working
The Symptom
You have rewrite rules in your .htaccess or Apache configuration, but URLs are not being rewritten. Requests either return 404, hit the wrong handler, or the rules are silently ignored.
For example, this rule should rewrite /about to /about.html:
RewriteEngine On
RewriteRule ^about$ about.html [L]
But visiting /about returns a 404 instead of serving about.html.
Root Cause
mod_rewrite failures usually come from one of these issues:
- The
mod_rewritemodule is not loaded. AllowOverrideis set toNone, so.htaccessfiles are completely ignored.RewriteEngine Onis missing in the current context.- The rewrite rule pattern does not match due to leading slashes or incorrect regex.
- The rules are in
.htaccessbut the directory configuration blocks override processing.
Step-by-Step Fix
1. Verify mod_rewrite is loaded
# Debian/Ubuntu
apache2ctl -M | grep rewrite
# RHEL/CentOS
httpd -M | grep rewrite
If there is no output, enable the module:
# Debian/Ubuntu
sudo a2enmod rewrite
sudo systemctl restart apache2
# RHEL/CentOS - add to httpd.conf
echo "LoadModule rewrite_module modules/mod_rewrite.so" | sudo tee -a /etc/httpd/conf.modules.d/00-rewrite.conf
sudo systemctl restart httpd
2. Check AllowOverride
If your rules are in .htaccess, the directory must allow overrides. Open your virtual host config:
sudo nano /etc/apache2/sites-available/000-default.conf
Find the <Directory> block for your document root and set AllowOverride:
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
AllowOverride None is the most common reason .htaccess rules are silently ignored. After changing this, restart Apache:
sudo systemctl restart apache2
3. Verify .htaccess is being read
Create a deliberately broken .htaccess to test:
echo "INVALID_DIRECTIVE" > /var/www/html/.htaccess
Visit the site. If you get a 500 Internal Server Error, Apache is reading the file. If the site loads normally, .htaccess is being ignored (go back to step 2).
Remove the test line after verifying:
rm /var/www/html/.htaccess
4. Fix common rule mistakes
Rules in .htaccess do NOT include a leading slash. Rules in a <VirtualHost> or <Directory> block DO include the leading slash:
# In .htaccess - NO leading slash
RewriteRule ^about$ /about.html [L]
# In VirtualHost config - leading slash
RewriteRule ^/about$ /about.html [L]
Always include RewriteEngine On before any rules:
RewriteEngine On
RewriteBase /
RewriteRule ^about$ about.html [L]
5. Enable rewrite logging for debugging
Add to your virtual host configuration:
LogLevel alert rewrite:trace6
Then check the error log:
sudo tail -f /var/log/apache2/error.log
The trace output shows exactly how each rule is evaluated and why it matches or fails. Disable trace logging after debugging as it generates significant output.
6. Test the configuration
sudo apache2ctl configtest
sudo systemctl reload apache2
curl -I http://localhost/about
Prevention Tips
- Prefer configuration files over
.htaccess. Rules in the virtual host config are more performant because Apache does not need to check for.htaccessfiles on every request. - Use
RewriteLogduring development. Always test rules with trace logging before deploying to production. - Test rules with
curl -Iorcurl -v. Check response headers and status codes to verify rewrites are working as expected. - Document your rewrite rules. Add comments explaining what each rule does and why, especially for complex regex patterns.
Was this article helpful?
Senior Kubernetes Architect
10+ years orchestrating containers in production. Battle-tested opinions on everything from pod scheduling to service mesh. I've seen clusters burn and helped rebuild them better.
Related Articles
Apache 500 Internal Server Error: Diagnosing .htaccess Syntax Failures And Module Conflicts Step By Step
If you've been running web infrastructure long enough, you know the 500 Internal Server Error is Apache's way of saying "something's broken, and I'm not go...
Apache 403 Forbidden Error After Directory Permissions Fix: Troubleshooting SELinux And File Contexts
You've just spent an hour wrestling with Apache file permissions, carefully setting ownership to `apache:apache` and permissions to `755` on your directori...
Apache 301 Redirect Loop: Diagnosing And Fixing Infinite Redirect Chains In VirtualHost And .htaccess Configurations
Few things are more frustrating than deploying what you think is a clean redirect configuration, only to have your browser throw an `ERR_TOO_MANY_REDIRECTS...
Apache 413 Request Entity Too Large: Fixing File Upload Failures With LimitRequestBody And PHP Configuration
The 413 error means Apache is rejecting your upload before it even hits PHP. Here's exactly what to change and where. Two layers can block large uploads: 1...
Fix Apache 'AH00558: Could not reliably determine server's FQDN'
Resolve the Apache AH00558 warning about not being able to determine the server's fully qualified domain name by setting ServerName correctly.
Apache Mod_status Real-Time Server Monitoring With Grafana And Prometheus Integration
Monitoring Apache without proper observability tooling is like flying blind. You might catch a problem after your users start complaining, but by then, you...
More in Apache
View all →Apache Mod_security WAF Rules For OWASP Top 10 Protection
If you're running Apache in production without a Web Application Firewall, you're essentially leaving your front door unlocked. mod_security is the industr...
Apache Performance Tuning: MPM, KeepAlive, and Caching
Tune Apache performance by choosing the right MPM, configuring KeepAlive correctly, and enabling mod_cache for significant throughput gains.
Apache as a Reverse Proxy: mod_proxy Configuration Guide
Configure Apache as a reverse proxy using mod_proxy to route traffic to backend applications with load balancing and health checks.
Apache SSL/TLS Hardening: Get an A+ on SSL Labs
Harden Apache SSL/TLS configuration to achieve an A+ rating on Qualys SSL Labs with modern cipher suites and security headers.