Skip to main content.
May 22nd, 2008

Converting PowerMac G4 to 2U Server

Many years ago, before there were Xserves, in an attempt to save rack space in our cabinets, we experimented with ripping the guts out of a PowerMac G4 and stuffing them into a 2U server case. Here is a photo of one of those attempts:

It worked out fairly well and we had a couple of these running for several years.

The main piece to the puzzle was finding the right L riser card to give us access to the AGP slot and 2 of the PCI slots, one for a secondary Ethernet card and another for an ATTO SCSI card.

Posted by Brian Blood as Colocation, Hardware, Servers at 10:15 AM CDT

No Comments »

January 17th, 2008

Converting disks from Apple Software RAID version 1 to version 2

We have a few servers that are still running from being upgraded from the 10.2 and 10.3 days. Most all are running Tiger server, with one or two running Leopard.

Since all our XServe G4s run with dual mirrored pairs, we have quite a few of these software RAID sets.

The trick is that if a mirror pair becomes degraded, your server is now vulnerable because 10.4 disk utilities will not allow you to rebuild a v.1 raid set. You MUST convert the RAID set to v2 before it can be restored.

Unfortunately, the convertRAID verb for the command line diskutil, had some issues. Specifically if your drives had the OS 9 Drivers installed on them, or there wasn’t enough room to shrink the current partition, then the convertRAID operation would destroy the partition map of your disk.

As a result, the only way to get these volumes converted to v2 was to take the volume offline and run a Dusk Utility Restore operation from the v1 pair/disk to a new v2 pair/disk.

Since we have a handful of v1 RAID pairs that are the boot volume, being able to take a server down long enough to perform this operation is sometimes difficult.

The fine folks at SoftRAID have added a new feature to their latest version that allows you to convert RAID sets from the Apple RAID to a SoftRAID version and back. We’ve tested converting from v1 to SoftRAID format then to v2 and it works well. We had some strange behavior from the partition maps, but Mark James and the engineering staff gave us some tips on what to look for and this cleared those issues up. If you can’t run hardware RAID, get yourself a copy of SoftRAID.

As a lark, we also booted the server we used to test all of this on with Leopard Server and tried the diskutil convertRAID command to see if Apple had fixed that operation and it hallelujah it worked!

It even turned a single disk degraded v1 raid into a single member v2 raid set that could easily have another drive added to it for bringing it back to full redundancy. Good news this is as we won’t have to have a server with a boot volume that needs converting down for longer than it takes to boot from Leopard (a external FireWire drive of course), run the conversion, then reboot.

If you are running a server and do not have fully redundant (RAID is NOT backup) boot and data partitions, get thee to a store and buy another drive and add it in. The diskutil enableRAID command also works very well on a single disk.

Posted by Brian Blood as OS X Server, Servers at 10:40 AM CST

No Comments »

January 9th, 2008

Ubuntu/Debian on an Intel MacMini

In our previous adventures with Mac Minis as “blade” servers, I thought we might try installing Ubuntu/Debian on an Intel MacMini and seeing how the system performed against an OS X client based system.

Well, we did that and about a week later we wiped the machine and imaged off one of the other Minis and set it back up under OS X.

We had one of our techs scour all he could find on the net about installing Linux on an Intel MacMini and the biggest hurdle was getting something working in the EFI realm.

We ended up using rEFIt, a project on sourceforge, to allow us to dual boot into either Debian or Tiger. This had some issues, but in the end it worked out ok.

The USB Ethernet adapter also worked rather well right out of the box.

No, the real kicker was the on-board gigabit ethernet which is used on the backside primarily for database access. The Mini uses the Yukon based chipset for it’s GigE port and and this combination with the default ethernet driver installed by Debian induces a flow-control hang under certain loads.

Marcus Bointon hinted as much in comment #6 to my original article and so when the Debian Mini developed problems communication over that interface, I was pretty sure where to look.

Debian by default picks the “sky2″ driver for that PHY and it wasn’t cutting the mustard. Apparently this bug has been around for a couple of years (the chipset is also used on some other system boards) and the “workaround” is to recompile a different ethernet driver into the kernel and it solves the issue. Since running Debian on this system was merely a trial, we decided to punt instead of sinking more time in tinkering with it.

Under Debian, the Mini did actually perform about 10% better than when it was running Tiger. Ultimately, the OS turned out to not be the biggest factor in getting more performance out of the load balanced system as a whole. Tuning Apache and making some other improvements to the web application proved to be far more useful.

Posted by Brian Blood as Hardware, Linux, Servers at 11:57 PM CST

No Comments »

OS X - Server Monitor crazy tech note

Server Monitor is an application that allows you to monitor the health of several Xserves over the network:

Server Monitor

Sometimes the application gets a bit cranky about the connections it makes to the servers and reports that it can’t communicate or as you see here in the picture “reply not understood”. So we don’t really use it for serious monitoring other than as a cursory glance usually to check some items.

However, Apple really takes the cake with this knowledge-base article:

Xserve: Server Monitor does not authenticate with server over subnet

in which they claim that the way to fix the problems with their SOFTWARE, is to:

  1. Make the necessary changes to the username or password using Server Monitor.
  2. Quit Server Monitor.
  3. Shut down the Xserve that is the target of these changes.
  4. Remove the power cord from the back of the Xserve.
  5. Wait 30 seconds and plug the power cord back in.
  6. Power the server back on.

This sounds suspiciously similar to something an old tech friend of mine once told me:

There are sound scientifically proven reasons why one must sometimes sacrifice a chicken in order to get a SCSI chain to work.

Ugh.

Posted by Brian Blood as Colocation, Hardware, OS X Server, Servers, Soap Box at 11:33 PM CST

No Comments »

December 20th, 2007

Failing 180GB Xserve hard drives

In the past couple of months, we’ve started to see the IBM/Hitachi 180 GB drives that came with the Apple Hard drive modules for the Xserve G4 and ATA Xraids fail.

We always have these in a software mirror RAID, so we don’t have any data loss, but we are proactively starting to replace these drives with new Seagate 250GB drives. These drives not only have better caches, but run cooler and with less power usage.

Posted by Brian Blood as Hardware, Servers at 9:15 AM CST

3 Comments »

December 14th, 2007

Xserve Thumbscrews and rackmount structural integrity

It has come to my attention that the thumbscrews on the front panel of Xserves are a very important component of the overall structural integrity of the rack mounting system. they not only keep the Xserve from coming out of the case, but they also secure the forward portion of the server to the mounted top case. I’ve seen many Xserves that seemed as if they could pop out of their cases due to a small amount of bowing in the case. Having the thumbscrews tightened down adds another vertical support component.

xservefront.gif

Posted by Brian Blood as Colocation, Hardware, Servers at 11:54 AM CST

No Comments »

November 30th, 2007

SSL Cert with Subject Alternate Name

One of our customers runs a system that has a shopping cart system and they like it when a customer upgrades their site to include full store functionality. This of course means an SSL certificate. And traditionally, this would mean an additional IP address that would need to added to the server to support the new certificate.

Entering wider spread usage is what is becoming known as the UCC (Unified Communications Certificate), which is just a fancy name for a regular X509 v3 certificate that utilizes the Subject Alternate Name extension. This extension allows the certificate creator to embed multiple alternate names that are cryptographically tied to the primary key that defines the certificate.

What this means in practical terms is that you could purchase a certificate whose primary name is www.mydomain.com and with the same certificate and IP address, support multiple variations of that domain name, such as secure.mydomain.com or www.mydomain.net, www.mydomain.org, etc… This is different than a wildcard certificate that is tied to a specific domain name and can be used on any third level host name as desired: *.mydomain.com.

Since many entities that have a web presence tend to pick up the .net/.biz/.org variations on their .com domain name, this type of certificate means that those additional names can be secured with the same certificate/IP address. This means simpler configuration and not having to burn an IP address for every single name variation.

I’ve tested GoDaddy’s version of this certificate that gives you a 5 name cert for $60/year on plain jane Apache under 10.4 client and it works without issue. I have two different vhosts with different ServerName directives and the SSL config under both simply use the same SSL

Example. Assume I have a cert that I have based on mydomain.com as the primary name and has the following names embedded in as Subject Alternate Name extensions:

  1. www.mydomain.com
  2. store.mydomain.com
  3. www.mydomain.net
  4. mydomain.net
  5. admin.mydomain.net

Also assume that I have two different facets of my web application. The public facing side that is served by the .com and the admin/extranet that is served under the .net variation. My Apache config would look like so:


Listen 443
NameVirtualHost *:443

<VirtualHost *:443>
ServerName www.mydomain.com
ServerAdmin support@mydomain.com
DocumentRoot “/www/mydomain-com/”
<IfModule mod_ssl.c>
SSLEngine On
SSLCertificateFile “/etc/httpd/ssl/mydomain-com.crt”
SSLCertificateKeyFile “/etc/httpd/ssl/mydomain-com.key”
SSLCertificateChainFile “/etc/httpd/ssl/gd_intermediate_bundle.crt”
</IfModule>
ServerAlias mydomain.com store.mydomain.com
</VirtualHost>

<VirtualHost *:443>
ServerName www.mydomain.net
ServerAdmin support@mydomain.net
DocumentRoot “/www/mydomain-net/”
<IfModule mod_ssl.c>
SSLEngine On
SSLCertificateFile “/etc/httpd/ssl/mydomain-com.crt”
SSLCertificateKeyFile “/etc/httpd/ssl/mydomain-com.key”
SSLCertificateChainFile “/etc/httpd/ssl/gd_intermediate_bundle.crt”
</IfModule>
ServerAlias mydomain.net admin.mydomain.net
</VirtualHost>
notice the certificate files are the same for both vhosts and there is no distinguishing between IP addresses on the VirtualHost directive. Nice, clean, simple and it Just Works.

I’ve tested the certificate in the following browsers and none of them complain at all:

IE 6, FF2, Camino 1.5, Safari 2/3, Opera 8.5

X.509 v3 has been around at least since 2002 so it should be well supported.

Now, OS X Server should work exactly the same way as the underlying Apache system pieces are the same. The only issue comes into play with the way that ServerMgr handles storing certificates, their keys and passphrases and how Apache integrates all of these items.

Using the Server Admin app, you will not be able to use one of these certificates to secure two different Hosts that you enter as the host name in Apache is used by the “getsslpassphrase” binary to locate the certificate, private key, and password for the host in question to start SSL.

Since the primary name of the certificate is NOT the name of this secondary vhost, the loading process will fail. Any usage of this type of certificate will require you to manually create whatever non-primary VirtualHosts that would be setup to take advantage of these additional names secure by the “UCC” cert.

In order to get these certificates to load you will need to remove the passphrase from the key file so that Apache doesn’t call the getpassphrase and then fail.

the basic command for doing this is:
openssl rsa -in mydomain.key -out mydomain.key.open

For those who are use to working with OS X Server and doing something a bit out of the ordinary, this should not be surprising.

More SSL Certificate vendors are starting to offer this type of certificate, but I like the extra feature that the folks at DigiCert include with ALL their certificates: unlimited usage on any number of servers.

The DigiCert products are more expensive than the ones at GoDaddy, but theirs are single root certificates and they also go through additional layers of validation more than the simple “can you get an email at the domain” verification that GoDaddy utilizes.

Posted by Brian Blood as OS X Server, Servers, Web App Development at 5:56 PM CST

No Comments »

November 23rd, 2007

Basic Guidelines for Internet Connected Systems

Here is a list of the basics that every system administrator should implement:

  1. Set your Reverse DNS. Don’t leave it empty.
  2. Have geographically separated DNS servers
  3. MTAs should have properly formed HELO names
  4. rDNS should match the HELO on your MTA
  5. HELO should resolve to your IP address
  6. MX records must point to A records
  7. Filter Bogons at the first opportunity in your network architecture and at appropriate routing points.
  8. More to come

Posted by Brian Blood as General, Mail Server, Routers and Firewalls, Servers, Soap Box at 3:53 PM CST

No Comments »

November 22nd, 2007

Managing Bulk Email Delivery - Part 2 - Bounce Handling with Postfix and PHP

If you are unfamiliar with the basics of how email messages are sent and what happens with bounces, please read the previous article.

This article explains ONE way of dealing with bounces. It has its pros and its cons and does not account for ALL instances of bounces, but it does deal with the basics of implementing bounce handling and can be used as the foundation of a more sophisticated system.

The primary logic in this system is the ability to control the SMTP Envelope FROM address. We want to construct this so that when a message is returned, it will have encoded in it information that will tell us exactly who the message was originally sent to. The drawback to this method is that if we had originally a single message that was being blasted to 1000 recipients, we now have to create 1000 messages each with it’s own customized/encoded FROM address. (there can be only one FROM)

Once we can control the Envelope FROM, we need a domain for the bounces to be returned to. Whereas the messages may have been originally FROM list@mycompany.com, we want bounces to be returned to a special host name. This way we can segregate bounce handling to a different system (if so desired.) With that in mind the FROM address will be constructed like so: encodedrecipaddr@bounces.mycompany.com. Don’t forget to setup an MX record for this host name (which must point to an A record, CNAMEs or bare IPs are not allowed as MX data)

So, how do we encode the local part of the FROM address? It’s really up to you, but pick one way and stick with it. Our solution uses the following:

sentto-brian=networkjack.info@bounces.mycompany.com

You could get fancy like so:

sentto-2e64665495eab1fa4c276f73a610e054@bounces.mycompany.com

where 2e64665495eab1fa4c276f73a610e054 is an MD5 hash of the original email address.

Whatever method chosen, it’s necessary to track that particular encoding somehow as we will see it as the recipient on any possible bounces.
Here is the SQL table we used:

CREATE TABLE EmailAddressTracker (
EmailAddress varchar(255) NOT NULL,
EncodedFROM varchar(255) NOT NULL,
IgnoreBounces tinyint(1) unsigned NOT NULL default '0',
MsgCount int(10) unsigned NOT NULL default '0',
FirstEmail datetime NOT NULL,
LastEmail datetime NOT NULL,
FirstBounce datetime NOT NULL,
LastBounce datetime NOT NULL,
LastBounce2 datetime NOT NULL,
LastBounce3 datetime NOT NULL,
BounceCount smallint(5) unsigned NOT NULL default '0',
PRIMARY KEY (EmailAddress),
UNIQUE KEY EncodedFROM (EncodedFROM)
)

EncodedFROM holds the ENTIRE local part.

In the function that is ultimately responsible for sending the email out, we lookup/maintain entries in this table. This would be the place to apply policy and either let the message actually be sent or disable the email address somehow or ignore any policy if the IgnoreBounces flag were enabled for this particular email address.


If a message ultimately is rejected, we have to have some way of accessing this table. This is where Postfix and PHP come into play.We could simply have all messages for that domain fall into a mailbox which is accessed and read and parse the payload for undeliverable recipients, but we want direct access to the Envelope information. We could create a two tiered system that does do parsing as a fallback, but for now let’s keep it simple.

We are using Postfix on the server that is responsible for handling bounces. Two main additions to the postfix configuration are necessary.

  1. add a transport to the master.cf file:
    mybh unix - n n - 10 pipe
    user=mailadmin argv=/usr/local/bouncehandler/mybh.php $sender $recipient
    This defines for postfix a transport that is of the pipe variety. Postfix will pipe any bounces we tell it to, to the executable script in question with the given parameters.
  2. add a domain entry to the transport map so that messages that come in for our bounces.mycompany.com domain are sent to the newly defined transport:
    bounces.mycompany.com mybh:
    this can be a file called transport.map in /etc/postfix.
    don’t forget to the call postmap on the file so that it becomes a map hash file for fast access by postfix.

Once postfix is ready, the script defined can then do pretty much anything we want it to do.

Here is the relevant section of the PHP shell script that does the decoding and updating of the table.


#! /usr/bin/php -q
$sender = trim($argv[1]); // should be EMPTY
$recipient = trim($argv[2]);

$bounceProcd = FALSE;

$conn = ConnectToDB();
if (FALSE !== $conn)
{
list($encodedFrom, $bhDomain) = explode(’@', $recipient, 2);
//sentto-brian=networkjack.info@bounces.mycompany.com
$encodedFromSQL = mysql_real_escape_string($encodedFrom, $conn);
$query = “UPDATE EmailAddressTracker “.
“SET FirstBounce = IF(FirstBounce=0, NOW(), FirstBounce), BounceCount=BounceCount+1, “.
“LastBounce3=LastBounce2, LastBounce2=LastBounce, LastBounce=NOW() “.
“WHERE EncodedFROM = ‘$encodedFromSQL’”;
// We keep track of the datetime of the last three bounces to allow time based policy
// to be applied

$qResult = mysql_query($query, $conn);
$bounceProcd = mysql_affected_rows($conn) > 0;

// We have to read the data that postfix is sending to us in stdin
// we don’t have to necessarily do anything with the data, but we could store it into a table for later
// processing if we couldn’t determine the original recipient or wanted to double check our results

$dataLen = IgnoreMessageData();
}

// if we couldn’t connect to the db or there was not a record in the table that matched
// our clause for the specific encoded FROM, then exit back to postfix with a
// Temporary Failure. This will cause postfix to queue up the bounce
// message for later processing
$exitStatus = (TRUE == $bounceProcd) ? 0 : 75;
// 75 = EX_TEMPFAIL per sysexits

exit($exitStatus+0);

function IgnoreMessageData()
{
$msgLen = 0;
$fd = fopen(’php://stdin’, ‘r’);
while (FALSE === feof($fd))
{
$dunsel = fread($fd, 1024);
$msgLen += strlen($dunsel);
}
fclose($fd);
return $msgLen;
}
return;
?>

Notice that this script does NOT apply policy. It merely is there for statistical tracking and that is all it should do.

Policy of whether to allow any future messages to be sent to the user are applied in the Sending function, since that is closer to where the emails are actually generated. The bounce handling system has it’s one job and can do it well without complications.

So there it is. A simple and effective way of catching bounces for your web application.
My favorite part of this solution is the extremely minimal configuration required inside postfix.

Happy bounce tracking.

Posted by Brian Blood as Mail Server, Servers, Web App Development at 9:07 PM CST

No Comments »

Managing Bulk Email Delivery - Part 1 - Basics of SMTP and Bounces

Email.

As much as we depend on it, it was never designed to be a 100% reliable communications medium. And with the rise of spam over the past 10 years, it has become a blessing and a curse to System Admins the world over. We continually are balancing on that line of “How come I never got that email?” vs “Why do I get so much spam?”

So, when your client asks you to build and manage a mailing list system, you cringe as you KNOW that sometime, somewhere down the line that these thousands of messages being sent out WILL cause you a headache.

Companies and service providers tend to use a mix of internal and external rules, blacklists, whitelists and other automated policy to achieve a reduction in hearing either of those two questions above. (We love you users, but not hearing from you is the best praise)

These systems tend to clash with each other when thrown into the real world. We don’t want YOUR spam, but you had better accept messages from MY customers mailing list.

In terms of infrastructure, the best way to stay off the radar of other systems as a possible source of spam is to make sure you have good reverse DNS, proper and resolvable HELO responses and that you adhere to RFCs in the way your MTA behaves.

In terms of the actual email you send and the entire life-cycle of those messages, the best way to build and maintain a good reputation is not to send email to recipients that don’t exist. Yahoo is one of those providers that will ding you hard and shut down incoming mail from you if you send too many messages to unknown or disabled recipients. Two of our clients learned the hard way when their older systems for sending email did not include a method for handling bounces.

What they did have in their favor was a bottleneck function for sending email. Any email sent by the system was sent by this function and not directly using the built-in PHP mail() function. This gave us a place in the code to alter how the email is delivered. We could then make sure that bounces would come back to us in a way that we could easily detect the original recipient. Mailing list software that does automated bounce handling (like mailman) does this kind of thing all the time.

Quick overview of how email is sent.
You have what is known (in SMTP parlance) as the envelope and the payload. This is very analogous to sending a letter through the postal mail. You have a letter (the payload) which could be your letterhead, it may have a date and a To: and From: and Regarding:, etc… You pop that into an envelope (the envelope) and address it with who the letter is to be delivered to and what the return address is for if the letter cannot be delivered. Your message could be delivered to someone who is not actually the person listen in the headers of your actual letter and the return address could also be different from the From: portion of your letter as well. You could send a Blind Carbon Copy of the letter to a third party who is unnamed in the letter by sending another copy with their delivery address on the envelope.

So, we’ve established that the information on the outside of the envelope doesn’t necessarily have to have any relation to those named on the letter inside the envelope. Since it is your email program that reads the information in the payload and never sees the information on the “envelope”, this gives us tremendous flexibility in how we send email messages with customized envelopes that aid in our bounce detection.

What happens when an email bounces? A new message is created with special parameters.
Who gets the bounce message? The envelope recipient of a bounce is exactly what was defined as the envelope sender of the original message.
What gets bounced? That depends. There are no strictly adhered to standards as to what a bounce message looks like. What is in the payload could take a hundred different forms as mail server software vary as to what they place into the bounce message payload. Usually a Subject header with “Undeliverable” something or other.
What is the sender of a bounce message: BLANK. This prevents bounces from eternally being rebounced as there is no one to return it to (this is known as a double bounce)

Efficient delivery of email can send a message that was originally addressed to multiple people by only delivering a single digital copy of the message to a server (assuming the recipients are all hosted on the same end server.) However, with bounce messages, the address(es) the message did NOT make it to are NOT part of the only strictly adhered to portion of the Delivery cycle, the SMTP envelope. Parsing of the bounce payload is required with standard SMTP envelope usage. This is not exact and can fail as a bounce detection method.

What we need is to have some way of detecting the EXACT recipient that bounced. See the next article for one method of solving this problem.

Posted by Brian Blood as Mail Server, Servers, Web App Development at 9:06 PM CST

No Comments »

« Previous Entries