Tutorial: Using environmental variables in Apache

Started by jetboy, February 03, 2012, 12:43:17 PM

Previous topic - Next topic

jetboy

I alluded to this techique in another thread, but I've written it up for those who have shell access to their servers.

Using environmental variables in Apache

Scenario:

  • We want to run the same websites on Windows using a local Apache install, a Linux development server and a Linux live web server without using multiple VirtualHost configurations.
  • We want to make PHP aware of the server and environment it's running on, so we can intelligently manage features like caching, that may only be applicable to particular environments.
  • We want to be able to easily override any settings for testing purposes.
  • We want to be able to include the individual VirtualHost configurations in SVN so they can be version controlled.

Solution:
Setting a series of environmental variables that document the differences between the various environments. These are:

VHOST_CANONICAL
VHOST_ENVIRONMENT
VHOST_SERVER

VHOST_LABEL_SUBDOMAIN
VHOST_LABEL_WWW
VHOST_PATH_DELIMITER
VHOST_PATH_DOCUMENT
VHOST_PATH_LOG
VHOST_PATH_TEMPLATE
VHOST_PORT_HTTP
VHOST_PORT_HTTPS

In Windows, environmental variables are set in My Computer > Properties > Advanced > Environmental Variables > System variables. Restart after setting them. In Ubuntu Server, environmental variables for Apache are set in /etc/apache2/envvars. On both operating systems, VirtualHost-specific variables can be set within the individual VirtualHost containers. Of the above variables, this applies to VHOST_CANONICAL and VHOST_PATH_TEMPLATE.


Windows variables for 'local' environment:

VHOST_ENVIRONMENT local
VHOST_SERVER localhost
VHOST_LABEL_SUBDOMAIN local.
VHOST_LABEL_WWW local.
VHOST_PATH_DELIMITER ;
VHOST_PATH_DOCUMENT D:/srv/www
VHOST_PATH_LOG D:/var/log
VHOST_PORT_HTTP 80
VHOST_POST_HTTPS 443



/etc/apache2/envvars additions for 'dev' environment, on server 'viper':

export VHOST_ENVIRONMENT=dev
export VHOST_SERVER=viper
export VHOST_LABEL_SUBDOMAIN=dev.
export VHOST_LABEL_WWW=dev.
export VHOST_PATH_DELIMITER=:
export VHOST_PATH_DOCUMENT=/srv/www
export VHOST_PATH_LOG=/var/log
export VHOST_PORT_HTTP=80
export VHOST_POST_HTTPS=443



/etc/apache2/envvars additions for 'www' environment, on server 'iceman':

export VHOST_ENVIRONMENT=www
export VHOST_SERVER=iceman
export VHOST_LABEL_SUBDOMAIN=
export VHOST_LABEL_WWW=www.
export VHOST_PATH_DELIMITER=:
export VHOST_PATH_DOCUMENT=/srv/www
export VHOST_PATH_LOG=/var/log
export VHOST_PORT_HTTP=80
export VHOST_POST_HTTPS=443




Example VirtualHost utilising environmental variables:

<VirtualHost *:${VHOST_HTTP_PORT}>

# Setting VirtualHost-specific variables which can be read in PHP with $_SERVER['VHOST_CANONICAL'] and $_SERVER['VHOST_PATH_TEMPLATE']
# These can't be 'reused' wihin the VirtualHost container
SetEnv VHOST_CANONICAL www.mysite.co.uk
SetEnv VHOST_PATH_TEMPLATE ${VHOST_PATH_DOCUMENT}/www.mysite.co.uk/inc/v

# Variables set at server level need to be passed through Apache to PHP
# These can be read in PHP with $_SERVER['VHOST_ENVIRONMENT'] and $_SERVER['VHOST_SERVER']
PassEnv VHOST_ENVIRONMENT
PassEnv VHOST_SERVER

ServerName ${VHOST_LABEL_WWW}mysite.co.uk

DocumentRoot ${VHOST_PATH_DOCUMENT}/www.mysite.co.uk/htdocs
<Directory ${VHOST_PATH_DOCUMENT}/www.mysite.co.uk/htdocs/>
Options FollowSymLinks
AllowOverride None
Order Allow,Deny
Allow from all
</Directory>

# This will translate as D:/srv/www/www.mysite.co.uk/inc/m;D:/srv/www/www.mysite.co.uk/inc/v;D:/srv/www/www.mysite.co.uk/inc/c on Windows
# This will translate as /srv/www/www.mysite.co.uk/inc/m:/srv/www/www.mysite.co.uk/inc/v:/srv/www/www.mysite.co.uk/inc/c on Linux
php_value include_path ${VHOST_PATH_DOCUMENT}/www.mysite.co.uk/inc/m${VHOST_PATH_DELIMITER}${VHOST_PATH_DOCUMENT}/www.mysite.co.uk/inc/v${VHOST_PATH_DELIMITER}${VHOST_PATH_DOCUMENT}/www.mysite.co.uk/inc/c

# Log file will translate to D:/var/log/apache2/local.mysite.co.uk.localhost.access.log on 'local' localhost
# Log file will translate to /var/log/apache2/dev.mysite.co.uk.viper.access.log on 'dev' viper
# Log file will translate to /var/log/apache2/www.mysite.co.uk.iceman.access.log on 'www' iceman
# This naming convention becomes useful when parsing logs with multiple dev or www servers
ErrorLog ${VHOST_PATH_LOG}/apache2/${VHOST_LABEL_WWW}mysite.co.uk.${VHOST_SERVER}.error.log
CustomLog ${VHOST_PATH_LOG}/apache2/${VHOST_LABEL_WWW}mysite.co.uk.${VHOST_SERVER}.access.log combined

</VirtualHost>




Making Apache use the individual VirtualHosts files on Linux:

Create a symlink from where Apache normally gets this information to where you're now storing it. E.g.:

sudo ln -s /srv/www/www.mysite.co.uk/conf/vhost.conf /etc/apache2/sites-available/www.mysite.co.uk.conf



Making Apache use the individual VirtualHosts files on Windows:

Create an include files that in turn references to individual VirtualHost files. E.g.:

In C:\Program Files\Apache Software Foundation\Apache2.2\conf\httpd.conf add:

# local
NameVirtualHost *:80
Include D:/srv/apache/vhosts.conf


In D:/srv/apache/vhosts.conf add:

Include D:/srv/www/www.mysite.co.uk/conf/vhost.conf



Notes:

  • VHOST_CANONICAL allows us to verify whether the site is being accessing under its canonical URL, or an alias if VirtualAliases are used
  • For sites that use 'www.' use VHOST_LABEL_WWW, so the three domains we access could be local.mysite.co.uk, dev.mysite.co.uk and www.mysite.co.uk
  • For sites than use another subdomain, use VHOST_LABEL_SUBDOMAIN, so the three domains we access could be local.admin.mysite.co.uk, dev.admin.mysite.co.uk and admin.mysite.co.uk
  • Specifying the ports as variables allows quick changes of multiple sites if we're using a proxy or load balancer on the same physical server as Apache

ukgimp

Thanks Rowan

Looks like a lo to go through, however with the list you have done it could well be quite efficient. On the odd occasions when I have systemised something I praise myself when I have to reinstall.


4Eyes

cheers Rowan

That will come in useful for me I am sure

ergophobe

Hmmm... I'll have to play around with some of this. For years, I ran my dev setup so that the site i was working on had a .loc domain. So if I'm working on example.com, example.loc is the version on my local server.

For some reason, in the past year or so I have been unable to get virtual hosts to work on Windows (XP and Vista, two totally separate machines). I haven't put much time into it, but have been wondering if it's my environment or Apache that's changed.

Maybe this will motivate me to start troubleshooting this - it's a PITA to have run everything on my dev machine as localhost and keep repointing DocumentRoot depending on what I'm working on.

ukgimp

ergophobe, I use WAMP

Really easy, you set up vhosts in the httpd.conf files and set a permission change as wamp is pretty secure.

Then stuff your hosts file.

Really easy, I have multiple sites served locally when I want.

http://somedesvsite/


ergophobe

Yep, that worked for me for years, but lately something is borked.

I've tried uninstalling and reinstalling both WAMP and XAMPP and there is something stopping vhosts from working right. I've set this up dozens on times on many different machines, but at some point it stopped working on both my machines and I have not been able to get it fixed. If you look at the WAMP and XAMPP forums, you'll find some other people having similar problems.

There's some environment conflict that I just haven't tracked down.