Apache virtual host based on *source* IP
I don't know if that's possible (without mod_rewrite, anyway) in Apache level.
Here's another idea. What if you set up two Apache virtual hosts and then use iptables to transparently forward visitor to correct virtual host? Something like
iptables -A PREROUTING -t nat -i eth0 -p tcp -s your.ip.address -d your.server --dport 80 -j DNAT --to-destination your.actual.site:someport
iptables -A PREROUTING -t nat -i eth0 -p tcp ! -s your.ip.address -d your.server --dport 80 -j DNAT --to-destination your.holding.site:someport
Or something similar. :)
It wouldn't really be a different virtual host. But using something like mod_rewrite or mod_alias you can serve content out of any folder for which you have set the appropriate permissions. There's only one docroot, but you can effectively change that on the fly.
One way to do it might be:
<VirtualHost *.80>
ServerName example.com
...
DocumentRoot "/path/to/root"
<Directory "/path/to/root">
...
</Directory>
<Directory "/path/to/not/root">
Order allow,deny
#replace with your IP
Allow from 192.168.0.100
...
</Directory>
RewriteEngine On
#Rewrite to alternate path if IP address matches
RewriteCond %{REMOTE_ADDR} ^192\.168\.0\.100$
RewriteRule ^/(.*)$ /path/to/not/root/$1
<VirtualHost>
Do note though that it'd probably be a bit cleaner to handle this with a dev subdomain.
Apache 2.3 or later
With Apache 2.3 or later you can apparently do something like this (tested):
<VirtualHost *:80>
ServerName www.example.com
<If "-R '10.10.10.10'">
# The next version of the website...
Alias /favicon.ico /home/ubuntu/website-new/favicon.ico
Alias /static/ /home/ubuntu/static/
WSGIScriptAlias / /home/ubuntu/website-new/main/wsgi.py
</If>
<Else>
# The standard version (e.g. holding page).
Alias /favicon.ico /home/ubuntu/website/favicon.ico
Alias /static/ /home/ubuntu/static/
WSGIScriptAlias / /home/ubuntu/website/main/wsgi.py
</Else>
# and so on...
</VirtualHost>
Apache 2.2 or earlier
Update: This is not a good solution. See below.
You have to do a hack like this. Note the [PT]
which stands for "passthrough". Without it, an actual HTTP redirect is sent back to the client, which probably isn't what you want. The [OR]
thing (which stands for "or") shows how to match multiple addresses.
Alias /next/favicon.ico /home/ubuntu/website-new/favicon.ico
Alias /next/static/ /home/ubuntu/static/
WSGIScriptAlias /next /home/ubuntu/website-new/main/wsgi.py
Alias /favicon.ico /home/ubuntu/website/favicon.ico
Alias /static/ /home/ubuntu/static/
WSGIScriptAlias / /home/ubuntu/website/main/wsgi.py
# Rewrite for our IP.
RewriteEngine On
RewriteCond %{REMOTE_ADDR} ^80\.4\.170\.209$ [OR]
RewriteCond %{REMOTE_ADDR} ^94\.193\.52\.157$
RewriteRule ^/(.*) /next/$1 [PT]
You need to enable mod_rewrite
which you can do on Debian/Ubuntu with this command:
sudo a2enmod rewrite
Note that this method doesn't completely ban other people from accessing your test site, so you will probably want to add some security, or just choose a more obscure prefix than next
.
Update on the mod_rewrite method.
There are a couple of problems with this method. First, Django does not work with two sites in the same process like this, you need to follow the instructions in this answer.
Secondly mod_rewrite does not work with POST
requests! All POST
s are silently changed to GET
and the post data is discarded. Very frustrating! Therefore I recommend you use the...
iptables version
Simply run the servers on two different ports. This one includes the WSGI stuff to have two separate django sites.
<VirtualHost *:80>
ServerName www.example.com
Alias /favicon.ico /home/ubuntu/alpha/favicon.ico
Alias /static/ /home/ubuntu/alpha/static/
WSGIDaemonProcess alpha_wsgi user=www-data group=www-data
WSGIScriptAlias / /home/ubuntu/alpha/alpha/wsgi.py
WSGIProcessGroup alpha_wsgi
ServerAdmin [email protected]
ErrorLog ${APACHE_LOG_DIR}/error.log
# Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:1222>
ServerName www.example.com
Alias /favicon.ico /home/ubuntu/main/favicon.ico
Alias /static/ /home/ubuntu/main/static/
WSGIDaemonProcess main_wsgi user=www-data group=www-data
WSGIScriptAlias / /home/ubuntu/main/main/wsgi.py
WSGIProcessGroup main_wsgi
ServerAdmin [email protected]
ErrorLog ${APACHE_LOG_DIR}/error.log
# Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Then you can use this iptables
command to route requests from your ip address on port 80 to port 1222:
sudo iptables -A PREROUTING -t nat -p tcp -s your.ip.address --dport 80 -j DNAT --to-destination :1222
Change -A
to -D
to remove the rule.
Note that the docs suggest you need to add additional Listen
and NameVirtualHost
commands, but I actually found that it works without them, and adding them made it break (at least in ubuntu).
AFAIK, the only way to do this is to symlink a location within the document root to your content outside the document root, then rewrite the request to that.