Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automation of Dynamic Virtual Host in Apache httpd-vhosts.conf and .htacces (XAMPP)

I am trying to set up some automation on my local dev machine. Normally I start all my projects like this

Open Hosts file, set up a DNS entry like 127.0.0.1 example.com www.example.com Open httpd-vhosts.conf file and add an entry, something like this below

<VirtualHost *>
    DocumentRoot "/path/to/xampp/htdocs/example.com"
    ServerName example.com
    ServerAlias www.example.com
</VirtualHost>

What I am trying to achieve is to set up the environment in such a way that, I shouldn't have add this entry in my httpd-vhosts.conf every time I want to work on a new host.

Rather I would like to have one global entry in httpd-vhosts.conf that can handle all the domains and map them to their respective directories

so if I have a list of records in my hosts file like this

127.0.0.1 example.com
127.0.0.1 mysite.com
127.0.0.1 google.com
127.0.0.1 abc.com

and a folder structure like this

/htdocs/
    /example.com/
    /mysite.com/
    /google.com/
    /abc.com/

It should automatically map to those directories without the need of adding the VirtualHost record in the httpd-vhosts.conf file.

I can guess that this can be achieved by adding a wildcard entry in httpd-vhosts.conf (I don't know how) and then adding some redirect rules in .htaccess file placed in /htdocs/ to map them to their directories.

So eventually,

  1. How to set up a wildcard entry in httpd-vhosts.conf
  2. How to set up exact rewrite rules in .htaccess file in /htdocs/

This is something that I thought of, there might also be a better way to do this.

like image 312
Atif Avatar asked Jan 14 '23 00:01

Atif


2 Answers

1. How to set up a wildcard entry in httpd-vhosts.conf

By placing an asterix (*) in front of the domain name, where you'd normally place www

<VirtualHost *>
    DocumentRoot "/path/to/xampp/htdocs/example.com"
    ServerName example.com

    ServerAlias *.example.com

</VirtualHost>

2. How to set up exact rewrite rules in .htaccess file in /htdocs/

RewriteEngine On
#RewriteCond %{HTTP_HOST} ^!example.com #(optional) do not redirect base domain
RewriteCond %{HTTP_HOST} (?(?=[a-z0-9\-\_]+\.[a-z0-9\-\_]{2,}$).+|[a-z0-9\-\_]+\.[a-z0-9\-\_]{2,})$
RewriteRule ^$ http://localhost/%0

All those domains:

www.example.com
img.example.com
cdn.example.com
static.img.example.com

will be redirected to /example.com.

Explanation

What the above does, essentially, is it takes the last two strings separated by a perdiod and redirects you to the newly found folder.


From a technical point of view:

This regex uses if then|else pattern. If 1 is found, then do 2 else do 3.

Do a test and then proceed with one of two options depending on the result of the text (?(?=[a-z0-9-_]+.[a-z0-9-_]{2,}$).+|[a-z0-9-_]+.[a-z0-9-_]{2,}$)

  1. (IF) Assert that the regex below can be matched, starting at this position (positive lookahead) (?=[a-z0-9\-\_]+\.[a-z0-9\-\_]{2,}$)
    • Match a single character present in the list below [a-z0-9\-\_]+
      • Between one and unlimited times, as many times as possible, giving back as needed (greedy) +
      • A character in the range between “a” and “z” a-z
      • A character in the range between “0” and “9” 0-9
      • A - character \-
      • A _ character \_
    • Match the character “.” literally \.
    • Match a single character present in the list below [a-z0-9\-\_]{2,}
      • Between 2 and unlimited times, as many times as possible, giving back as needed (greedy) {2,}
      • A character in the range between “a” and “z” a-z
      • A character in the range between “0” and “9” 0-9
      • A - character \-
      • A _ character \_
    • Assert position at the end of the string (or before the line break at the end of the string, if any) $
  2. (THEN) If the test succeeded, match the regular expression below .+
    • Match any single character that is not a line break character .+
    • Between one and unlimited times, as many times as possible, giving back as needed (greedy) +
  3. (ELSE) If the test failed, match the regular expression below if the test succeeded [a-z0-9\-\_]+\.[a-z0-9\-\_]{2,}$
    • Match a single character present in the list below [a-z0-9\-\_]+
    • Between one and unlimited times, as many times as possible, giving back as needed (greedy) +
    • A character in the range between “a” and “z” a-z
    • A character in the range between “0” and “9” 0-9
    • A - character \-
    • A _ character \_
    • Match the character “.” literally \.
    • Match a single character present in the list below [a-z0-9\-\_]{2,}
    • Between 2 and unlimited times, as many times as possible, giving back as needed (greedy) {2,}
    • A character in the range between “a” and “z” a-z
    • A character in the range between “0” and “9” 0-9
    • A - character \-
    • A _ character \_
  4. Assert position at the end of the string (or before the line break at the end of the string, if any) $

Test suite:

a.bc
ab.cd
abc.def
ab.cd.ef
12.34
12.34.56
1.2.3.4.5.67
cnn.com
no_country.for.old.men
like image 55
Unamata Sanatarai Avatar answered Jan 30 '23 20:01

Unamata Sanatarai


You have several ways to manage this task. There is even a special documentation page on apache httpd website for this.

This lead to several methods:

  • mod_rewrite (dedicated page), the swiss knife, but in my humble opinion this leads to seme cryptic syntax and strange behaviors
  • mod_vhost_alias, certainly the simpliest way to set simple virtualhosts (as simple asthe ones you usually use)

And for more complex vistualhosts you should check mod_macro, a great module. with this module you could write templates of virtualhosts with several parameters (not only domain and document root, any variable thing you could think about), and then simply add one line calling this macro with all the parameters for each virtualhost.

like image 32
regilero Avatar answered Jan 30 '23 20:01

regilero