<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arricc &#187; Hosting</title>
	<atom:link href="http://www.arricc.net/tag/hosting/feed" rel="self" type="application/rss+xml" />
	<link>http://www.arricc.net</link>
	<description>50% IT snippets that I couldn&#039;t readily find existing help on. 50% drivel.</description>
	<lastBuildDate>Mon, 05 Jul 2010 23:26:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>User VHosting</title>
		<link>http://www.arricc.net/user-vhosting.php</link>
		<comments>http://www.arricc.net/user-vhosting.php#comments</comments>
		<pubDate>Tue, 29 Aug 2006 23:05:50 +0000</pubDate>
		<dc:creator>Fizzgig</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[Hosting]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Wintermute]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.arricc.net/user-vhosting.php</guid>
		<description><![CDATA[So, previously, I detailed how to do web virtual hosting to directories on the file system. This is all well and good, but I want to have users pidgeon holed into their own directories, plus I want users own websites to be stored under their own directories in a similar format to that used in [...]]]></description>
			<content:encoded><![CDATA[<p>So, <a href="/vwebhosting.php">previously</a>, I detailed how to do web virtual hosting to directories on the file system. This is all well and good, but I want to have users pidgeon holed into their own directories, plus I want users own websites to be stored under their own directories in a similar format to that used in the previous article (eg. /home/user/web/example.org/subdomain)</p>
<p>The problem lies with mapping domain names (example.org) onto user accounts (Alice? Bob?). This is where Apache and mod_rewrite come to the rescue again. On Wintermute I&#8217;ve installed Apache 2, but this recipe will work just as well with Apache 1.3.<span id="more-24"></span></p>
<p>First, we create a file with domain names to username mappings:<br />
/etc/apache2/map.hosted<br />
<div class="codeblock"><code>wintermute:/etc/apache2# cat map.hosted<br />xeno-phon.co.uk: jimsin<br />starfallonline.co.uk: stillborn<br />ryanroberts.co.uk: stillborn<br />witchhunter.co.uk: stillborn<br />flushedphoenix.co.uk: flushedphoenix<br />shawree.co.uk: shawree<br />theballswinger.co.uk: the_ball_swinger<br />the-hearse.com: hobgoth<br /></code></div><br />
The pattern is &#8220;website.com: username&#8221; with one per line.<br />
Each of these usernames must also exist in the Xoops database (or as system users), but I&#8217;ll be covering the links to that DB in a later article.</p>
<p>Coming up with that file was the easy bit. The next bit was the major pain in the hole. I searched for aaaages to try and work out how to do this in php ( my php is significantly better than my Perl), but all the examples I could find were written in Perl. So, here are some keywords for search engines: how to write a mod_rewrite map in php not perl. php apache rewritemap.</p>
<p><div class="codeblock"><code>#!/usr/bin/php<br /><span class="synSpecial">&lt;?</span><br /><span class="synComment">//Optional log file.</span><br /><span class="synComment">#$log = fopen (&quot;/tmp/rwlist&quot;,'a');</span><br /><span class="synComment">//Map file</span><br /><span class="synStatement">$</span><span class="synIdentifier">mapIn</span> <span class="synStatement">=</span> <span class="synIdentifier">fopen</span><span class="synSpecial">(</span>&quot;<span class="synConstant">/etc/apache2/map.hosted</span>&quot;, &quot;<span class="synConstant">r</span>&quot;<span class="synSpecial">)</span>;<br /><span class="synComment">//Read in the file.</span><br /><span class="synComment">//NB: This is only done at startup, so if you change the file you have to reload Apache to get the changes recognised.</span><br /><span class="synStatement">while</span> <span class="synSpecial">((</span><span class="synStatement">$</span><span class="synIdentifier">data</span> <span class="synStatement">=</span> <span class="synIdentifier">fgetcsv</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">mapIn</span>, <span class="synConstant">1000</span>, &quot;<span class="synConstant">:</span>&quot;<span class="synSpecial">))</span> <span class="synStatement">!==</span> <span class="synConstant">FALSE</span><span class="synSpecial">)</span> <span class="synSpecial">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">map</span><span class="synSpecial">[</span><span class="synStatement">$</span><span class="synIdentifier">data</span><span class="synSpecial">[</span><span class="synConstant">0</span><span class="synSpecial">]]</span> <span class="synStatement">=</span> <span class="synIdentifier">trim</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">data</span><span class="synSpecial">[</span><span class="synConstant">1</span><span class="synSpecial">])</span>;<br /><span class="synSpecial">}</span><br /><span class="synIdentifier">fclose</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">mapIn</span><span class="synSpecial">)</span>;<br /><span class="synComment">//Recursive function. Starts with the full domain name and gradually pops off segments until it finds an owner (or not).</span><br /><span class="synComment">//eg. www.sub.example.org - first checks for www.sub.example.org, then sub.example.org, then example.org and finally org.</span><br /><span class="synPreProc">function</span> checkUser<span class="synSpecial">(</span><span class="synStatement">&amp;$</span><span class="synIdentifier">url</span><span class="synSpecial">)</span><br /><span class="synSpecial">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synType">global</span> <span class="synStatement">$</span><span class="synIdentifier">map</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">uname</span> <span class="synStatement">=</span> <span class="synStatement">$</span><span class="synIdentifier">map</span><span class="synSpecial">[</span><span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">host</span>&quot;<span class="synSpecial">]]</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">if</span> <span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">uname</span> <span class="synStatement">&lt;&gt;</span> &quot;&quot;<span class="synSpecial">)</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">hostedUser</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">=</span> <span class="synStatement">$</span><span class="synIdentifier">uname</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">}</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">else</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">host</span> <span class="synStatement">=</span> <span class="synIdentifier">explode</span><span class="synSpecial">(</span>&quot;<span class="synConstant">.</span>&quot;,<span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">host</span>&quot;<span class="synSpecial">])</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">path</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">=</span> &quot;<span class="synConstant">/</span>&quot;<span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">host</span><span class="synSpecial">[</span><span class="synConstant">0</span><span class="synSpecial">]</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">path</span>&quot;<span class="synSpecial">]</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synIdentifier">unset</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">host</span><span class="synSpecial">[</span><span class="synConstant">0</span><span class="synSpecial">])</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">host</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">=</span> <span class="synIdentifier">implode</span><span class="synSpecial">(</span>&quot;<span class="synConstant">.</span>&quot;,<span class="synStatement">$</span><span class="synIdentifier">host</span><span class="synSpecial">)</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">if</span> <span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">host</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">&lt;&gt;</span> &quot;&quot;<span class="synSpecial">)</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkUser<span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">)</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">}</span><br /><span class="synSpecial">}</span><br /><span class="synStatement">do</span><br /><span class="synSpecial">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">in</span> <span class="synStatement">=</span> <span class="synIdentifier">trim</span><span class="synSpecial">(</span><span class="synIdentifier">fgets</span><span class="synSpecial">(</span>STDIN,<span class="synConstant">8096</span><span class="synSpecial">))</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">if</span> <span class="synSpecial">(</span><span class="synIdentifier">strlen</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">in</span><span class="synSpecial">)</span> <span class="synStatement">&gt;</span><span class="synConstant">0</span><span class="synSpecial">)</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">{</span><br /><span class="synComment">//Log request</span><br /><span class="synComment">#&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  fputs($log, &quot;$in\n&quot;);</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synIdentifier">unset</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">hostedUser</span>&quot;<span class="synSpecial">])</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">if</span> <span class="synSpecial">(</span><span class="synIdentifier">substr</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">in</span>,<span class="synConstant">0</span>,<span class="synConstant">1</span><span class="synSpecial">)</span> <span class="synStatement">&lt;&gt;</span> &quot;<span class="synConstant">/</span>&quot;<span class="synSpecial">)</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">in</span> <span class="synStatement">=</span> &quot;<span class="synConstant">http://</span><span class="synStatement">$</span><span class="synIdentifier">in</span>&quot;;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">url</span> <span class="synStatement">=</span> <span class="synIdentifier">parse_url</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">in</span><span class="synSpecial">)</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">path</span> <span class="synStatement">=</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">path</span>&quot;<span class="synSpecial">]</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">path</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">=</span> &quot;&quot;;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkUser<span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">)</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">}</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synComment">//If we find an owner</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">if</span><span class="synSpecial">(</span><span class="synIdentifier">isset</span><span class="synSpecial">(</span><span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">hostedUser</span>&quot;<span class="synSpecial">]))</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synComment">//This bit is slightly legacy before I moved the hosting files about a bit. Kept for posterity mainly.</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">out</span> <span class="synStatement">=</span> &quot;<span class="synConstant">/home/</span>&quot; <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">hostedUser</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span>&quot;<span class="synConstant">/web/</span>&quot; <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">hostedUser</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span> &quot;<span class="synConstant">.elizium.net/</span>&quot; <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">host</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">path</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">path</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">if</span> <span class="synSpecial">(</span><span class="synIdentifier">file_exists</span><span class="synSpecial">(</span>&quot;<span class="synConstant">/home/</span>&quot; <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">hostedUser</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span>&quot;<span class="synConstant">/web/</span>&quot; <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">host</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">path</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">path</span><span class="synSpecial">))</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">out</span> <span class="synStatement">=</span> &quot;<span class="synConstant">/home/</span>&quot; <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">hostedUser</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span>&quot;<span class="synConstant">/web/</span>&quot; <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">host</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">url</span><span class="synSpecial">[</span>&quot;<span class="synConstant">path</span>&quot;<span class="synSpecial">]</span> <span class="synStatement">.</span> <span class="synStatement">$</span><span class="synIdentifier">path</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">}</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">}</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synComment">//Otherwise just return this file as 99% chance its some automated script looking for exploitable webapps.</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">else</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synStatement">$</span><span class="synIdentifier">out</span><span class="synStatement">=</span> &quot;<span class="synConstant">/var/www/monkey.txt</span>&quot;;<br /><span class="synComment">//Log resulting path</span><br /><span class="synComment">#&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  fputs($log, &quot;$out\n&quot;);</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="synIdentifier">fputs</span><span class="synSpecial">(</span>STDOUT, &quot;<span class="synStatement">$</span><span class="synIdentifier">out</span><span class="synSpecial">\n</span>&quot;<span class="synSpecial">)</span>;<br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synSpecial">}</span><br /><span class="synComment">//Just keep doing it forever.</span><br /><span class="synSpecial">}</span> <span class="synStatement">while</span> <span class="synSpecial">(</span><span class="synConstant">true</span><span class="synSpecial">)</span>;<br /><span class="synSpecial">?&gt;</span><br /></code></div></p>
<p>The only improvement I may make to that is to get the users home directory info as opposed to assuming its under /home.</p>
<p>Now we just need put that script somewhere, make it executable by the Apache user and tell Apache to use it. Thats done like so:<br />
<div class="codeblock"><code><span class="synIdentifier">RewriteEngine</span> <span class="synConstant">on</span><br /><span class="synComment">#Use this program to do the mappings</span><br /><span class="synIdentifier">RewriteMap</span>&nbsp; &nbsp; &nbsp; hosted&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prg:/etc/apache2/<span class="synConstant">map</span>.hosted.php<br /><span class="synComment">#This is for allowing www.user.elizium.net type urls as they're outwith the scope of the rewrite script as they're easy to map.</span><br /><span class="synComment">#See http://forum.modrewrite.com/viewtopic.php?t=1652&amp;postdays=0&amp;postorder=asc&amp;start=10</span><br /><span class="synIdentifier">RewriteCond</span> %{HTTP_HOST} !^(www\.)?elizium\.net$ [NC]<br /><span class="synIdentifier">RewriteCond</span> %{ENV:REDIRECT_STATUS} ^$<br /><span class="synIdentifier">RewriteCond</span> %{HTTP_HOST} ^([^\.]+\.)?([^.]+)\.elizium\.net$ [NC]<br /><span class="synIdentifier">RewriteRule</span> .*&nbsp; /home/%2/web/%2\.elizium.net%{REQUEST_URI}&nbsp; &nbsp; &nbsp; [QSA,L]<br /><span class="synComment">#Ignore *.elizium.net</span><br /><span class="synIdentifier">RewriteCond</span>&nbsp; &nbsp;  %{HTTP_HOST}&nbsp; &nbsp; !elizium.net$ [NC]<br /><span class="synComment">#Use the full request</span><br /><span class="synIdentifier">RewriteRule</span>&nbsp; &nbsp;  ^(.+)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  %{HTTP_HOST}$1&nbsp; [C]<br /><span class="synComment">#Throw the request through the map program</span><br /><span class="synIdentifier">RewriteRule</span>&nbsp; &nbsp;  ^(.*)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  ${hosted:$1}&nbsp; &nbsp; [L,C]<br /></code></div></p>
<p>I hope this is of use to people. Especially those folk looking for a php based rewrite script for Apache. Theres a lot of scope to expand the script. For example, the file data could be retrieved from a database and then stored in something like <a href="http://www.danga.com/memcached/">memcached</a> if you were performing this sort of thing on a larger scale. Much better than having a large webserver config file that means the webserver has to be reloaded for each change.</p>
<p>The only problem I have with this, and I know its not insurmountable, is that the webserver user has to be able to read the files that users are storing. To allow this I&#8217;ve made the www-data user a member of the group all the users are members of. This also means that users can read each others files. So if somebody was to hardcode a password in a php file (for example) then it would be open to being read by any other user.</p>
<p>I also want to mention <a href="http://www.suphp.org">suPHP</a>, it really does merit an article to itself, but as I&#8217;m not intending to cover it in depth (you can read all about it at the website) I&#8217;ll just say that I&#8217;ve enabled it on Wintermute to prevent users being able to do things like kill the web server processes via a php script. To do that, I installed the suphp-common Debian package. The default configs are all you need. For the non-Debian user, they look like this when taken together:<br />
<div class="codeblock"><code><span class="synIdentifier">LoadModule</span> suphp_module /usr/lib/apache2/modules/mod_suphp.so<br /><span class="synStatement">&lt;IfModule</span><span class="synConstant"> mod_suphp.c</span><span class="synStatement">&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; suPHP_Engine <span class="synConstant">on</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span class="synIdentifier">AddHandler</span> x-httpd-php .php .php3 .php4 .phtml<br /><span class="synComment"># # Use a specific php config file (a dir which contains a php.ini file)</span><br />&nbsp; &nbsp; &nbsp; &nbsp; suPHP_ConfigPath /etc/php4/cgi/<br /><span class="synStatement">&lt;/IfModule&gt;</span><br /></code></div></p>
<p>As usual comments on the above are most welcome. Especially quick links about solving my security issue!</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mark@arricc.net" /><input type="hidden" name="return" value="http://www.arricc.net/pp-thanks.php" /><input type="hidden" name="item_name" value="Buy Me a Beer for User VHosting" /><input type="hidden" name="currency_code" value="GBP" /><input type="hidden" name="amount" value="5" /><input type="image" src="http://www.arricc.net/wp-content/plugins/buy-me-beer/icon_beer.gif" align="left" alt="" title="" hspace="3" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mark@arricc.net&amp;currency_code=GBP&amp;amount=5&amp;return=http://www.arricc.net/pp-thanks.php&amp;item_name=Buy+Me+a+Beer+for+User+VHosting" target="paypal">If you find this article useful, buy me a beer!</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.arricc.net/user-vhosting.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VWebhosting</title>
		<link>http://www.arricc.net/vwebhosting.php</link>
		<comments>http://www.arricc.net/vwebhosting.php#comments</comments>
		<pubDate>Fri, 07 Jul 2006 19:18:04 +0000</pubDate>
		<dc:creator>Fizzgig</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[Hosting]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Wist]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.arricc.net/vwebhosting.php</guid>
		<description><![CDATA[So, to reiterate &#8211; the main server (Wist) will hold all my own stuff, then I&#8217;ll be creating a user Virtual Server (Wintermute) on top of that for users to play with and/or break. All the user stuff is backended in a Xoops database using Xoops groups. Wist is installed with Debian Sarge using a [...]]]></description>
			<content:encoded><![CDATA[<p>So, to reiterate &#8211; the main server (Wist) will hold all my own stuff, then I&#8217;ll be creating a user Virtual Server (Wintermute) on top of that for users to play with and/or break. All the user stuff is backended in a <a href="http://www.xoops.org">Xoops</a> database using Xoops groups.</p>
<p>Wist is installed with Debian Sarge using a custom kernel including the vserver patches from Debian. This sort of thing is detailed elsewhere so I won&#8217;t go over it again here.</p>
<p>The core server software (all from the Debian archive) will include: Apache 1.3 with PHP4, Apache-SSL, Bind, MySQL 4.1, Exim4, ClamAV and Dovecot (I&#8217;ll be detailing the email setup seperately)<span id="more-17"></span></p>
<p>The installation of the Bind9 DNS server is very straight forward and only hosts a few domains, most of which are served from either Wist or Wintermute using a handfull of A/CNAME records and wildcard dns.</p>
<p>The Apache-SSL server is only going to host https for www.elizium.net so the only changes from the stock install for that is to install the appropriate certificate. I tend to buy certificates from <a href="https://ssl.ev1servers.net/?SslType=QuickSSL">EV1Servers</a> which I find very affordable.</p>
<p>The magic for this article happens in the config file for Apache 1.3 hosting plain http traffic.<br />
To allow me to easily add arbitrary domains and subdomains without extra config of the DNS server, I&#8217;ve used wildcard DNS. This means that all DNS requests for any subdomain of a domain (eg. www.example.org and sub.example.org) will be directed to the same server unless there is a specific DNS record for that particular subdomain. Clear? Probably not but thats the best I can do just now.</p>
<p>I wanted to be able to create a directory structure which would let me map out the web sites. Lets say I&#8217;ve created a root folder at /var/http and domains under that will be at /var/http/example.org then the subdomains will reside at /var/http/example.org/www /var/http/example.org/sub following me? Good. </p>
<p>On Wist, the first part of the domain name is stripped to become the subdomain. This means that if a request for http://example.org is recieved it will go to /var/http/org/example. I tend to create redirects in each of those folders to www.example.org etc as the vanity www has been overly popular for the last million years.</p>
<p>How did I manage to do this? Using mod_rewrite! Much as I hate regex (well, to be honest, I don&#8217;t use it enough to easily remember its quirks) this is clearly the way forward in this case.</p>
<p>Concentrate, here comes the science bit:<br />
<div class="codeblock"><code><span class="synIdentifier">RewriteEngine</span> <span class="synConstant">on</span><br /><span class="synComment">#Ignore requests for server wide directories</span><br /><span class="synIdentifier">RewriteCond</span>&nbsp; &nbsp;  %{REQUEST_URI}&nbsp; !^/mailman/.*<br /><span class="synIdentifier">RewriteCond</span>&nbsp; &nbsp;  %{REQUEST_URI}&nbsp; !^/pipermail/.*<br /><span class="synIdentifier">RewriteCond</span>&nbsp; &nbsp;  %{REQUEST_URI}&nbsp; !^/cgi-bin/.*<br /><span class="synIdentifier">RewriteCond</span>&nbsp; &nbsp;  %{REQUEST_URI}&nbsp; !^/icons/.*<br /><span class="synComment">#Rewrite the full request to include the host instead of just the path</span><br /><span class="synComment">#eg. /dir/index.html -&gt; www.example.org/dir/index.html</span><br /><span class="synIdentifier">RewriteRule</span>&nbsp; &nbsp;  ^(.+)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  %{HTTP_HOST}$1&nbsp; [C]<br /><span class="synComment">#Rewrite the url to a file in a directory</span><br /><span class="synComment">#www.example.org/dir/index.html -&gt; /var/http/example.org/www/dir/index.html</span><br /><span class="synIdentifier">RewriteRule</span>&nbsp; &nbsp;  ^([^.]+)\.([^/]+)\/(.*)$&nbsp; &nbsp; &nbsp; &nbsp; /var/http/$2/$1/$3 [L]<br /></code></div></p>
<p>Good, eh? I have to add my thanks to the guys in <a href="irc://chat.freenode.net/#regex">#regex</a> when I was struggling to come up with this.</p>
<p>Apache handles all the rest &#8211; default directory indexes and the variety of options itself.</p>
<p>The one last addition to the whole bundle is logging. First I started with this:<br />
<div class="codeblock"><code><span class="synIdentifier">LogFormat</span> <span class="synConstant">&quot;%{Host}i %h %l %u %t \&quot;%r\&quot; %&gt;s %b \&quot;%{Referer}i\&quot; \&quot;%{User-Agent}i\&quot;&quot;</span> vfull<br /><span class="synIdentifier">CustomLog</span> /var/log/apache/access.log vfull<br /></code></div></p>
<p>Which is the same as a standard Apache log file line but with the hostname (eg. www.example.org) as the first field.</p>
<p>Good, but we can do better.<br />
<div class="codeblock"><code><span class="synIdentifier">CustomLog</span> <span class="synConstant">&quot;|/sbin/vlogger -s access.log -u www-data -g www-data&nbsp; -t %Y%m%d-access.log /var/log/apache&quot;</span> vfull<br /></code></div></p>
<p>I&#8217;ve installed the <a href="http://n0rp.chemlab.org/vlogger/">vlogger</a> package. This spits out a directory per hostname with dated YYYY-MM-DD-access.log files and a symlink called access.log to the current days logs. Priceless if you want to do per host webstats withouth pre-precessing a big monolithic log file for specific domains.</p>
<p>Hopefully some folk will find that useful. After I&#8217;ve detailed the webhosting setup on Wintermute &#8211; more regex, some the same, mostly different &#8211; I&#8217;ll tell you how I automatically generate my webstats.</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mark@arricc.net" /><input type="hidden" name="return" value="http://www.arricc.net/pp-thanks.php" /><input type="hidden" name="item_name" value="Buy Me a Beer for VWebhosting" /><input type="hidden" name="currency_code" value="GBP" /><input type="hidden" name="amount" value="5" /><input type="image" src="http://www.arricc.net/wp-content/plugins/buy-me-beer/icon_beer.gif" align="left" alt="" title="" hspace="3" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mark@arricc.net&amp;currency_code=GBP&amp;amount=5&amp;return=http://www.arricc.net/pp-thanks.php&amp;item_name=Buy+Me+a+Beer+for+VWebhosting" target="paypal">If you find this article useful, buy me a beer!</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.arricc.net/vwebhosting.php/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Migratory changes&#8230;</title>
		<link>http://www.arricc.net/migratory-changes.php</link>
		<comments>http://www.arricc.net/migratory-changes.php#comments</comments>
		<pubDate>Sat, 01 Jul 2006 23:46:00 +0000</pubDate>
		<dc:creator>Fizzgig</dc:creator>
				<category><![CDATA[Hosting]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Wist]]></category>
		<category><![CDATA[Xev]]></category>

		<guid isPermaLink="false">http://wp.arricc.net/migratory-changes.php</guid>
		<description><![CDATA[Over the last 12 months I&#8217;ve become increasingly disenchanted with the value for money of the colo server I rent (xev.arricc.net) from Serversure. When I first took out the contract, it was the best there was, and as my bandwidth at the time was very low, 5Gb/month was an acceptable limitation. Since then my bandwidth [...]]]></description>
			<content:encoded><![CDATA[<p>Over the last 12 months I&#8217;ve become increasingly disenchanted with the value for money of the colo server I rent (xev.arricc.net) from <a href="http://www.serversure.net">Serversure</a>. When I first took out the contract, it was the best there was, and as my bandwidth at the time was very low, 5Gb/month was an acceptable limitation.</p>
<p>Since then my bandwidth has gone over that fairly regularly. So I went shopping about. After a lot of time spend trying to convert € and $ into £ I eventually settled on the basic root server offering from <a href="http://www.1and1.co.uk/?k_id=10500082">1&#038;1 Internet</a> (wist.arricc.net). The benefits? <em>unlimited</em> bandwidth and serial console access to the server &#8211; not to mention the spec is about double the memory and Mhz of Xev!</p>
<p>I&#8217;ve made a number of changes to the setup of Wist over Xev, with (hopefully!) no loss of services. Not least is the implementation of <a href="http://www.linux-vserver.org">virtual servers</a>. This has allowed me to let users run <a href="http://www.php.net">PHP</a> scripts in a sandbox which won&#8217;t affect my own projects. </p>
<p>I&#8217;m going to attempt to detail the setup in stages as there are a number of things to cover &#8211; vservers, webservers &#038; virtual hosting,  database server, host access(ssh, ftp, etc.) &#8211; so hopefully I&#8217;ll be able to break them down in meaningful stages!</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mark@arricc.net" /><input type="hidden" name="return" value="http://www.arricc.net/pp-thanks.php" /><input type="hidden" name="item_name" value="Buy Me a Beer for Migratory changes..." /><input type="hidden" name="currency_code" value="GBP" /><input type="hidden" name="amount" value="5" /><input type="image" src="http://www.arricc.net/wp-content/plugins/buy-me-beer/icon_beer.gif" align="left" alt="" title="" hspace="3" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mark@arricc.net&amp;currency_code=GBP&amp;amount=5&amp;return=http://www.arricc.net/pp-thanks.php&amp;item_name=Buy+Me+a+Beer+for+Migratory+changes..." target="paypal">If you find this article useful, buy me a beer!</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.arricc.net/migratory-changes.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
