22

The title pretty much says it all. :-) I have lots of virtual hosts and I want to put a single rewriting block at the top of the httpd.conf file that rewrites URLs no matter which virtual host the request might be directed to. How the heck do I do this?

I found this but my question is the same: how can I do this without resorting to .htaccess files and performing some other action for each virtual host?

OMGTIA!

hourback
  • 1,150
  • 4
  • 12
  • 27

8 Answers8

15

Specify RewriteOptions InheritDown in the parent scope (such as httpd.conf) to get your rules applied in child Virtual Hosts without modifing them.

This will only work on Virtual Hosts where the RewriteEngine directive is set to on:

Note that rewrite configurations are not inherited by virtual hosts. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use rewrite rules.

(source)

Apache supports this since 2.4.8 (not available at the time of the original question).

From documentation for RewriteOptions:

InheritDown

If this option is enabled, all child configurations will inherit the configuration of the current configuration. It is equivalent to specifying RewriteOptions Inherit in all child configurations. See the Inherit option for more details on how the parent-child relationships are handled. Available in Apache HTTP Server 2.4.8 and later.

InheritDownBefore

Like InheritDown above, but the rules from the current scope are applied before rules specified in any child's scope. Available in Apache HTTP Server 2.4.8 and later.

IgnoreInherit

This option forces the current and child configurations to ignore all rules that would be inherited from a parent specifying InheritDown or InheritDownBefore. Available in Apache HTTP Server 2.4.8 and later.

(http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteoptions)

That Brazilian Guy
  • 3,328
  • 5
  • 31
  • 49
Matej Snoha
  • 497
  • 6
  • 10
  • 2
    Note that this still requires `RewriteEngine On` set within the Virtual Host section. – brocksamson Nov 30 '15 at 17:24
  • 2
    "Note that rewrite configurations are not inherited by virtual hosts. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use rewrite rules." https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html – Frederick Nord Feb 02 '17 at 21:25
  • Also note, I am using Apache/2.4.25 (Debian) and InheritDown still works. BUT you need `RewriteEngine On` in each virtual host. Not sure why it says 2.4.8. I am using GCE with Apache (2.4.25) Debian Stretch. It also says this is latest version when I try to update. – Maciek Semik Feb 06 '20 at 22:35
  • @MaciekSemik 8 < 25 – MrWhite May 19 '23 at 22:12
12

By default, mod_rewrite configuration settings from the main server context are not inherited by virtual hosts. To make the main server settings apply to virtual hosts, you must place the following directives in each <VirtualHost> section:

RewriteEngine On
RewriteOptions Inherit 

click http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html to find more information

Zava
  • 743
  • 6
  • 17
10

Looks like the simplest possible solution is to add

RewriteOptions inherit

to each VirtualHost directive. This is at least a lot simpler than messing with .htaccess files. Apache is pretty clear on the fact that

by default, rewrite configurations are not inherited. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use it. (http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html)

and apparently the way to change the default is via RewriteOptions in the child (vhost or director), so you have to do something in each child.

Travis Wilson
  • 949
  • 9
  • 19
  • 2
    Since Apache 2.4.8 you can use httpd.conf (or others) with `RewriteOptions InheritDown`, it is equivalent to specifying `RewriteOptions Inherit` in all vhosts. – Matej Snoha Dec 06 '14 at 22:57
  • @MatejSnoha , do you want to submit your comment as a solution to the question? It might become more visible to others looking for a solution to this problem. I'm not in the position to test this myself, but I'd be interested to know if it helps others. – hourback May 11 '15 at 01:13
6

I've never tested it, so it might not work, but I would try adding an include directive in all of the virtual host blocks to a single file. You would have to change each virtual host configuration block once, but after that, you should have a central place from which to make changes. YMMV.

Jeremy Bourque
  • 3,533
  • 1
  • 21
  • 18
  • The best answer for me :) as it is not restricted to mod_rewrite, but works with any Apache feature/directive. – CedX Oct 07 '13 at 18:42
2

If you're only trying to rewrite something in the domain part of the name, e.g. to fix a common misspelling, you don't even need the 'inherit' option. I setup a no-name virtual host to catch all invalid host names and respell them correctly before redirecting them.

Since this uses redirects, the appropriate virtual host will be found after the rewrites have been applied.

Options +Indexes +FollowSymLinks
RewriteEngine on
# If it begins with only domain.com, prepend www and send to www.domain.com
RewriteCond %{HTTP_HOST} ^domain [NC]
RewriteRule ^(.*) http://www.domain.com$1 [L,R=301]

# Correct misspelling in the domain name, applies to any VirtualHost in the domain
# Requires a subdomain, i.e. (serviceXXX.)domain.com, or the prepended www. from above
RewriteCond %{HTTP_HOST} ^([^.]+\.)dommmmmain\.com\.?(:[0-9]*)?$ [NC]
RewriteRule ^(.*) %{HTTP_HOST}$1 [C]
RewriteRule ^([^.]+\.)?domain.com(.*) http://$1domain.com$2 [L,R=301]

# No-name virtual host to catch all invalid hostnames and mod_rewrite and redirect them
<VirtualHost *>
    RewriteEngine on
    RewriteOptions inherit
</VirtualHost>
Chad A. Davis
  • 321
  • 1
  • 3
  • I thought you said you didn't even need the "inherit" option, yet you include it in your rule – huyz Jun 12 '11 at 04:59
  • We use this to fix the spelling of our domain name. In that case, it's sufficient to have 'inherit' only for the wildcard VirtualHost. If you have more more complex rewrite options, then you may need to include 'inherit' in each VirtualHost. – Chad A. Davis Jun 15 '11 at 15:09
  • Ah, so you meant that you don't need the 'inherit' option in every virtualhost. Got it. – huyz Jun 18 '11 at 15:17
  • "Note that rewrite configurations are not inherited by virtual hosts. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use rewrite rules." https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html – Frederick Nord Feb 02 '17 at 21:25
1

You may want to use InheritDownBefore to avoid having to add more junk to your vhosts.

An example of a global letsencrypt alias:

# letsencrypt
<IfModule alias_module>
    Alias /.well-known/ /var/www/html/.well-known/
</IfModule>
<IfModule mod_rewrite.c>
    # prevent vhost rewrites from killing the alias
    RewriteEngine On
    RewriteOptions InheritDownBefore
    RewriteCond %{REQUEST_URI} ^/\.well\-known
    RewriteRule . - [L,PT]
</IfModule>

Then you can do this in each of your vhosts, with no other directives:

<VirtualHost *:80>
    ....
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule ^/.*            /index.php [L,PT]
    </IfModule>
</VirtualHost>
nyet
  • 482
  • 2
  • 13
1

Thanks to everyone to answered above. It helped me find my answer.

Question has been answered already, I just wanted to add an example in case you are using Google Compute Engine. It says it requires Apache HTTP Server 2.4.8 BUT it works with Apache/2.4.25 (Debian). Even when I try to upgrade, I cannot go past Apache/2.4.25. It says this version is the latest version.

Here's an example of how to implement.

RewriteOptions InheritDown
RewriteCond %{HTTP_HOST} ^www\. [NC,OR]
RewriteCond %{HTTP_HOST} !\.co$ [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)\.[^.]+$ [NC]
RewriteRule ^ https://%1.co%{REQUEST_URI} [L,NE,R=301]
<VirtualHost *:80>
 RewriteEngine On
 ServerAlias *.*
</VirtualHost>

ALSO OF NOTE (For Testing):

When you are testing your rewrite engine. It is really easy to get confused about if it is working or not because of cache and cookies. If you got it to work once on a browser, it will continue to work even if you delete the rewrite code. Testing rewrite is really annoying sometimes. You might think it works but then it stops or starts.

Best way to test rewrite code is to open an incognito tab in your browser, clear or cookies and cache. Open developer mode just in case. DO NOT JUST REFRESH. You need to click into the URL and refresh. Or open new tab. Or copy/paste URL into new window. If you use same window with refresh, it might be just redoing results from the past instead of renewing the new code.

Maciek Semik
  • 1,872
  • 23
  • 43
  • "It says it requires Apache HTTP Server 2.4.8 BUT it works with Apache/2.4.25" - Yes, that's 2.4.8 (eight), not 2.4.80 (eighty). 8 < 25. "if it is working or not because of cache" - If you are testing _redirects_ (as you are here) then it is always advisable to test first with 302 (temporary) redirects to avoid potential caching issues. – MrWhite May 19 '23 at 22:20
-1

I've always used a "catch-all" VHost for directives I wanted across the board, like......

Listen 80
NameVirtualHost *:80

<VirtualHost *:80>
ErrorLog "/var/log/apache2/error_log"
</VirtualHost>

<VirtualHost *:80>
ServerName alloftherestoftheVHosts.com
DocumentRoot "/ServiceData/.........
............ 

And it's always seemed to work... error logs were getting combined properly, etc...... but it IS possible that this was the result of an earlier / conflicting / like-minded directive.

Personal note.. Whoever dreamed up the Apache configuration schema and syntax was a dingbat, or a group of dingbats, who spent too much time in their cave.... The whole thing should be exorcised and XMLized, or something! Although they are both wildly different... the Hello-Kitty setup process of Cherokee.. to the viciously succinct NGinx config.... are both so much more logical..

Alex Gray
  • 16,007
  • 9
  • 96
  • 118