How can I implement a global RewriteCond / RewriteRule in Apache that applies to all virtual hosts?

StackOverflow https://stackoverflow.com/questions/344588

  •  19-08-2019
  •  | 
  •  

Question

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!

Was it helpful?

Solution

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)

OTHER TIPS

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

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.

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.

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>

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..

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top