# Apache Dynamic Virtual Hosts with mod_rewrite Problem

## PhragMunkee

I am setting up a new web server using Apache 1.3.33 using dynamic virtual hosts.  Here is my VirtualHost configuration directive:

```
<VirtualHost *:80>

   UseCanonicalName off

   VirtualDocumentRoot /usr/local/webs/%2+/%1

   ErrorLog "| /usr/sbin/cronolog /usr/local/apache/logs/error_log.%Y-%m-%d.log"

   LogFormat "%V %h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\"" vcombined

   CustomLog "| /usr/sbin/cronolog /usr/local/apache/logs/access_log.%Y-%m-%d.log" vcombined

</VirtualHost>
```

I want to be able to use mod_rewrite to catch any requests that only contain something like http://domain.tld and redirect them to http://www.domain.tld.  However, if the requests are something like http://mail.domain.tld, it doesn't pre-pend the www host.  I know I can use symlinking (ln -s) to get around this problem, but I do not want to clutter the web server with extraneous directories and symlinks.

I have been able to get it working with only http://domain.tld requests that redirect to http://www.domain.tld, but requests that actually use a hostname are pre-pended with the www.  Here is the VirtualHost directive with that I have working up to this point:

```
<VirtualHost *:80>

   UseCanonicalName off

   VirtualDocumentRoot /usr/local/webs/%2+/%1

   RewriteEngine On

   RewriteCond %{HTTP_HOST}     ^(.+)\.(.+)$ [NC]

   RewriteRule ^(.*)            http://www.%{HTTP_HOST}

   ErrorLog "| /usr/sbin/cronolog /usr/local/apache/logs/error_log.%Y-%m-%d.log"

   LogFormat "%V %h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\"" vcombined

   CustomLog "| /usr/sbin/cronolog /usr/local/apache/logs/access_log.%Y-%m-%d.log" vcombined

</VirtualHost>
```

This setup also does not work with files or directories following the domain name.  Unfortunately, I am not very good with regular expressions.  I've been working on it for days and this is the closest I have been able to get.  What I have now is a bunch of guess work from other snippets I have found (but weren't designed to do what I want to do).

Does anyone have a setup similar to this that they can share or knows of a fix?

----------

## tuxmin

Try this:

   RewriteCond %{HTTP_HOST}     .*\.?domain\.tld

   RewriteCond %{HTTP_HOST}     !www\.domain\.tld

   # RewriteRule /(.*)   http://www.domain.tld/$1  [L]

 Edit --> RewriteRule /(.*)   http://www.domain.tld/$1  [R,L]

Alex!!!

----------

## PhragMunkee

 *tuxmin wrote:*   

>    RewriteCond %{HTTP_HOST}     .*\.?domain\.tld
> 
>    RewriteCond %{HTTP_HOST}     !www\.domain\.tld
> 
>    RewriteRule /(.*)   http://www.domain.tld/$1  [L]

 

How would I rewrite that to handle dynamic virtual hosts?  There are about 30 sites/domains hosted with that single VirtualHost directive.

----------

## tuxmin

Perhaps I'm not getting your point.  I thought you want to rewrite any hostname of the form

     host.domain.ltd

 -- where host ist variable or NULL (in that case the first dot is not required) -- to

www.domain.ltd

and preserve anything after the hostname. That's exactly what my rewrite rule does... (or at least should, I didn't test it...)

If you want to serve a number of domains do it this way

```

RewriteCond %{HTTP_HOST} .*\.?domain1\.tld 

RewriteCond %{HTTP_HOST} !www\.domain1\.tld 

RewriteRule /(.*) http://www.domain1.tld/$1 [R,L]

RewriteCond %{HTTP_HOST} .*\.?domain2\.tld 

RewriteCond %{HTTP_HOST} !www\.domain2\.tld 

RewriteRule /(.*) http://www.domain2.tld/$1 [R,L]

       .

       .

RewriteCond %{HTTP_HOST} .*\.?domain_n\.tld 

RewriteCond %{HTTP_HOST} !www\.domain_n\.tld 

RewriteRule /(.*) http://www.domain_n.tld/$1 [R,L]

```

Alex!!!

Edit: Be aware that literally any request to any virtual will have to pass this rewrite chain! This is normally no big deal but if you serve high loaded sites I'd advice to setup a default virtual for the rewrite rules and another one for each hostname that serves the real content.

----------

## PhragMunkee

It's definitely a tricky one to explain.

Basically, if a host.domain.tld is requested, it shouldn't be rewritten.  However, if the host part is missing, it should be rewritten to www.domain.tld.  So, it just needs to be rewritten if there is no host and left alone if there is.

And to make matters worse, I can't match it specifically on domain.tld (or anything static).  It needs to be matched on any domain at any top-level domain.

Maybe something like

If http://*.*/* (no host) then rewrite to http://www.*.*/*

But if it has http://mail.*.*/* or http://whateveryoucandreamup.*.*/* then it doesn't get rewritten.

Does that help clarify a little?

Thanks!!!  :Very Happy: 

----------

## tuxmin

If you serve only top level domains this should do the trick:

```

RewriteCond %{HTTP_HOST} ^.*\..*$

RewriteRule /(.*) http://www.%{HTTP_HOST}/$1 [R,L] 

```

Hth, Alex!!!

----------

## PhragMunkee

 *tuxmin wrote:*   

> If you serve only top level domains this should do the trick:
> 
> ```
> 
> RewriteCond %{HTTP_HOST} ^.*\..*$
> ...

 

That doesn't seem to do much at all.  Any domains with hosts work fine, but without a host, it still 404s.

----------

## tuxmin

Will you please provide me with some more detail. I can't help you much when you simply state it's not working...

What URL do you request and what does apache actually make out of it. Have a look at the access_log and the error_log. Make sure there is some content that can be served... I don't know how you setup your DocumentRoot etc.

To get some more insight you should activate the RewriteLog and watch how the URLs actually get rewritten.

Alex!!!

----------

## Pingu1979

I think maybe I can explain it a bit better as I want to do exactly the same thing...

Say you host 4 domains...

example1.com

example2.org

example3.net

example4.co.uk

What PhragMunkee wants to happen is that if someone puts http://example2.org into the address bar of their browser it rewrites the URL to http://www.example2.org ... however if someone puts in http://www.example1.com or http://mail.example3.net then it won't rewrite the URL at all...

It would also need to be able to deal with http://example4.co.uk (needs to be rewritten) and http://www.example4.co.uk or http://mail.example4.co.uk (shouldn't be rewritten)

I've tried to get this to work but I'm **** at regex!

----------

## tuxmin

Hm,

I understood it exactly the way you explained it. To put in other words: any hostname that consists of exactly 2 parts get rewritten, anything else not, right!?

So, take a look at the regexp above

```

RewriteCond %{HTTP_HOST} ^.*\..*$ 

```

What does this mean: ^  <-- anchor at beginning of the string (hostname, in out case)

                                .*  <-- followed my 0 or any number of chars

                                \.   <-- exactly *one* . (dot)

                                .*  <-- followd by 0 or any number or chars

                                 $  <-- and here it ends

OK, I admit, this is not what you want ;P The point is that .* matches the dot, which is undesireable.

Now this should work:

```

    ^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+$

```

Another option would be to count the dots...

Have to look it up...

Hth, Alex!!!

----------

## Pingu1979

I did think of counting the dots but it wouldn't work for country tld's like .co.uk as they would have 2 dots without the host and 3 dots with...

I'm beginning to think that it's just not possible to do it this way.....

----------

## tuxmin

```

RewriteCond %{HTTP_HOST} ^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+$

RewriteCond %{HTTP_HOST} ^[a-zA-Z0-9_-]+\.co\.[a-zA-Z]+$

RewriteRule /(.*) http://www.%{HTTP_HOST}/$1 [R,L] 

```

----------

## MrBlc

I have a similiar issue...

i want to have certain vhosts rewritten from http://subdomain.domain.tld to https://samesubdomain.domain.tld

i'm no wiz in regexp either...  :Rolling Eyes: 

but this is what i have managed to boil together so far, although it's not working.. 

```

                 <IfModule mod_rewrite.c>

                 RewriteEngine On

                 RewriteOptions inherit

                 RewriteCond %{HTTP_HOST}        .webmail*

                 RewriteCond %{HTTP_HOST}        !webmail\.domain\.tld

                 RewriteRule /(.*)              https://webmail.domain.tld/$1 [L,R]

                 </IfModule>

```

anyone have a better suggestion?

-MrBlc

----------

## tuxmin

If I get it right you simply want to make sure that any http request is redirected to the same URL but via https.

This is accomplished as follows:

- In the http virtual (host.domain.tld):

RedirectMatch permanent (.*)   https://host.domain.tld($1)

Hth, Alex!!!

----------

## MrBlc

Thanks for the solution.. 

i'm starting to see that there are a multitude of ways to perform this task..

i ended up with a simpler one though..

in the vhost config, i wrote:

redirect / https://host.domain.tld

it seemed to work as well, but i appreciate your answer.. makes me realize there's a LOT of ways to do this..

-blc

----------

## tuxmin

The difference between your and mine solution is that mine preserves the part behind the hostname, e.g.

```

http://host.domain.com/some/path/doc.html is mapped to

https://host.domain.com/some/path/doc.html

```

while your solution always maps to https://host.domain.com

Alex!!!

----------

## MrBlc

interesting...

thanks for clarifying that for me.  :Smile: 

-blc

----------

## guigouz

Hi, 

 First of all, your post enlightened me on how to accomplish this virtual host thing, so thanks!

 Here's the regexp that will work for you

```

RewriteEngine On

RewriteCond %{HTTP_HOST} ^[a-z0-9]+((-|_)[a-z0-9]+)*(\.[a-z0-9]{2,3}){1,2}$

RewriteRule ^(.*) http://www.%{HTTP_HOST}

```

This regexp means anything (except dots) followed by 1 or 2 sequences of a dot + 2 or 3 chars. This would catch

anything.com

anything.co.uk

But *.anything.com won't get rewrited

Hope it helped

gui

----------

