Archive

Posts Tagged ‘apache’

Apache catchall vhost

April 7th, 2010

As mentioned in One of my recent posts, I occasionally have to setup catchall pages in Apache. The general idea is usually that I either want a vhost that serves one page for any conceivable request, or that I moved something and want to alert the visitor, but provide a formula-based link to the new content. Assuming you have mod_rewrite, this is relatively simple.

In your vhost configuration (or .htaccess), you just need two lines:

RewriteEngine on
RewriteRule ^(.*)$ /index.php$1 [L]

This will redirect every request for the vhost to /index.php. Within your PHP script, you can access the actual request URI through $_SERVER["REQUEST_URI"]. The script that I’m currently using for an internal page is:

$newServer = "http://foo.example.com:12345";
 
if($_SERVER["REQUEST_URI"] == "/" || $_SERVER["REQUEST_URI"] == "/index.php")
  {
    header("Location: ".$newServer);
  }
else
  {
    $newURL = $newServer.$_SERVER["REQUEST_URI"];
    echo '<html><head><title>Page Moved</title>';
    echo '<META HTTP-EQUIV="refresh" CONTENT="5;URL='.$newURL.'">';
    echo '</head><body>';
    echo '<p>The page you are looking for is best found at:</p>';
    echo '<p><strong><a href="'.$newURL.'">'.$newURL.'</a></strong></p>';
    echo '<p>You will be automatically redirected after 5 seconds. If this does not happen, click the link above.</p>';
    echo '</body></html>';
  }

This script takes two distinct actions:

  • If the requested URL is / or /index.php, it transparently redirects to a different URL (and port).
  • Otherwise, it displays a “page moved to” message and uses a Meta-Refresh to redirect after 5 seconds.

Tech HowTos , , ,

New web server, WP optimization

February 28th, 2010

Tonight, more or less on a whim, I moved my blog from my older (dual 1GHz Pentium III Coppermine, 1GB RAM, 10k RPM SCSI disks, Compaq Proliant DL360 G1, OpenSuSE 10.2 32-bit) web server to my newer one (dual 1.4GHz Pentium III, 2GB RAM, 10k RPM SCSI disks, HP Proliant DL360 G2, CentOS 5.3 32-bit). I did some profiling with ab (ApacheBench), and just moving from one server to the other got some serious performance gains (I was profiling with runs of 1000 requests total, 10 concurrent requests). I also added the W3 Total Cache Wordpress plugin, which got the numbers to look even better!

As a side note, this was all done pretty quickly (moving the database and tarball for the vhost, installing the plugin, changing DNS), so please give me a heads-up if you experience any problems.

The numbers are rather impressive:

 Total Time(s)RPSAvg. Connection Time (ms)
Old Server1192.252838.7511,893
New Server569.1211757.095,667
Default W3tc Config23.75442,098.44237
Tuned W3tc12.28181,428.76122

All tests were performed on my workstation, a Dell Precision 470, two dual-core Xeons at 2.8 GHz, 2GB RAM, 16GB swap, OpenSuSE 11.1 64-bit. This was on the same LAN and subnet as the servers, with the workstation connected via a 1Gbps copper Ethernet link and the web-serving interfaces of the servers connected via 100Mbps (There’s a trunk in between, from the gigabit aggregation switch to the 100Mbps distribution switch).

Projects , , ,

Apache2 – list Name-Based Virtual Hosts

February 11th, 2010

Here’s a little tidbit that I never knew until I had an Apache2 name-based virtual host problem: httpd -S lists the vhosts that are being served by Apache, and how they were parsed from the config files.

The output on one of my servers looks something like:

[root@web2 vhosts.d]# httpd -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
_default_:443          web2.jasonantman.com (/etc/httpd/vhosts.d/ssl-host.conf:7)
*:80                   is a NameVirtualHost
         default server www.jasonantman.com (/etc/httpd/vhosts.d/000-default.conf:1)
         port 80 namevhost www.jasonantman.com (/etc/httpd/vhosts.d/000-default.conf:1)
         port 80 namevhost rackman.jasonantman.com (/etc/httpd/vhosts.d/rackman.jasonantman.com.conf:1)
         port 80 namevhost whatismyip.jasonantman.com (/etc/httpd/vhosts.d/whatismyip.jasonantman.com.conf:1)
Syntax OK

This is quite useful in debugging vhost problems, especially those pesky times when a request that should go to a specific vhost is being served by the default (in my case at this time, I had two ServerName directives instead of a ServerName and a ServerAlias).

Uncategorized , ,

Apache holding strong, IIS declining

July 23rd, 2009

According to the latest (June 2009) NetCraft web server survey, the Free/Open Source Apache web server is now hosting 50.46% of all active web sites surveyed (about 38 Million). Microsoft’s IIS server is at 28.05% (or about 29 Million) – a 7.64% decline from IIS’s May 2009 statistics. Interestingly, Google holds 12.2%, presumably most of that is their own content or content generated by their applications.

This is nothing new – both Free/Open Source software and Unix-related stuff has always had a stronger share in the server (and Internet) market than Microsoft products. And, despite all of Microsoft’s FUD, it’s clear that Apache is still more popular than IIS by a large margin – probably in no small part due to the extendability and scalability of Apache, and its security record (just take a look at the difference in system calls).

The real shining example, however, comes from looking at the stats on the Internet’s million busiest sites – 66.26% running Apache and only 18.77% running IIS, which has been constant for the better part of the last year. That says quite a bit about the stability and scalability of Apache. Not to mention that a lot of the really big sites run their own custom-modified versions of Apache which may or may not be identified as Apache in a survey.

opensource , ,

Wordpress Installation, Finished

February 3rd, 2009

Found this from a month and a half ago, waiting as a draft:

So, I mostly finished the WordPress installation. I got everything for WordPress up and running, tested my Blogger URL redirection script and then switched over my subdomain redirection.

The blogger redirection takes two parts, but is in fact quite simple. First, I went into the directory where the Blogger content had lived – /srv/www/htdocs/blog and moved everything in there into another directory, out of the way. I then created a .htaccess in the directory like:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
</IfModule>

All this does is used mod_rewrite to serve blog/index.php up for every page request. In index.php, I handle the important URL forms for Blogger – archives, tags, feeds, and posts – and redirect to the appropriate place. For archives, I just parse out the year and month from the Blogger URL and redirect to the proper page for WP. The feed is straight redirection. The tags (”labels” in Blogger parlance) are pulled out of the URL, have spaces (after urldecode()) replaced with dashes and are redirected to the right tag for WP.

The posts, on the other hand, were a bit more difficult. My solution ended up being parsing the post name out of the URL. When I used the import tool, WP kept the original Blogger URLs in the wp_postmeta table with a meta_key of “blogger_permalink”. I just looked for a Blogger permalink matching the title from the Blogger URL, found the corresponding post ID and redirected to the proper new WP URL.

The code for index.php, for me, looks something like:

<?php
// redirect old Blogger URLs in /blog to new WordPress in /wp
$request = mysql_real_escape_string(str_replace("/blog", "", $_SERVER['REQUEST_URI']));
 
// handle constant stuff like feeds and top-level pages
// TODO
if(strpos($request, "_archive.html"))
{
    // redirect to an archive
    $request = substr($request, strpos($request, "/", 1)+1);
    $ary = explode("_", $request);
    $redirect_to = "http://blog.jasonantman.com/".$ary[0]."/".$ary[1]."/";
    header("Location: ".$redirect_to);
    die();
}
elseif(strpos($request, "labels/"))
{
    // redirect to a tag page
    $redirect_to = substr($request, strpos($request, "labels/")+7);
    $redirect_to = str_replace(".html", "", $redirect_to);
    $redirect_to = urldecode($redirect_to);
    $redirect_to = str_replace(" ", "-", $redirect_to);
    $redirect_to = "http://blog.jasonantman.com/tags/".strtolower($redirect_to)."/";
    header("Location: ".$redirect_to);
    die();
}
elseif(strpos($request, "/blogger.html"))
{
    // redirect to main blog
    header("Location: http://blog.jasonantman.com/");
    die();
}
elseif(strpos($request, "/atom.xml"))
{
    // redirect to new feed
    header("Location: http://blog.jasonantman.com/feed/");
    die();
}
 
// handle the posts, months, tags, etc.
$fail = false;
$redirect_to = "";
$conn = mysql_connect()   or die("Error. MySQL connection failed at mysql_connect");
if(! $conn)
{
    error_log("SCRIPT ".$_SERVER['PHP_SELF'].": "."Unable to connect to MySQL.");
    $fail = true;
}
$select = mysql_select_db('wordpress');
if(! $select)
{
    error_log("SCRIPT ".$_SERVER['PHP_SELF'].": "."Unable to select DB wordpress.");
    $fail = true;
}
$query = "SELECT m.meta_key,m.meta_value,p.post_name,p.post_date FROM wp_postmeta AS m LEFT JOIN wp_posts AS p ON m.post_id=p.ID WHERE m.meta_key='blogger_permalink' AND m.meta_value='".$request."';";
$result = mysql_query($query);
if(! $result)
{
    error_log("SCRIPT ".$_SERVER['PHP_SELF'].": "."Error in query: ".$query." ERROR: ".mysql_error());
    $fail = true;
}
if(mysql_num_rows($result) < 1)
{
    // couldn't find an appropriate page
    // TODO: find a better way... for now just redirect to the month page
    $ary = explode("/", $request);
    if(count($ary) > 3)
    {
        $redirect_to = "http://blog.jasonantman.com/".$ary[1]."/".$ary[2]."/";
    }
    else
    {
        $redirect_to = "http://blog.jasonantman.com/";
    }
}
else
{
    $row = mysql_fetch_assoc($result);
    $redirect_to = "http://blog.jasonantman.com/".date("Y", strtotime($row['post_date']))."/".date("m", strtotime($row['post_date']))."/".$row['post_name'];
}
 
if($fail)
{
    // redirect to main page with 302
    Header( "Location: http://blog.jasonantman.com/" ); // implicit 302
}
else
{
    // redirect to the post or month
    Header( "HTTP/1.1 301 Moved Permanently" );
    Header( "Location: ".$redirect_to );
}
 
?>

So, it now looks like I’m pretty much done with setup, and even get to keep my links. The one interesting problem that will crop up is due to the fact that, at the moment, I’m hosting off of a dynamically IPed residential internet connection, so I’m at http://jantman.dyndns.org:10011. The problem lies in the fact that Blogger used this for its’ URIs and Permalinks, and it seems that (though http://blog.jasonantman.com uses a 302 not a 301 to redirect) Google, Technorati, etc. have indexed my site with this hostname and port, instead of the redirecting subdomain. Normally this wouldn’t be a problem, but I plan on soon moving to a business hosting account with 5 static IPs and port 80 open. Which means that soon the subdomain will become “real”… and all of those pesky dyndns.org:10011 links will be obsolete. The only way I can think of fixing this is, once I make the switch to static IP and port 80 (which will also include moving all of my subdomains to name-based virtual hosts) I’ll have to craft RewriteRules or redirect rules to replace http://jantman.dyndns.org:10011/wp/ with http://blog.jasonantman.com/, update DynDNS with my new static IP, and keep a default vhost listening on 10011 to provide rule-based redirection to the new subdomain. Eek.

Projects , , ,