-

Microsoft Office sku011.cab

Posted by aionman on Jul 31, 2009 in Microsoft Office

 

When trying to open Excel / Word, it prompts for CD and ask for the file SKU011.cab

Solution below:

 


Regedit (start menu -> run -> type regedit) 

Expand HKEY_LOCAL_MACHINE -> Software -> Microsoft -> Office -> 11.0 -> Delivery

There should be only 1 directory under Delivery, which is your DownloadCode (mine was 90000409-6000-11D3-8CFE-0150048383C9). Select that directory. On the right side of the screen, right-click on CDCache. Change the value to 0.

 
-

Install Clonezilla on Ubuntu

Posted by aionman on Jul 30, 2009 in Linux, Ubuntu

sudo aptitude install nis dhcp3-server tftpd (may fail start the service because /etc/dhcp3/dhcpd.conf is not configured)

sudo ifconfig eth0:1 192.168.0.1 (when system only has 1 nic port)

# import gpg key
wget -q http://drbl.sourceforge.net/GPG-KEY-DRBL -O- | sudo apt-key add -

# add following line into source list
# then aptitude update and install drbl
deb http://drbl.sourceforge.net/drbl-core drbl stable testing unstable

# For setting up system environment, here has lots of setting, and choose which IP to be the PXE interface should be the most important portion.
sudo /opt/drbl/sbin/drblsrv -i
sudo /opt/drbl/sbin/drblpush -i
———————————–
# start to use clonezilla
sudo /opt/drbl/sbin/dcs
# clone the client image
All –> clonezilla-start –> Beginner –> save-disk
# restore the local image to the client
All –> clonezilla-start –> Beginner –> restore-disk

Tags: ,

 
-

Zimbra slow response on SMTP

Posted by aionman on Jul 27, 2009 in Ubuntu, Zimbra

Zimbra reponse with 5-10s before SMTP banner
220 mail.example.com ESMTP Postix

Need to do a trace at the server
tcpdump -s 1500  -w /tmp/server_trace.pcap

Looking at a wireshark trace, i see the server sending out “MDNS” packets which was installed along with ubuntu-desktop.

sudo update-rc.d -f avahi-daemon remove
/etc/init.d/avahi-daemon stop

 
-

.htaccess tips and tricks

Posted by aionman on Jul 25, 2009 in Linux

http://corz.org/serv/tricks/htaccess2.php

<ifModule>
more clever stuff here
</ifModule>

redirecting and rewriting

“The great thing about mod_rewrite is it gives you all the configurability and flexibility of Sendmail. The downside to mod_rewrite is that it gives you all the configurability and flexibility of Sendmail.”

- Brian Behlendorf, Apache Group
ne of the more powerful tricks of the .htaccess hacker is the ability to rewrite URLs. This enables us to do some mighty manipulations on our links; useful stuff like transforming very long URL’s into short, cute URLs, transforming dynamic ?generated=page&URL’s into /friendly/flat/links, redirect missing pages, preventing hot-linking, performing automatic language translation, and much, much more.

Make no mistake, mod_rewrite is complex. This isn’t the subject for a quick bite-size tech-snack, probably not even a week-end crash-course, I’ve seen guys pull off some real cute stuff with mod_rewrite, but with kudos-hat tipped firmly towards that bastard operator from hell, Ralf S. Engelschall, author of the magic module itself, I have to admit that a great deal of it still seems so much voodoo to me.

The way that rules can work one minute and then seem not to the next, how browser and other in-between network caches interact with rules and testing rules is often baffling, maddening. When I feel the need to bend my mind completely out of shape, I mess around with mod_rewrite!

After all this, it does work, and while I’m not planning on taking that week-end crash-course any time soon, I have picked up a few wee tricks myself, messing around with webservers and web sites, this place..

The plan here is to just drop some neat stuff, examples, things that have proven useful, and work on a variety of server setups; there are apache’s all over my LAN, I keep coming across old .htaccess files stuffed with past rewriting experiments that either worked; and I add them to my list, or failed dismally; and I’m surprised that more often these days, I can see exactly why!

Very little here is my own invention. Even the bits I figured out myself were already well documented, I just hadn’t understood the documents, or couldn’t find them. Sometimes, just looking at the same thing from a different angle can make all the difference, so perhaps this humble stab at URL Rewriting might be of some use. I’m writing it for me, of course. but I do get some credit for this..

# time to get dynamic, see..
RewriteRule (.*)\.htm $1.php

beginning rewriting..

Whenever you use mod_rewrite (the part of apache that does all this magic), you need to do..

..before any ReWrite rules. note: +FollowSymLinks must be enabled for any rules to work, this is a security requirement of the rewrite engine. Normally it’s enabled in the root and you shouldn’t have to add it, but it doesn’t hurt to do so, and I’ll insert it into all the examples on this page, just in case*.

The next line simply switches on the rewrite engine for that folder. if this directive is in you main .htaccess file, then the ReWrite engine is theoretically enabled for your entire site, but it’s wise to always add that line before you write any redirections, anywhere.

* Although highly unlikely, your host may have +FollowSymLinks enabled at the root level, yet disallow its addition in .htaccess; in which case, adding+FollowSymLinks will break your setup (probably a 500 error), so just remove it, and your rules should work fine.

Important: While some of the directives on this page may appear split onto two lines, in your .htaccess file, they must exist completely on one line. If you drag-select and copy the directives on this page, they should paste just fine into any text editor.

simple rewriting

Simply put, Apache scans all incoming URL requests, checks for matches in our .htaccess file and rewrites those matching URLs to whatever we specify. something like this..

all requests to whatever.htm will be sent to whatever.php:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$ $1.php [NC]

Handy for anyone updating a site from static htm (you could use .html, or .htm(.*), .htm?, etc) to dynamic php pages; requests to the old pages are automatically rewritten to our new urls. no one notices a thing, visitors and search engines can access your content either way. leave the rule in; as an added bonus, this enables us to easily split php code and its included html structures into two separate files, a nice idea; makes editing and updating a breeze. The [NC] part at the end means “No Case”, or “case-insensitive”; more on the switches, later.

Folks can link to whatever.htm or whatever.php, but they always get whatever.php in their browser, and this works even if whatever.htm doesn’t exist! But I’m straying..

As it stands, it’s a bit tricky; folks will still have whatever.htm in their browser address bar, and will still keep bookmarking your old .htm URL’s. Search engines, too, will keep on indexing your links as .htm, some have even argued that serving up the same content from two different places could have you penalized by the search engines. This may or not bother you, but if it does, mod_rewrite can do some more magic..

this will do a “real” external redirection:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.+)\.htm$ http://corz.org/$1.php [R,NC]

This time we instruct mod_rewrite to do a proper external rewrite, aka, “redirection”. Now, instead of just background rewriting on-the-fly, the user’s browser is physically redirected to a new URI, and whatever.php appears in their browser’s address bar – search engines and other spidering entities will automatically update their links to the .php versions; everyone wins. You can take your time with the updating, too.

Note: if you use [R] alone, it defaults to sending an HTTP “MOVED TEMPORARILY” redirection, aka, “302″. But you can send other codes, like so..

this performs the exact same as the previous example RewriteRule.
RewriteRule ^(.+)\.htm$ http://corz.org/$1.php [R=302,NC]

Okay, I sent the exact same code, but I didn’t have to. For details of the many 30* response codes you can send, see here. Most people seem to want to send 301, aka, “MOVED PERMENENTLY”.

Note: if you add an “L” flag to the mix; meaning “Last Rule”, e.g. [R=302,NC,L]; Apache will stop processing rules for this request at that point, which may or may not be what you want. Either way, it’s useful to know.

not-so-simple rewriting … flat links and more

You may have noticed, the above examples use regular expression to match variables. What that simply means is.. match the part inside (.+) and use it to construct “$1″ in the new URL. In other words, (.+) = $1 you could have multiple (.+) parts and for each,mod_rewrite automatically creates a matching $1, $2, $3, etc, in your target (aka. ‘substitution’) URL. This facility enables us to do all sorts of tricks, and the most common of those, is the creation of “flat links”..

Even a cute short link like http://mysite/grab?file=my.zip is too ugly for some people, and nothing less than a true old-school soliddomain/path/flat/link will do. Fortunately, mod_rewrite makes it easy to convert URLs with query strings and multiple variables into exactly this, something like..

a more complex rewrite rule:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^files/([^/]+)/([^/]+).zip /download.php?section=$1&file=$2 [NC]

would allow you to present this link as..

http://mysite/files/games/hoopy.zip

and in the background have that transparently translated, server-side, to..

http://mysite/download.php?section=games&file=hoopy

which some script could process. You see, many search engines simply don’t follow our ?generated=links, so if you create generating pages, this is useful. However, it’s only the dumb search engines that can’t handle these kinds of links; we have to ask ourselves.. do we really want to be listed by the dumb search engines? Google will handle a good few parameters in your URL without any problems, and the (hungry hungry) msn-bot stops at nothing to get that page, sometimes again and again and again…

I personally feel it’s the search engines that should strive to keep up with modern web technologies, in other words; we shouldn’t have to dumb-down for them. But that’s just my opinion. Many users will prefer /files/games/hoopy.zip to /download.php?section=games&file=hoopy but I don’t mind either way. As someone pointed out to me recently, presenting links as standard/flat/pathsmeans you’re less likely to get folks doing typos in typed URL’s, so something like..

an even more complex rewrite rule:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^blog/([0-9]+)-([a-z]+) http://corz.org/blog/index.php?archive=$1-$2 [NC]

would be a neat trick, enabling anyone to access my blog archives by doing..

http://corz.org/blog/2003-nov

in their browser, and have it automagically transformed server-side into..

http://corz.org/blog/index.php?archive=2003-nov

which corzblog would understand. It’s easy to see that with a little imagination, and a basic understanding of posix regular expression, you can perform some highly cool URL manipulations.

Here’s the very basics of regexp (expanded from the apache mod_rewrite documentation)..

Escaping:

\char escape that particular char

    For instance to specify special characters.. [].()\ etc.

Text:

.             Any single character  (on its own = the entire URI)
[chars]       Character class: One of following chars
[^chars]      Character class: None of following chars
text1|text2   Alternative: text1 or text2 (i.e. "or")

    e.g. [^/] matches any character except /
         (foo|bar)\.html matches foo.html and bar.html

Quantifiers:

? 0 or 1 of the preceding text
* 0 or N of the preceding text  (hungry)
+ 1 or N of the preceding text

    e.g. (.+)\.html? matches foo.htm and foo.html
         (foo)?bar\.html matches bar.html and foobar.html

Grouping:

(text)  Grouping of text

    Either to set the borders of an alternative or
    for making backreferences where the nth group can
    be used on the target of a RewriteRule with $n

	e.g.  ^(.*)\.html foo.php?bar=$1

Anchors:

^    Start of line anchor
$    End   of line anchor

    An anchor explicitly states that the character right next to it MUST
    be either the very first character ("^"), or the very last character ("$")
    of the URI string to match against the pattern, e.g.. 

	^foo(.*) matches foo and foobar but not eggfoo
	(.*)l$ matches fool and cool, but not foo

shortening URLs

One common use of mod_rewrite is to shorten URL’s. Shorter URL’s are easier to remember and, of course, easier to type. An example..

beware the regular expression:
Options +FollowSymlinks
RewriteEngine On
RewriteRule ^grab /public/files/download/download.php

this rule would transform this user’s URL..

http://mysite/grab?file=my.zip

server-side, into..

http://mysite/public/files/download/download.php?file=my.zip

which is a wee trick I use for my distro machine, among other things. everyone likes short URL’s, and so will you; using this technique, you can move /public/files/download/ to anywhere else in your site, and all the old links still work fine; simply alter your .htaccess file to reflect the new location. edit one line, done – nice – means even when stuff is way deep in your site you can have cool links like this../trueview/sample.php and this; links which are not only short, but flat..

capturing variables

Slapping (.*) onto the end of the request part of a ReWriteRule is just fine when using a simple $_GET variable, but sometimes you want to do trickier things, like capturing particular variables and converting them into other variables in the target URL. Or something else..

When capturing variables, the first thing you need to know about, is the [QSA] flag, which simply tags all the original variables back onto the end of the target url. This may be all you need, and will happen automatically for simple rewites. The second thing, is%{QUERY_STRING}, an Apache server string we can capture variables from, using simple RewriteCond (aka. conditional ) statements.

RewriteCond is very like doing if...then...do in many programming languages. If a certain condition is true, then do the rewrite that follows..

In the following example, the RewriteCond statement checks that the query string has the foo variable set, and captures its value while it’s there. In other words, only requests for /grab that have the variable foo set, will be rewritten, and while we’re at it, we’ll also switchfoo, for bar, just because we can..

capturing a $_GET variable:
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.*)
RewriteRule ^grab(.*) /page.php?bar=%1

would translate a link/user’s request for..

http://domain.com/grab?foo=bar

server-side, into..

http://domain.com/page.php?bar=bar

Which is to say, the user’s browser would be fed page.php (without an [R] flag in the RewriteRule, their address bar would still read/grab?foo=bar). The variable bar would be available to your script, with its value set to bar. This variable has been magically created, by simply using a regular ? in the target of the RewriteRule, and tagging on the first captured backreference, %1.. ?bar=%1

Note how we use the % character, to specify variables captured in RewriteCond statements, aka “Backreferences”. This is exactly like using $1 to specify numbered backreferences captured in RewriteRule patterns, except for strings captured inside a RewriteCondstatement, we use % instead of $. Simple.

You can use the [QSA] flag in addition to these query string manipulations, merge them. In the next example, the value of foo becomes the directory in the target URL, and the variable file is magically created. The original query string is then tagged back onto the end of the whole thing..

QSA Overkill!
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.+)
RewriteRule ^grab/(.*) /%1/index.php?file=$1 [QSA]

So a request for..

http://domain.com/grab/foobar.zip?level=5&foo=bar

is translated, server-side, into..

http://domain.com/bar/index.php?file=foobar.zip&level=5&foo=bar

Depending on your needs, you could even use flat links and dynamic variables together, something like this could be useful..

By the way, you can easily do the opposite, strip a query string from a URL, by simply putting a ? right at the end of the taget part. This example does exactly that, whilst leaving the actual URI intact..

just a demo!
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{QUERY_STRING} .
RewriteRule foo.php(.*) /foo.php? [L]

The RewriteCond statement only allows requests that have something in their query string, to be processed by the RewriteRule, or else we’d end up in that hellish place, dread to all mod_rewriters.. the endless loop. RewriteCond is often used like this; as a safety-net.

cooler access denied

In part one I demonstrated a drop-dead simple mechanism for denying access to particular files and folders. The trouble with this is the way our user gets a 403 “Access Denied” error, which is a bit like having a door slammed in your face. Fortunately, mod_rewrite comes to the rescue again and enables us to do less painful things. One method I often employ is to redirect the user to the parent folder..

they go “huh?.. ahhh!”
# send them up!
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)$ ../ [NC]

It works great, though it can be a wee bit tricky with the URLs, and you may prefer to use a harder location, which avoids potential issues in indexed directories, where folks can get in a loop..

they go damn! Oh!
# send them exactly there!
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)$ /comms/hardware/router/ [NC]

Sometimes you’ll only want to deny access to most of the files in the directory, but allow access to maybe one or two files, or file types, easy..

deny with style!
# users can load only “special.zip”, and the css and js files.
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !^(.+)\.css$
RewriteCond %{REQUEST_FILENAME} !^(.+)\.js$
RewriteCond %{REQUEST_FILENAME} !special.zip$
RewriteRule ^(.+)$ /chat/ [NC]

Here we take the whole thing a stage further. Users can access .css (stylesheet) and javascript files without problem, and also the file called “special.zip”, but requests for any other filetypes are immediately redirected back up to the main “/chat/” directory. You can add as many types as you need. You could also bundle the filetypes into one line using | (or) syntax, though individual lines are perhaps clearer.

Here’s what’s currently cooking inside my /inc/ directory..

all-in-one control..
RewriteEngine on
Options +FollowSymlinks
# allow access with no restrictions to local machine at 192.168.1.3
RewriteCond %{REMOTE_ADDR} !192.168.1.3
# allow access to all .css and .js in sub-directories..
RewriteCond %{REQUEST_URI} !\.css$
RewriteCond %{REQUEST_URI} !\.js$
# allow access to the files inside img/, but not a directory listing..
RewriteCond %{REQUEST_URI} !img/(.*)\.
# allow access to these particular files…
RewriteCond %{REQUEST_URI} !comments.php$
RewriteCond %{REQUEST_URI} !corzmail.php$
RewriteCond %{REQUEST_URI} !digitrack.php$
RewriteCond %{REQUEST_URI} !gd-verify.php$
RewriteCond %{REQUEST_URI} !post-dumper.php$
RewriteCond %{REQUEST_URI} !print.php$
RewriteCond %{REQUEST_URI} !source-dump.php$
RewriteCond %{REQUEST_URI} !textview.php$
RewriteRule ^(.*)$ / [R,NC,L]

Ban User Agents, referrers, script-kiddies and more..

There are many valid reasons to ban a particular request from sucking up your site’s resources; resources that could be better served to valid, interested users. It might be some cross-site attack script, or inward link from a place you don’t want to be associated with, or perhaps a web sucker or download manager, whatever; .htaccess + mod_rewrite provides ways to protect your content from unwanted “guests”.

The basic formula is standard if-then logic: if the request meets a particular CONDITION, then REWRITE the request. The “conditions” can be many things; perhaps the referrer header sent by their browser (the site they came from), or the page they asked for, or a particular query parameter, or the type of client (browser, etc.) they are using, or any other piece of information Apache has attached to the request. Here’s an example which will deny access to “Teleport Pro”, a download manager which is known to suck, hard..

Who need’s a local copy, when I’m right here?..
RewriteCond %{HTTP_USER_AGENT} ^Teleport\ Pro [NC]
RewriteRule . abuse.txt [L]

It’s your site, and just like your home, you have every right to exert some control over who gets in. You may have a huge list of user agents you’d rather not have eating your bandwidth; so use the [OR] flag, and line ‘em up..

A little garlic for the net vampires..
RewriteCond %{HTTP_USER_AGENT} ^BackWeb [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^Bandit [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BatchFTP [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BecomeBot [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [NC,OR]
# etc..
RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [NC]
RewriteRule . abuse.txt [L]

This forms the basis of what often becomes a HUGE list of ban-lines. Remember, we aren’t limited to user agent strings..

Suckers, h4x0rz, kiddies, cross-site scripters and more.. Bye now!
# why not come visit me directly?
RewriteCond %{HTTP_REFERER} \.opendirviewer\. [NC,OR]
# this prevents stoopid cross-site discovery attacks..
RewriteCond %{THE_REQUEST} \?\ HTTP/ [NC,OR]
# please stop pretending to be the Googlebot..
RewriteCond %{HTTP_REFERER} users\.skynet\.be.* [NC,OR]
# really, we need a special page for these twats..
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{THE_REQUEST} etc/passwd [NC,OR]
RewriteCond %{REQUEST_URI} owssvr\.dll [NC,OR]
# you can probably work these out..
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{THE_REQUEST} \/\*\ HTTP/ [NC,OR]
# etc..
RewriteCond %{HTTP_USER_AGENT} Sucker [NC]
RewriteRule . abuse.txt [L]

Fortunately, mod_rewite can parse enormous lists of ban-lines in milliseconds, so feel free to be as specific and comprehensive as required.

As ever, thorough testing is strongly recommended. Simply send requests matching your conditions and see what happens. And importantly; normal requests, too. Firefox, Opera, Konqueror, and most other decent browsers, allow you to alter the user agent string; though you would quickly find the process tedious in a testing situation. Far better to use some tool better designed to send fake HTTP requests..

It’s not too difficult to mock up a web request on the command-line with any-old user agent using a scripting language like php or Perl, if you have these things available (read: most Linux/UNIX/BSD/etc. as well as many other OS). Many examples exist online. In fact, you could quickly create a suite of tests, designed to interrogate all your rewrite rules, with results logging and much more, if required. cURLis always useful for jobs like this, so long as you don’t add a cURL ban-line!

On a Windows desktop, Sam Spade can send a single spoofed request with a couple of clicks, along with a stack of similarly handy tricks, and regularly proves itself invaluable.

prevent hot-linking

Believe it or not, there are some webmasters who, rather than coming up with their own content will steal yours. Really! Even worse, they won’t even bother to copy to their own server to serve it up, they’ll just link to your content! no, it’s true, in fact, it used to be incredibly common. These days most people like to prevent this sort of thing, and .htaccess is one of the best ways to do it.

This is one of those directives where the mileage variables are at their limits, but something like this works fine for me..

how DARE they!
Options +FollowSymlinks
# no hot-linking
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?corz\.org/ [NC]
RewriteRule .*\.(gif|jpg|png)$ http://corz.org/img/hotlink.png [NC]

You may see the last line broken into two, but it’s all one line (all the directives on this page are). Let’s have a wee look at what it does..

We begin by enabling the rewrite engine, as always.

The first RewriteCond line allows direct requests (not from other pages – an “empty referrer”) to pass unmolested. The next line means;if the browser did send a referrer header, and the word “corz.org” is not in the domain part of it, then DO rewrite this request.

The all-important final RewriteRule line instructs mod_rewrite to rewrite all matched requests (anything without “corz.org” in its referrer) asking for gifs, jpegs, or pngs, to an alternative image.

There are loads of ways you can write this rule; Google for “hot-link protection” and get a whole heap. Simple is best. You could send a wee message instead, or direct them to some evil script, or something. Mine is a simple corz.org logo, which I think is rather clever. Actually, these days, I do something even cleverer-er..

lose the “www”

I’m often asked how I prevent the “www” part showing up at my site, so I guess I should add something about that. Briefly, if someone types http://www.corz.org/ into their browser (or uses the www part for any link at corz.org) it is redirected to the plain, rather neat, http://corz.org/ version. This is very easy to achieve, like this..

beware the regular expression:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{http_host} ^www\.corz\.org [NC]
RewriteRule ^(.*)$ http://corz.org/$1 [R=301,NC]

You don’t need to be touched by genius to see what’s going on here. There are other ways you could write this rule, but again, simple is best. Like most of the examples here, the above is pasted directly from my own main .htaccess file, so you can be sure it works perfectly. In fact, I recently updated it so that I could share rules between my dev mirror and live site without any .htaccess editing..

here’s what I’m currently using:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]

multiple domains in one root

If you are in the unfortunate position of having your sites living on a host that doesn’t support multiple domains, you may be forced to roll your own with .htaccess and mod_rewrite. So long as your physical directory structure is well thought-out, this is fairly simple to achieve.

For example, let’s say we have two domains, pointing at a single hosted root; domain-one.com and domain-two.com. In our web server root, we simply create a folder for each domain, perhaps one/, and two/ then in our main (root) .htaccess, rewrite all incoming requests, like this..

All requests NOT already rewritten into these folders, transparently rewrite..
#two domains served from one root..
RewriteCond %{HTTP_HOST} domain-one.com
RewriteCond %{REQUEST_URI} !^/one
RewriteRule ^(.*)$ one/$1 [L]

RewriteCond %{HTTP_HOST} domain-two.com
RewriteCond %{REQUEST_URI} !^two
RewriteRule ^(.*)$ two/$1 [L]

All requests for the host domain-one.com are rewritten (not R=redirected) to the one/ directory, so long as they haven’t already been rewritten there (the second RewriteCond). Same story for domain-two.com. Note the inconsistency in the RewriteCond statement;!^/dir-name and !^dir-name should both work fine.

Also note, with such a simple domain & folder naming scheme, you could easily merge these two rule sets together. This would be unlikely in the real world though, which is why I left them separate; but still, worth noting.

Other general settings and php directives can also go in this root .htaccess file, though if you have any further rewrite you’d like to perform; short URL’s, htm to php conversion and what-not; it’s probably easier and clearer to do those inside the sub-directory’s .htaccess files.

automatic translation

If you don’t read English, or some of your guests don’t, here’s a neat way to have the wonderful Google translator provide automatic on-the-fly translation for your site’s pages. Something like this..

they simply add their country code to the end of the link, or you do..
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)-fr$ http://www.google.com/translate_c?hl=fr&sl=en&u=http://corz.org/$1 [R,NC]
RewriteRule ^(.*)-de$ http://www.google.com/translate_c?hl=de&sl=en&u=http://corz.org/$1 [R,NC]
RewriteRule ^(.*)-es$ http://www.google.com/translate_c?hl=es&sl=en&u=http://corz.org/$1 [R,NC]
RewriteRule ^(.*)-it$ http://www.google.com/translate_c?hl=it&sl=en&u=http://corz.org/$1 [R,NC]
RewriteRule ^(.*)-pt$ http://www.google.com/translate_c?hl=pt&sl=en&u=http://corz.org/$1 [R,NC]

You can create your menu with its flags or whatever you like, and add the country code to end of the links.. <a href="page.html-fr" id="... Want to see this page in French?

Although it is very handy, and I’ve been using it here for a couple of years here at the org, for my international blog readers, all two of them, heh. Almost no one knows about it, mainly because I don’t have any links . One day I’ll probably do a wee toolbar with flags and what-not. Perhaps not. Trouble is, the Google translator stops translating after a certain amount of characters (which seems to be increasing, good), though these same rules could easily be applied to other translators, and if you find a good one, one that will translate a really huge document on-the-fly, do let me know!

If you wanted to be really clever, you could even perform some some kind of IP block check and present the correct version automatically, but that is outside the scope of this document. note: this may be undesirable for pages where technical commands are given (like this page) because the commands will also be translated. “RewriteEngine dessus” will almost certainly get you a 500 error page!

Another thing you might like to try; rather than individual country flags; fr, de, etc., use the “u” flag, for “Universal”. In theory, Google will check the client’s location, and automatically translate to that language. One line in your .htaccess would cover all languages, and automatically cover new ones as Google adds them.

While I’m here, slightly related; if you are non-english speaking, note, you can do a similar thing browser-side, create a “bookmarklet” (a regular bookmark, except that it “does something”), using this code for the location..

the same sort of thing, except browser-side..
javascript:void(location.href=’http://translate.google.com/translate?u=’+location.href)

httpd.conf

Remember, if you put these rules in the main server conf file (usually httpd.conf) rather than an .htaccess file, you’ll need to use ^/… … instead of ^… … at the beginning of the RewriteRule line, in other words, add a slash.

inheritance..

If you are creating rules in sub-folders of your site, you need to read this.

You’ll remember how rules in top folders apply to all the folders inside those folders too. we call this “inheritance”. normally this just works. but if you start creating other rules inside subfolders you will, in effect, obliterate the rules already applying to that folder due to inheritance, or “decendancy”, if you prefer. not all the rules, just the ones applying to that subfolder. a wee demonstration..

Let’s say I have a rule in my main /.htaccess which redirected requests for files ending .htm to their .php equivalent, just like the example at the top of this very page. now, if for any reason I need to add some rewrite rules to my /osx/.htaccess file, the .htm >> .php redirection will no longer work for the /osx/ subfolder, I’ll need to reinsert it, but with a crucial difference..

this works fine, site-wide, in my main .htaccess file
# main (top-level) .htaccess file..
# requests to file.htm goto file.php
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$ http://corz.org/$1.php [R=301,NC]

Here’s my updated /osx/.htaccess file, with the .htm >> .php redirection rule reinserted..

but I’ll need to reinsert the rules for it to work in this sub-folder
# /osx/.htaccess file..
Options +FollowSymlinks
RewriteEngine on
RewriteRule some rule that I need here
RewriteRule some other rule I need here
RewriteRule ^(.*)\.htm$ http://corz.org/osx/$1.php [R=301,NC]

Spot the difference in the subfolder rule, highlighted in red. you must add the current path to the new rule. now it works again, and all the osx/ subfolders will be covered by the new rule. if you remember this, you can go replicating rewrite rules all over the place.

If it’s possible to put your entire site’s rewrite rules into the main .htaccess file, and it probably is; do that, instead, like this..

it’s a good idea to put all your rules in your main .htaccess file..
# root /.htaccess file..
Options +FollowSymlinks
RewriteEngine on
# .htm >> .php is now be covered by our main rule, there’s no need to repeat it.
# But if we do need some /osx/-specific rule, we can do something like this..
RewriteRule ^osx/(.*)\.foo$ /osx/$1.bar [R=301,NC]

Note, no full URL (with domain) in the second example. Don’t let this throw you; with or without is functionally identical, on mostservers. Essentially, try it without the full URL first, and if that doesn’t work, sigh, and add it – maybe on your next host!

The latter, simpler form is preferable, if only for its tremendous portability it offers – my live site, and my development mirror share the exact same .htaccess files – a highly desirable thing.

By the way, it perhaps doesn’t go without saying that if you want to disable rewriting inside a particular subfolder, where it is enabledfurther up the tree, simply do:

handy for avatar folders, to allow hot-linking, etc..
RewriteEngine off

cookies

Lastly, a quick word about cookies. While it’s easy enough to set cookies in .htaccess without any mod_rewrite..

create a cookie called “example-cookie”, and set its value to “true”..
Header set Set-Cookie “example-cookie=true”

..you will need it to read the cookie information back again, and “do stuff” with it. It’s easy. For example, to check if the above cookie exists and has the correct value set, we could simply do..

check for that same cookie + value..
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_COOKIE} !corz-tools=true
RewriteRule .* /err/401.php

..which could easily form the basis of a simple authentication system. As with any RewriteCond, you can get pretty complex, checking multiple cookies, utilizing regexp and more, but that’s enough to get you started.

conclusion

In short, mod_rewrite allows you to send browsers from anywhere to anywhere. You can create rules based not simply on the requested URL, but also on such things as IP address, browser agent (send old browsers to different pages, for instance), and even the time of day; the possibilities are practically limitless.

The ins-and outs of mod_rewrite syntax are topic for a much longer document than this, and if you fancy experimenting with more advanced rewriting rules, I urge you to check out the apache documentation.

If you have apache installed on your system, there will likely be a copy of the apache manual, right here, and the excellent mod_rewriting guide, lives right here. do check out the URL Rewriting Engine notes for the juicy syntax bits. That’s where I got the cute quote for the top of the page, too.

;o)
(or

troubleshooting tips..

rewrite logging..

When things aren’t working, you may want to enable rewrite logging. I’ll assume you are testing these mod_rewrite directives on your development mirror, or similar setup, and can access the main httpd.conf file. If not, why not? Testing mod_rewrite rules on your live domain isn’t exactly ideal, is it? Anyway, put this somewhere at the foot of your http.conf..

Expect large log files..
#
# ONLY FOR TESTING REWRITE RULES!!!!!
#
RewriteLog “/tmp/rewrite.log”
#RewriteLogLevel 9
RewriteLogLevel 5

Set the file location and logging level to suit your own requirements. If your rule is causing your Apache to loop, load the page, immediately hit your browser’s “STOP” button, and then restart Apache. All within a couple of seconds. Your rewrite log will be full of all your diagnostic information, and your server will carry on as before.

Setting a value of 1 gets you almost no information, setting the log level to 9 gets you GIGABYTES! So you must remember to comment out these rules and restart Apache when you are finished because, not only will rewrite logging create space-eating files, it will seriously impact your web server’s performance.

RewriteLogLevel 5 is very useful, but 2 is probably enough information for most issues.

Fatal Redirection

If you start messing around with 301 redirects [R=301], aka. “Permanently Redirected”, and your rule isn’t working, you could give yourself some serious headaches..

Once the browser has been redirected permanently to the wrong address, if you then go on to alter the wonky rule, your browser willstill be redirected to the old address (because it’s a browser thing), and you may even go on to fix, and then break the rule all over again without ever knowing it. Changes to 301 redirects can take a long time to show up in your browser.

Solution: restart your browser, or use a different one.

Better Solution: Use [R] instead of [R=301] while you are testing . When you are 100% certain the rule does exactly as it’s expected to, then switch it to [R=301] for your live site.

debug-report.php
A php script to make your mod_rewrite life easier!

When things aren’t working as you would expect, you probably won’t have to enable rewrite logging to get the information you need. What’s usually required is no more than a quick readout of all the current variables, $_GET array, and so on; so you can see exactlywhat happened to the request.

For another purpose, I long ago created debug.php, and later, finding all this information useful in chasing down wonky rewrites, created a “report” version, which rather than output to a file, spits the information straight back into your browser, as well as $_POST,$_SESSION, and $_SERVER arrays, special variables, like __FILE__, and much more.

Usage is simple; you make it your target page, so in a rule like this..

RewriteRule ^(.*)\.html$ /catch-all.php?var=$1

You would have a copy of debug-report.php temporarily renamed to catch-all.php in the root of your server, and typehttp://testdomain.org/foobar.html into your address bar and, with yer mojo working, debug-report.php leaps into your browser with a shit-load of exactly the sort of information you need to figure out all this stuff. When I’m messing with mod_rewritedebug-report.php saves me time, a lot. Also, it’s free..

Tags:

 
-

Install Zimbra on Ubuntu

Posted by aionman on Jul 24, 2009 in Ubuntu, Zimbra

Ubuntu 8.04 LTS Server (Hardy Heron) Install Guide

The following guide is for installing ZCS on Ubuntu Server 8.04 LTS, and is a revision of my previous Ubuntu Server 6.06 installation guide here. Please verify which version you are using and follow the appropriate guide, as there are material differences between the two. I have tested this guide with the 32-bit version of Ubuntu only; others will need to verify if any tweaks are necessary for a 64-bit installation.

This installation is for a split-DNS setup, where the server resides on a DMZ and so needs to resolve to its own internal (DMZ subnet) IP address rather than the public IP address that is published to the world. This is a setting where a firewall/router supplies the translation from the public IP to the DMZ IP (DNAT–Destination Network Address Translation) so that translation is not known to the server itself. This configuration is desirable for security, but it makes bits of the Zimbra configuration more complex than they might otherwise be.

For simplicity’s sake I’m referring to Zimbra’s DMZ address as the “private ip address” from here on. By that I mean that the Zimbra box has only one IP address, it’s on the DMZ, and can be seen by my LAN but not the public. When I say “public IP address” I’m not talking about another address on the Zimbra box, but rather the address that gets DNATed to my box and which is resolved in the world.

Contents

[hide]

Installing Ubuntu 8.04 LTS

Obtain your installation binary from Ubuntu at http://www.ubuntu.com/getubuntu/download. Be sure you download the LTS (Longterm Support) Server Edition, NOT the Desktop Edition. Burn the iso file to a CD and boot it in your server. There is an excellent, highly-detailed installation guide for this version at http://www.howtoforge.com/perfect-server-ubuntu8.04-lts. I highly recommend this guide, particularly if you are new to Linux or Ubuntu specifically. The following points need to be kept in mind as you install:

1) The installation (and the guide) want to configure your LAN via DHCP. Cancel it before it gets that far, and manually configure it with a static IP address, netmask, and gateway. Don’t put in a public DNS for your nameserver configuration; instead put in the same IP address that you just gave the machine for its own static IP (this won’t let you resolve names on the internet until we do some more configuration below, but it saves headaches later).

2) When the installation asks for a hostname, give it only a one-word hostname (e.g. “mail” or “myserver”) NOT the fully-qualified domain name (mail.mydomain.com). In the next screen where it asks for the domain name, give the “mydomain.com” part without the hostname.

3) Hard disk configuration is easy if you are using a single drive, but for a server, that’s not the most secure way to do things. Ideally you should have either a RAID-1 or a RAID 1+0 configuration for your disks to provide redundancy. Most ideally that would be hardware-RAID, but configuring it in Ubuntu is a challenge. Software RAID (native to Linux) on the other hand, is easy IF you set it up AT THE TIME YOU ARE PARTITIONING YOUR DISKS. See this howto http://www.howtoforge.com/how-to-install-ubuntu8.04-with-software-raid1 for setup instructions if you want to use software RAID. As to partitioning your drives, you can find a variety of opinions. I just make a small partition for swap (1.5-2x RAM) and the rest for the whole system. Others will recommend separate partitions for mailstore, system, etc. Use your own judgement here.

4) Once the base system has been installed, the installer will ask you for a username, and then a password for that user. This needs to be a non-root user, and unlike previous Ubuntu versions, the user “admin” is no longer accepted. Whatever you choose, that username and password will be what you use to log in at the command line later, and the same password will be the password for sudo commands. Be sure you remember what you put in here!

5) At the “Software Selection” screen, select the DNS Server and OpenSSH Server options for installation, but nothing else. This will allow remote administration (SSH), and will install bind9 which you will need for split DNS.

6) Run the following command to make sure you have all the necessary packages: sudo apt-get install bind9 dnsutils file libgmp3c2 libexpat1 libstdc++5 libltdl3 libperl5.8 perl curl libpcre3 libc6

With these items, your installation will complete and the system will reboot.

This guide shows how to install the Zimbra Collaboration Suite (ZCS) on Ubuntu 6.10 (Edgy Eft) and 6.06 (Dapper Drake) server systems. Zimbra is a full-featured, open source collaboration suite – email, group calendaring, contacts, and web document management and authoring. It has a feature-rich AJAX web interface and is compatible with clients such as Microsoft Outlook, Apple Mail, and Novell Evolution so that mail, contacts, and calendar items can be synchronised from these to the ZCS server. It can also be synchronized to many mobile devices. ZCS makes use of many existing open source projects such as Postfix, MySQL, and OpenLDAP.

I do not issue any guarantee that this will work for you!

1.1 Enable The root Account

To enable the root account, run

sudo passwd root

and specify a password for root.

Afterwards, become root by running

su

All following commands in this tutorial are executed as root (unless something else is written)!

1.2 Install The SSH Daemon

Just run

apt-get install ssh openssh-server

to install the SSH daemon.

1.3 Apply A Static IP Address And Hostname

Edit /etc/network/interfaces and adjust it to your needs (in this example setup I will use the IP address 192.168.0.110):

vi /etc/network/interfaces

# This file describes the network interfaces available on your system

# and how to activate them. For more information, see interfaces(5).

# The loopback network interface

auto lo

iface lo inet loopback

# The primary network interface

auto eth0

iface eth0 inet static

address 192.168.0.110

netmask 255.255.255.0

network 192.168.0.0

broadcast 192.168.0.255

gateway 192.168.0.1

Then restart your network:

/etc/init.d/networking restart

Then edit /etc/hosts. Make it look like this:

vi /etc/hosts

127.0.0.1 localhost.localdomain localhost

192.168.0.110 mail.example.com mail

# The following lines are desirable for IPv6 capable hosts

::1 ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

ff02::3 ip6-allhosts

Now run

echo mail.example.com > /etc/hostname

and reboot the system:

shutdown -r now

Afterwards, run

hostname
hostname -f

Both should show mail.example.com.

From now on you can use an SSH client such as PuTTY and connect from your workstation to your Ubuntu server and follow the remaining steps from this tutorial.

DNS

Proper DNS configuration is PARAMOUNT! If you don’t have your DNS working properly, don’t even bother trying to install Zimbra, because trying to fix DNS after the fact may result in an install that can do everything except send mail–even from a Zimbra user to himself! So I’ll say it again:

If you can’t resolve your mailserver’s own private IP address (NOT the public IP) using nslookup, fix it BEFORE you install Zimbra!

If your installation above was successful, when you sign on at the command line you’ll be able to ping public IP addresses if you know them, but you may not be able to resolve any names to ping them.

Now you have to configure the following files, which are in the directory /etc/bind (for brevity I’ve deleted the generic comment lines included by the distro). Note that the query-source address and forwarders lines are already there, they just need to be uncommented, and in the case of the forwarders, the ip addresses of your ISP’s DNS servers need to be added. Note also that the syntax needs to be EXACTLY as shown below–leave out one semicolon or bracket and the whole thing blows up:

/etc/bind/named.conf.options

options {
        directory "/var/cache/bind";

        query-source address * port 53;

        forwarders {
                xxx.xxx.xxx.xxx; xxx.xxx.xxx.xxx;
        };

        auth-nxdomain no;    # conform to RFC1035

};

the ip addresses on this file are public ip addresses of the DNS you use in the outside world. The line “query-source address * port 53″ is to allow your machine to hit the DNS if oddball DNS ports are blocked. You can leave it commented if you don’t need it.

Check /etc/resolv.conf and make sure it looks like this:

nameserver xxx.xxx.xxx.xxx

The IP address here should be the Zimbra box’s private ip address.

Once you’ve fixed these two files and restarted bind

/etc/init.d/bind9 restart

you should be able to resolve names in the outside world. Try something like “ping google.com” and if you get an answer, you’re on the way.

Now it’s time to get the internal zone working. Append the following lines to /etc/bind/named.conf.local

        zone "mydomain.com"  {
                type master;
                file "/etc/bind/db.mydomain.com";
        };

Note that you need to type the full pathname to your db.* file. Also, be sure you don’t miss a semicolon “;” in any of these lines that have them because a missing semicolon breaks the file.

Now create your file /etc/bind/db.mydomain.com

;
; BIND data file for mydomain.com
;
$TTL    604800
@       IN      SOA     mail.mydomain.com. admin.mydomain.com. (
                         070725         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      mail
        IN      MX      10 mail
        IN      A       xxx.xxx.xxx.xxx
mail    IN      A       xxx.xxx.xxx.xxx

The ip address here is again your Zimbra internal ip address; the string “admin.mydomain.com” is replaced with the email address you are using for administration, only with a “.” instead of the “@” in the address. Be careful to increment the serial number one higher every time you modify this file or the changes won’t stick. Many users use the date they edit the file for the serial number, but as long as you start low and only get higher it really doesn’t matter.

Now you may need to reboot the machine (restarting bind9 alone doesn’t always work) and try to resolve your mail server.

nslookup mydomain.com

If it returns your public IP address, your internal DNS is not working. If things are configured correctly it’ll return the internal address.

Hosts Table

Before you get to the install you also need to modify your /etc/hosts file:

127.0.0.1       localhost.localdomain   localhost
10.3.2.244      mail.tractor-equip.net  mail

ONLY IF this is working, it’s now time to update your packages:

sudo bash (this will ask for your password, enter your administrator's pw, then you'll be at a root prompt)
apt-get upgrade
apt-get update

Now you’re ready to install Zimbra.

Installing ZCS

Several discussion groups have listed the dependencies not installed by the standard Linux install, but the easy thing to do is try to run the install and let Zimbra give you a list of what’s missing. Download the appropriate package for your Ubuntu installation (32 or 64 bit Ubuntu 8.04 LTS), copy it into your choice directory (I prefer /temp because /tmp is volatile and clears out every reboot), change to that directory, and type

tar -xzf zc*

and it’ll create a whole directory /temp/zcs with lots of files inside it. Then:

cd /temp/zcs
./install.sh

It’s not going to work the first time, but it’ll give you a list of missing dependencies. Write down all the package names it says are missing. Your list may be slightly different than mine, but whatever it is, load them. Just separate each package name with a space like this:

apt-get install libpcre3 libgmp3c2 libstdc++5

Now re-run your Zimbra install and accept all the defaults except:

When it asks you for your domain, it’s going to have your fully-qualified domain name (hostname.mydomain.com) rather than just the domain, and probably complain about not having an MX record. Change the hostname to just mydomain.com and it’ll find the names through nslookup, and it’ll be happy. The rest of the install should proceed without errors, except that toward the end it’s going to ask you to “Adress unconfigured items” but, if you’re doing this from the console and not from an SSH connection with a buffer, the actual item that’s unconfigured is off the screen and invisible. It’s the admin password, which is in menu item 3.

Finally, when the install is done and it has given you the last “press Enter to finish” you are almost done. I recommend at this point that you convert your webmail to use https rather than http. This is a security question, but it is also discretionary. If you choose to do this, then at the command prompt, type:

su - zimbra
zmtlsctl https

Now reboot the system, and when it comes back up,give it a couple minutes to start the rest of the Zimbra processes. If your installation is successful, you can go to https://xxx.xxx.xxx.xxx:7071 (your internal ip address again) to get the administrative console, or

https://xxx.xxx.xxx.xxx to log in as a user.

Congratulations–one shiny new Zimbra installation on Ubuntu!

 
-

Setting up software RAID in Ubuntu Server

Posted by aionman on Jul 15, 2009 in Ubuntu

Setting up software RAID in Ubuntu Server

Updated Mar 13 2009 to reflect improvements in Ubuntu 8.04 and later.

Linux has excellent software-based RAID built into the kernel. Unfortunately information on configuring and maintaining it is sparse. Back in 2003, O’Reilly published Managing RAID on Linux and that book is still mostly up to date, but finding clear instructions on the web for setting up RAID has become a chore.

Here is how to install Ubuntu Server with software RAID 1 (disk mirroring). This guide has been tested on Ubuntu Server 8.04 LTS (Hardy Heron). I strongly recommend using Ubuntu Hardy or later if you want to boot from RAID1.

Software RAID vs. hardware RAID

Some system administrators still sneer at the idea of software RAID. Years ago CPUs didn’t have the speed to manage both a busy server and RAID activities. That’s not true any more, especially when all you want to do is mirror a drive with RAID1. Linux software RAID is ideal for mirroring, and due to kernel disk caching and buffering it can actually be faster than RAID1 on lower end RAID hardware. However, for larger requirements like RAID 5, the CPU can still get bogged down with software RAID.

Software RAID is inexpensive to implement: no need for expensive controllers or identical drives. Software RAID works with ordinary EIDE, Serial ATA and SCSI drives and controllers. You can mix together whatever drive types and sizes you have on hand. When all you need are mirrored drives, software RAID is an especially good choice.

However, there are reasons you might prefer hardware RAID over software RAID:

  • Hardware RAID is simpler to setup and manage.
  • Depending on the server BIOS, a system using Linux software RAID probably won’t be able to boot automatically when the first disk of a mirror is first replaced with a new blank drive (It can still be booted manually though).
  • Linux will only boot when the “/boot” and “/” partitions are on RAID1. It cannot boot when those partitions are on RAID5. Other partitions, however, can be RAID5.
  • With software RAID, after replacing a failed drive the administrator must login and enter commands to add the new drive to the array and re-sync the contents. Good hardware RAID controllers re-sync automatically as soon as they see a new drive, without operator intervention.

Notice I said “good hardware controllers”. Low-end controllers like those integrated with consumer-grade motherboards that require software drivers are not suitable for server use. Cheap motherboard RAID (often called “fake RAID”) is designed for gamers who want RAID 0 to boost disk read times, not for reliability. Server-grade hardware RAID requires controllers from Adaptec, 3ware or another reputable manufacturer.

A simple RAID1 example

For this example we’ll construct a simple RAID1 mirror using a server that has two 4 GB serial ATA drives. Such a configuration will keep running if either drive fails, but (obviously) not if both fail.

EIDE or SCSI drives can be used with Linux RAID, but right now serial ATA provides the best combination of low cost, performance and flexibility.

For this example, partitioning will be done as simply as possible:

Drive Partition Type Mounted on Size
Drive0 /dev/sda1 Primary / 4.1 GB
/dev/sda2 Primary (swap area) (remainder of disk)
Drive1 /dev/sdb1 Primary / 4.1 GB
/dev/sdb2 Primary (swap area) (remainder of disk)

In Linux software RAID each mount point is usually configured as a separate RAID device. It’s possible for entire drives to be RAID members rather than each partition (e.g. combine /dev/sda and /dev/sdb) but the resulting device will not be bootable.

In this example partitions sda1 and sdb1 will be made members of a RAID1 device named /dev/md0. Partitions sda2 and sdb2 will be members of a RAID1 device named /dev/md1.

RAID device Type Mounted on Size Members
/dev/md0 RAID1
mirror
/ 4.1 GB /dev/sda1
/dev/sdb1
/dev/md1 RAID1
mirror
(swap) (remainder of disk) /dev/sda2
/dev/sdb2

On a real world server it’s a good idea to have at least /var and /home on their own partitions, but the above scheme is good enough for this example. We are also purposely avoiding complications like logical volume management (LVM), just to keep things simple.

In Linux RAID, corresponding partitions on each drive in a RAID device should be the same size. If they aren’t, software RAID will still work but each RAID device will only be as large as the smallest member partition (e.g. if you add a 10GB partition and a 20GB partition into a RAID1 array, the resulting array will only have 10GB of usable space).

Installing Ubuntu server with RAID1

To install a fresh Ubuntu System with RAID, boot from the CD-ROM as usual. Follow the prompts until you get at the “Partition Disks” dialog.

  • From the “Partitions Disks” dialog box, select “Manually edit the partition table”.
  • Select the first disk (”sda”)
  • Say yes to “Create a new empty partition table on this device?”
  • Use the dialog boxes to create a new primary partition large enough to hold the root filesystem but leave space for a swap partition (4.1 GB in this example).
  • For “How to use this partition” select “physical volume for RAID“, not the default “Ext3 journaling file system”
  • Make the partition bootable (Bootable flag “on”)
  • Use the dialogs to create one other primary partition taking up the remaining disk space (197.4 MB in this example). Later this will be used for swap.
  • For “How to use this partition” select “physical volume for RAID“, not the default “Ext3 journaling file system” and not “swap area”
  • Repeat the above steps to create identical partitions on the second drive. Remember to mark partition one on both drives as “bootable”. The final result should look similar to the following:

Initial partitioning scheme (click for full size)

  • Once the partitions are configured, at the top of the “Partition Disks” main dialog select “Configure Software RAID”
  • When asked “Write the changes to the storage devices and configure RAID” select “Yes”.
  • For “Multidisk configuration actions” select “Create MD device”
  • For “Multidisk device type” select “RAID1″
  • For “Number of active devices for the RAID1 array” enter “2″
  • For Number of spare devices for the RAID1 array” enter “0″ (zero)
  • When asked to select “Active devices for the RAID1 multidisk device” select both /dev/sda1 and /dev/sdb1
  • From the next dialog select “create MD device”
  • Repeat the above steps to create an MD device that contains /dev/sda2 and /dev/sdb2
  • Finally, from the dialog “Multidisk configuration actions” select “Finish”

Next configure RAID #0 (md0) to be mounted as the “/” filesystem and RAID device #1 (md1) to be mounted as swap:

  • From the “Partition Disks” dialog, move the cursor bar under “RAID device #0″ and select “#1 4.1 GB”
  • Configure the device as an Ext3 filesystem mounted on /, as shown:

ubunturaid022.png (click image for full size)

  • From the Partition Disks dialog under “RAID device #1″ select “#1 197.3 MB”
  • Configure the device as “swap area”, as shown:

ubunturaid023.png (click image for full size)

  • The final partitioning screen should resemble the following:

ubunturaid024.png (click image for full size

  • Select “Finish partitioning and write changes to disk”.The RAID1 mirrors are created and made active, the filesystem is formatted and installation of Ubuntu proceeds as usual.
  • Allow the installation to complete then reboot when requested.

Booting with a failed drive

The GRUB bootloader has always made it tricky to boot from a RAID array when one of the drives has failed. Fortunately, the Ubuntu team improved the situation in Ubuntu 8.10 Intrepid Ibex and backported the changes to Ubuntu Server 8.04 Hardy Heron (See Bug 290885 for the whole saga).

Now administrators can choose how the server will behave when a drive in a RAID array has failed:

  1. Wait at a boot prompt for manual intervention (the default), or
  2. Automatically boot from the other drive

Most administrators will want option 2. After all, the purpose of RAID is to increase server availability. However, with some hardware failures automatically booting could wipe out data on the remaining drive. If you have good backup and recovery procedures, that risk is probably acceptable, but it is your decision as administrator.

To make Ubuntu Server automatically boot when one drive in a RAID array has failed do the following:

  • From a running server, do a package update to make sure you have the latest kernel and boot loader (e.g. sudo apt-get update; apt-get upgrade).
  • Reboot the server to ensure any new kernel and bootloader packages are in place.
  • From the command line run “sudo grub-install /dev/md0″ to ensure GRUB is installed on all members of the boot RAID device.
  • From the command line run “sudo dpkg-reconfigure mdadm”
  • When asked “Should mdadm run monthly redundancy checks of the RAID arrays?”, select either Yes or No (read the warning about possible performance impact and decide. “Yes” is the safer choice)
  • When asked “Do you want to start the md monitoring daemon?” select Yes.
  • Enter a valid email address to send warning messages to.
  • When asked “Do you want to boot your system if your RAID becomes degraded?” selected Yes.

Now when the system boots and either of the drives has failed, the system will seem to hang at the “Loading, please wait…” stage for approximately five minutes, then proceed to boot normally.

Some friendly advice

RAID systems that boot and continue to function with failed members are great for continuity, but we often see administrators either not notice that drives have failed, or wait to long to replace them.

Suddenly the last drive also dies and they face a long downtime while the system is rebuilt or restored. It may seem obvious, but when dealing with RAID:

  1. Make sure your system properly alerts you when a drive fails. Don’t just rely on the MD monitoring daemon to send email alerts: also run smartmontools to monitor physical health and setup a script in your server monitor (e.g. monit or Nagios), run a script from cron that parses /proc/mdstat, or whatever method works best in your environment.
  2. Don’t wait to repair or replace the failed drive. When a drive fails, act immediately. Drives had a eerietendancy to fail at nearly the same time, especially when  they are identical models and purchased at the same time.

Why RAID swap?

You might be wondering why we put swap on a RAID device, causing system swap activity to suffer the additional overhead of RAID.

Though Linux is capable of handling multiple independent swap partitions on multiple drives, if a drive containing an active swap partition dies it may take the system down with it. That defeats the point of having RAID in the first place, so to avoid that possibility we put the swap in RAID.

This creates more overhead, but swap is only meant as temporary substitute memory during rare moments of memory exhaustion. If the system is regularly using swap, performance is already being severely impacted and it’s time to add more physical memory.

Care and feeding

Having two drives configured in a RAID1 mirror allows the server to continue to function when either drive fails. When a drive fails completely, the kernel RAID driver automatically removes it from the array.

However, a drive may start having seek errors without failing completely. In that situation the RAID driver may not remove it from service and performance will degrade. Luckily you can manually remove a failing drive using the “mdadm” command. For example, to manually mark both of the RAID devices on drive sda as failed:

mdadm /dev/md0 –fail /dev/sda1
mdadm /dev/md1 –fail /dev/sda2

The above removes both RAID devices on drive sda from service, leaving only the partitions on drive sdb active.

Removing a failed drive

When Ubuntu sees that RAID has been configured, it automatically runs the mdadm command in “monitor mode” to watch each device and send email to root when a problem is noticed. You can also manually inspect RAID status using commands like the following:

cat /proc/mdstat
mdadm –query –detail /dev/md0
mdadm –query –detail /dev/md1

As mentioned above, it’s wise to use the smartmontools package to monitor each drive’s internal failure stats. However, as noted in a recent analysis by Google (PDF link), drives are perfectly capable to dying without any warning showing in their SMART indicators.

To replace a drive that has been marked as failed (either automatically or by using “mdadm –fail”), first remove all partitions on that drive from the array. For example to remove all partitions from drive sda:

mdadm /dev/md0 –remove /dev/sda1
mdadm /dev/md1 –remove /dev/sda2

Once removed it is safe to power down the server and replace the failed drive.

Boot problems

If it was the first drive that failed, after replacing it with a new unformatted drive the system may no longer boot: some BIOSs only attempt to boot from the lowest numbered hard drive (e.g. sda or hda) and if it is blank the system will hang. In that case you’ll need a rescue CD capable of running a GRUB boot prompt so you can manually boot from the second physical drive.

There are many free Linux-based rescue CDs available (e.g. SystemRescueCD) but for quick access to GRUB try the Super Grub Disk. This small download can be written to bootable floppy or CDROM and give quick access to system boot tools, especially the GRUB command line.

Whatever rescue tool you use, use it to boot to a GRUB command prompt and force the system to boot from the second installed hard drive using commands similar to the following:

root (hd1,0)
kernel /boot/vmlinuz-whatever root=/dev/md0 ro
initrd /boot/initrd.img-whatever
boot

To find the correct file names for the “kernel” and “initrd” parameters, GRUB has bash-style command-line completion… type just enough of the path then press TAB to auto-complete or see a list of available choices.

Preparing the new drive

Once system as been rebooted with the new unformatted replacement drive in place, some manual intervention is required to partition the drive and add it to the RAID array.

The new drive must have an identical (or nearly identical) partition table to the other. You can use fdisk to manually create a partition table on the new drive identical to the table of the other, or if both drives are identical you can use the “sfdisk” command to duplicate the partition. For example, to copy the partition table from the second drive “sdb” onto the first drive “sda”, the sfdisk command is as follows:

sfdisk –d /dev/sdb | sfdisk /dev/sda

Warning: be careful to specify the right source and destinations drives when using sfdisk or your could blank out the partition table on your good drive.

Once the partitions have been created, you can add them to the corresponding RAID devices using “mdadm –add” commands. For example:

mdadm –add /dev/md0 /dev/sda1
mdadm –add /dev/md1 /dev/sda2

Once added, the Linux kernel immediately starts re-syncing contents of the arrays onto the new drive. You can monitor progress via “cat /proc/mdstat”. Syncing uses idle CPU cycles to avoid overloading a production system, so performance should not be affected too badly. The busier the server (and larger the partitions), the longer the re-sync will take.

You don’t have to wait until all partitions are re-synced… servers can be on-line and in production while syncing is in progress: no data will be lost and eventually all drives will become synchronized.

Summary

Linux software RAID is far more cost effective and flexible than hardware RAID, though it is more complex and requires manual intervention when replacing drives. In most situations, software RAID performance is as good (and often better) than an equivalent hardware RAID solution, all at a lower cost and with greater flexibility. When all you need are mirrored drives, software RAID is often the best choice.

More information on Linux RAID:

Related posts:

Tags:

Copyright © 2010 IT Support Blog All rights reserved. Theme by Laptop Geek.