Websites & apps

Enable.htaccess and mod_rewrite in Apache

If your.htaccess rules are ignored, Apache is usually missing mod_rewrite or AllowOverride. Enable both, restart safely and prove it works with a one-line test rule.

BeginnerLinux server4 min read

Many PHP apps, WordPress included, ship an .htaccess file with rewrite rules for pretty URLs. On a fresh VPS those rules often do nothing, and every page except the home page returns 404. Two settings cause almost every case: the rewrite module is not loaded, or Apache is told to ignore .htaccess files. This guide fixes both and shows how to confirm it.

Before you start

  • Apache running on Ubuntu, Debian, AlmaLinux or Rocky Linux.
  • A working virtual host for your site. If you do not have one yet, follow Set up Apache virtual hosts.
  • A user with sudo rights.

Why.htaccess is ignored

Apache reads .htaccess files only where the AllowOverride directive allows it. The stock Ubuntu and Debian config sets AllowOverride None for /var/www/, and the RHEL-family config does the same for /var/www/html. With None, Apache never even opens the file, so even a deliberate syntax error inside it does nothing.

Separately, RewriteEngine and RewriteRule come from mod_rewrite. If the module is not loaded and AllowOverride is on, you get a 500 error instead, because Apache does not recognise the directive.

Enable mod_rewrite

Ubuntu and Debian

Bash
sudo a2enmod rewrite

The command prints a reminder to restart Apache. Do that after the next step.

AlmaLinux and Rocky Linux

The module is loaded by default from /etc/httpd/conf.modules.d/00-base.conf. Confirm it:

Bash
httpd -M | grep rewrite

You should see rewrite_module (shared). On Ubuntu and Debian the same check is apache2ctl -M | grep rewrite.

Set AllowOverride in the Directory block

Edit your site's virtual host file, for example /etc/apache2/sites-available/example.com.conf or /etc/httpd/conf.d/example.com.conf. Add or change the <Directory> block so its path matches your DocumentRoot exactly:

Apache
<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/example.com/public

    <Directory /var/www/example.com/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Points that trip people up:

  • The path must be the folder that holds the .htaccess file, or a parent of it. A block for /var/www/html does nothing for /var/www/example.com/public.
  • AllowOverride is only valid inside <Directory>. Putting it directly in <VirtualHost> gives a config error.
  • +FollowSymLinks (or +SymLinksIfOwnerMatch) must be on for rewrite rules in .htaccess to run.
  • If you do not want to allow everything, AllowOverride FileInfo is enough for rewrite rules, and you can add AuthConfig, Indexes or Limit as needed.

Note: AllowOverride All costs a little speed, because Apache looks for .htaccess in every folder on the path for each request. On a busy site you can move the rules into the vhost and set AllowOverride None. For most sites the difference is small.

Restart and test the config

Check the syntax, then restart. A restart (not just a reload) is the safe choice after enabling a module:

Bash
sudo apachectl configtest
sudo systemctl restart apache2   # Ubuntu and Debian
sudo systemctl restart httpd     # AlmaLinux and Rocky

If configtest does not print Syntax OK, fix the reported line before restarting, or Apache will not come back up.

Check it works

Create a test rule. In your document root, add a file .htaccess with:

Apache
RewriteEngine On
RewriteRule ^rewrite-test$ /index.html [L]

Now request the made-up URL:

Bash
curl -I http://example.com/rewrite-test

A 200 OK means mod_rewrite and .htaccess both work: Apache served index.html for a path that does not exist. A 404 Not Found means the .htaccess file is still being ignored. A 500 Internal Server Error means the file is read but the module is missing or a line is wrong.

Remove the test rule afterwards, or replace it with your app's real rules. For WordPress, go to Settings → Permalinks and click Save Changes so it writes its own block.

Tip: A quick way to see whether Apache reads .htaccess at all is to put a line of nonsense in it. If the site still loads normally, the file is being ignored.

Troubleshooting

  • Still 404 on every inner page: the <Directory> path does not match your DocumentRoot, or another, more specific <Directory> block sets AllowOverride None. Search for it with grep -Rn AllowOverride /etc/apache2/ (or /etc/httpd/).
  • 500 error right after adding .htaccess: read the site's error log. Invalid command 'RewriteEngine' means the module is not loaded; anything else points at a bad line. See Fix 500 Internal Server Error on Apache.
  • Options FollowSymLinks or SymLinksIfOwnerMatch is off: add +FollowSymLinks to the Options line in the <Directory> block.
  • Changes in .htaccess work locally but not on the server: the file was uploaded without the leading dot, or your FTP client hides dotfiles. Check with ls -la.
  • A control panel or Nginx sits in front: Nginx ignores .htaccess completely. If Nginx serves the site, convert the rules to Nginx syntax instead.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.