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

<channel>
	<title>FamousPhil.com Admin Blog and More &#187; Hosting / Server Administration</title>
	<atom:link href="http://famousphil.com/blog/category/hosting-server-administration/feed/" rel="self" type="application/rss+xml" />
	<link>http://famousphil.com</link>
	<description>My Personal Blog</description>
	<lastBuildDate>Mon, 06 Feb 2012 01:40:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Migrating Exchange 2010 to new (upgraded) hardware</title>
		<link>http://famousphil.com/blog/2011/11/migrating-exchange-2010-to-new-upgraded-hardware/</link>
		<comments>http://famousphil.com/blog/2011/11/migrating-exchange-2010-to-new-upgraded-hardware/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 03:01:04 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[active directory]]></category>
		<category><![CDATA[exchange]]></category>
		<category><![CDATA[exchange 2010]]></category>
		<category><![CDATA[migration]]></category>
		<category><![CDATA[owa]]></category>
		<category><![CDATA[Transfer]]></category>
		<category><![CDATA[upgrade]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=1573</guid>
		<description><![CDATA[Phil walks through the process / potential problems of moving Exchange 2010 over to a new server.]]></description>
			<content:encoded><![CDATA[<p>Most of the Matthouse infrastructure is running on old Celeron processors and limited RAM, you may laugh at me, but that hardware has been very reliable and has lasted Matthouse for the better part of 3 years, and some of it may continue to power Matthouse well into the future!  But there are some applications out there that require a little more juice to run well, and (unfortunately) Exchange falls into this category.  I say it is unfortunate since the Exchange server hosts a handful (&lt; 10) mailboxes, yet it costs quite a bit to maintain compared to other Mail Transfer Agents (MTA).  So anyways, this blog is dedicated to the procedure that I took to migrate Exchange over to brand new, shiny, fast hardware.</p>
<p>First, I had Server 2008 R2 Datacenter as my operating system on both the existing server (denoted double) and the new server (denoted ruby).  The servers could clearly communicate with each other within the same datacenter as well so that file / data transfers could be effective.  The first thing to adding any server is to give the new server a name and know its network configuration details ahead of time.  I’m not going to go into details about how to install Windows, since it’s pretty simple.  Just make sure that you have the correct drivers installed for your server after the installation completes.</p>
<p>Note about installing Windows: just so that you don’t run into any issues with your system, make sure that your primary hard drive is attached to the first port for your motherboard’s interface, in my case, the first hard drive was connected to SATA 0.  If you don’t do this, you’ll run into a lot of problems and waste a lot of time (like I did!).  In addition, make sure that your BIOS has AHCI enabled prior to installing Windows, this also caused problems in my scenario.  Once Windows is installed, make sure that you can disable write caching on your hard disk without the operating system freezing (in computer management, under storage, right click the disk and optimize for quick removal).  If you followed the above, this shouldn’t cause Windows to hang, and will prevent Active Directory from incapacitating your system during the restart phase of the installation.  In addition, this is a good time to name your computer, join it to some default workgroup, add remote administration features, and change the time zone / clock settings.</p>
<p>Before continuing, I’d also recommend disabling Internet Explorer’s advanced security features; this is done by going to the computer management main screen and scrolling down, finding IE ESC and turning it off (acknowledging all of the warnings).  If you keep them on, you’ll find yourself doing way too much work to download necessary applications, etc.  These features are only useful if you plan on doing general web surfing on the server (which I would not recommend for security reasons).  I also activated windows, ran all the necessary windows updates (several reboots and optional updates as well).  After this all has been done, I ended up rebooting the machine a final time.</p>
<p>At this point, I installed several applications (using IE to get Google Chrome initially).</p>
<ul>
<li>Google Chrome (<a href="http://chrome.google.com/">http://chrome.google.com</a>) for web surfing / downloading the rest of these</li>
<li>Adblock plus for chrome (<a href="http://adblockplus.org/en/">http://adblockplus.org/en/</a>) to block malware / ads</li>
<li>7zip (<a href="http://www.7-zip.org/download.html">http://www.7-zip.org/download.html</a>) for good archive file support</li>
<li>Microsoft Security Essentials (<a href="http://windows.microsoft.com/en-US/windows/products/security-essentials">http://windows.microsoft.com/en-US/windows/products/security-essentials</a>), Windows 7 version works fine, this is a quick, safe, free antivirus solution for all of those who hate Symantec’s ability to slow down the entire system (hey, that’s me!)   This is also good for desktop users!  I would recommend disabling the scheduled Sunday scan since real-time protection is sufficient in my case.</li>
<li>Magic ISO (<a href="http://www.magiciso.com/tutorials/miso-magicdisc-overview.htm">http://www.magiciso.com/tutorials/miso-magicdisc-overview.htm</a>) to mount ISO images (including the Exchange 2010 ISO if you downloaded it from MSDN like I did).</li>
<li>Office Filter Packs which are a prerequisite for Exchange 2010 (<a href="http://www.microsoft.com/download/en/details.aspx?id=17062">http://www.microsoft.com/download/en/details.aspx?id=17062</a>)<span id="more-1573"></span></li>
</ul>
<p>At this point, I added 2 custom firewall rules on both servers that allowed unrestricted incoming traffic from each server.  I then started the Active Directory installer by installing the AD User Service Role, and then ran DCPromo.exe as suggested by the installer.  I did an advanced mode install, adding a new controller to an existing domain in an existing forest, installing the DNS role locally, and I let it install.  For the AD Restore Password, make sure you remember what you set it to since this will be the password to the local (inaccessible) administrator account on the server incase everything fails.  At this point, the server should reboot at least once on its own.</p>
<p>Next, I mounted the Exchange ISO and went through the step by step screens to install it.  For me, I installed the mailbox, client access, hub transport, and management tools roles.  I told it that the client role would be internet facing to the OWA website (matthouse.org).  Exchange takes roughly 3 hours to install at this point.  After it is done, you should enter the Exchange Management Console (EMC), enter a product key to active it, and add a send connector for your organization (for the new server specifically).  If you’re wondering why your server isn’t sending mail (and you’re new to this and installing Exchange for the first time), try adding a send connector that is internet facing and allows *, that will fix your problem.</p>
<p>You will want to run Windows updates again and make sure that all of the Exchange updates are installed before continuing.  This may require several reboots of the server.</p>
<p>At this point, Exchange should be synched with the other server mostly so it’s time to start migrating services.  I first recommend changing all of your DNS records for mail over to the new server and give them time to propagate (as per the Time to Live [TTL] value on the record).  I also did mailbox remove requests (through the EMC) to the database on the new server; this should be fairly intuitive for anyone with a background in at least some systems administration.  I also went through all the client access role options and made sure that the internal / external sites for IMAP, POP, OWA, OAB, and ECP were properly set up for my main OWA address (matthouse.org).</p>
<p>Since Exchange by default requires <a href="https://server/owa">https://server/owa</a> to gain access to Outlook Web Access [OWA], I needed to add a few files to the web root of the domain to properly forward the user onto the OWA website when they went to the main website.  To do this, simply go to the IIS manager, go to the Default Website, and right click and open the document root.  In here, add 2 files as follows:</p>
<p>Web.config:<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;configuration&gt;<br />
&lt;system.webServer&gt;<br />
&lt;httpErrors&gt;<br />
&lt;error statusCode=&#8221;403&#8243; subStatusCode=&#8221;4&#8243; path=&#8221;https://matthouse.org&#8221; responseMode=&#8221;Redirect&#8221; /&gt;<br />
&lt;/httpErrors&gt;<br />
&lt;/system.webServer&gt;<br />
&lt;/configuration&gt;</p>
<p>Default.aspx</p>
<p>&lt;script language=&#8221;c#&#8221; runat=&#8221;server&#8221;&gt;<br />
private void Page_Load(object sender, System.EventArgs e)<br />
{<br />
Response.Status = &#8220;301 Moved Permanently&#8221;;<br />
Response.AddHeader(&#8220;Location&#8221;,&#8221;https://matthouse.org/owa&#8221;);<br />
}<br />
&lt;/script&gt;</p>
<p>Basically, these 2 files will forward anyone from the web root to the appropriate OWA directory in SSL (https) mode.  I figure that anyone competent can figure out what needs to be changed, it isn’t rocket science, after all.</p>
<p>At this point, I added a real RapidSSL certificate to the server.  To do this, I went to the Exchange Management Console, went to the server tab, found the place to generate a CSR (Certificate Signing Request) and I created one.  I pasted everything from the CA (Certificate Authority) and imported it to Exchange and set all the services to use it (IIS, SMTP, POPS, IMAPS).  I also found the remote desktop session host manager window, right clicked the configuration of the server, and right clicked on rdp-tcp and went to properties.  I selected the general tab, selected the appropriate already installed certificate and ok’d everything, after restarting my RDP session, I had the new secure connection.</p>
<p>For anyone who is curious about anti-spam, there is a hidden anti-spam feature on the Exchange Hub Transport role, to get this, you can run the below steps in the Exchange PowerShell environment.  Afterwards, you will see an Anti-spam option in the Hub Transport role node under the Organization Configuration node of the EMC.  As for me, I opted for Forefront Protection 2010 (formerly Forefront Security 2010) since it provides a much more sophisticated scanning engine, although it does cost more and takes a lot more memory and configuration to get running smoothly.</p>
<ul>
<li>cd /</li>
<li>cd c:\</li>
<li>cd program files</li>
<li>cd microsoft</li>
<li>cd exchange server</li>
<li>cd v14</li>
<li>cd scripts</li>
<li>./install-AntispamAgents.ps1</li>
<li>Restart-Service MSExchangeTransport</li>
</ul>
<p>After all of this, I also found an IE9 / EMC interoperability bug where you can’t close the EMC if IE9 is installed on the system, this seems to be a bug with the Microsoft Management Console (MMC), so the patch can be directly downloaded from Microsoft, I would recommend searching Google for hotfix 2624899 to get the patch.  Keep in mind that a hotfix rollup in the future will include this patch from Microsoft so I’d recommend only installing it if you have this issue.</p>
<p>At this point, I’d recommend securing the firewall, RDP’s port, and adding some backup scripts.</p>
<p>Next, it is time to remove the old server.  I ran the following in the Exchange Management Power Shell Environment: “Get-Mailbox -Arbitration -Database db1 | New-MoveRequest -TargetDatabase db2”, where db1 is on the old server, and db2 is on the new server.  In EMC, I went to the organization node &gt; mailbox &gt; offline address book (OAB), added a new OAB generated by the new server and removed the existing one generated by the old server.  I also went to hub transport under organization, went to send connectors and removed the old server from the send connector.</p>
<p>On the new server, go to Active Directory Sites and Services under Administrative Tools and find each domain controller and view the properties.  Make sure the new domain controller is a global catalog and the old domain controller is not a global catalog server (respectively), these will be under the NTDS settings properties page.  Next, we need to transfer several roles, I used (<a href="http://www.petri.co.il/seizing_fsmo_roles.htm">http://www.petri.co.il/seizing_fsmo_roles.htm</a>) as a guide for this.</p>
<ul>
<li>open command prompt (run cmd)</li>
<li>ntdisutil</li>
<li>roles</li>
<li>connections</li>
<li>connect to server &lt;new domain controller&gt;</li>
<li>q</li>
<li>transfer naming master</li>
<li>transfer infrastructure master</li>
<li>transfer PDC</li>
<li>transfer RID master</li>
<li>transfer schema master</li>
<li>q</li>
</ul>
<p>On the old server, remove the Active Directory Certificate Services role if it exists (you can probably ignore any warnings since Exchange should be using external certificates).  You may have to reboot the server.  Finally, go to add/remove programs on the old server, and remove Exchange 2010 by deselecting all of the roles.  Exchange automatically detects if it is safe to remove everything and will transfer anything left behind over to the new server.  Do the same for Active Directory by running DCPromo.exe (under the Active Directory node of the server management console), and running through the prompt.  If you get any warnings / errors when attempting to remove Exchange / Active Directory, take the advice and don’t continue since you might end up creating a lot more work for yourself.</p>
<p>Once everything is removed, you can trash the old server from the network and Exchange has been successfully moved.  For me, I ended up having about 4 reboots that affected OWA for users for a total of roughly 5 minutes each while Exchange rebooted.</p>
<p>As usual, thanks for reading.  Disclaimer: this information is provided on an as-is basis, I do not guarantee that this will work in your scenario, but I hope that it can help someone else out that is having similar difficulties to the ones that I&#8217;ve described.</p>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/11/migrating-exchange-2010-to-new-upgraded-hardware/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Resetting a Password on Mac OSX (Server)</title>
		<link>http://famousphil.com/blog/2011/08/resetting-a-password-on-mac-osx-server/</link>
		<comments>http://famousphil.com/blog/2011/08/resetting-a-password-on-mac-osx-server/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 03:39:06 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[password]]></category>
		<category><![CDATA[reset]]></category>
		<category><![CDATA[root]]></category>
		<category><![CDATA[single user mode]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=1239</guid>
		<description><![CDATA[Phil gives a step by step guide to resetting a user's password on Mac OS X without knowing the user's password.]]></description>
			<content:encoded><![CDATA[<p>Anymore, it seems like posting here is a seldom activity because I don&#8217;t often deal with server administration issues any longer (although I am working on changing that <img src='http://famousphil.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ).  Today, I was asked to reset the password on a Mac Server because the user didn&#8217;t remember the password.  Personally, I don&#8217;t know how a server oriented password can be lost, but whatever, I guess I&#8217;ve seen it all now <img src='http://famousphil.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Mac, like Linux and its BSD roots, has a flaw when you have physical access to the machine.  Basically, passwords are stored as password hashes in a simple file on the server.  To change the password of any user account, you basically have to gain write access to the said password (or shadow) file and change the hash to something that matches the new desired password.  Typically, this is very easy to do for any kind of Linux or BSD operating system.  For all of you Windows fans, Windows stores the passwords encrypted in SAM files (if I recall correctly), and there are also password reset disks available that you boot from and overwrite the administrator account password with your own password.  Once again, resetting a password is very easy to do to gain access to a machine provided you have physical access.  One tiny exception to this rule on every platform, if the encryption feature is enabled on a user account (provided it exists), the files that were encrypted will never be readable again if you change the password using this method.</p>
<p>Since this is resetting the password of a Mac, I&#8217;m only going to cover the Mac OS.  Mac, like Linux and BSD, has something called single user mode which is basically a recovery environment built into the operating system.  When something doesn&#8217;t work properly, this environment typically boots and gives the local user (on the console) a command prompt that is running as the root user (or superuser).  Typically in single user mode, the local hard disk is read only, but because you are root, you can simply change that to write mode.  Afterwards, its a matter of changing the password.  If you aren&#8217;t a single user mode fan, Mac even puts a reset password link in the utilities menu of their installation disk that does the work manually.</p>
<p>So, using the single user mode shell, here is the procedure to resetting the password of your mac:</p>
<ol>
<li>Shut down the computer</li>
<li>While holding the command (apple) key and S simultaneously, power the computer on</li>
<li>The command line will come up shortly</li>
<li>Type in &#8220;/sbin/mount -wu /&#8221; without the quotes, this enables writing to the root operating system directory</li>
<li>type in &#8220;passwd &lt;user&gt;&#8221;, where &lt;user&gt; is the username whose password needs to be reset</li>
<li>type in &#8220;reboot&#8221;</li>
<li>Login as the user that you reset the password for, using the new password you set.</li>
</ol>
<div>I&#8217;d like to mention that many other tutorials mention a lot of other commands that are required, these aren&#8217;t necessary since they&#8217;re checks on the operating system.  There is also a command called nidump which will give you the password hash to a user, this is useful if you want to spend the time cracking the password.  In my case, that was simply a waste of time.</div>
<div>Hopefully this helps someone else out.</div>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/08/resetting-a-password-on-mac-osx-server/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Crontab Usage Reference</title>
		<link>http://famousphil.com/blog/2011/07/crontab-usage-reference/</link>
		<comments>http://famousphil.com/blog/2011/07/crontab-usage-reference/#comments</comments>
		<pubDate>Mon, 04 Jul 2011 22:58:15 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[crontab]]></category>
		<category><![CDATA[device]]></category>
		<category><![CDATA[file descriptor]]></category>
		<category><![CDATA[syntax]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=1106</guid>
		<description><![CDATA[A reference guide to using crontabs including syntax and explanations to things like >/dev/null 2>&#038;1.]]></description>
			<content:encoded><![CDATA[<p>This blog is something that I know like the back of my hand, but I realize that others may not be as fluent in using crons.  This blog is meant to be a reference to those individuals.  Cron is a unix (and solaris,  BSD) utility that runs tasks automatically in the background at regular intervals, its very similar to the Windows Task Scheduler.  Cron can be referenced as a cron job, or cron tab (cron table).  For simplicity, I will simply call it a cron.</p>
<p><strong>Restrictions:</strong> Crons can be ran if your username is in the cron.allow file, the location of this file varies across different systems.  If the cron.allow file does not exist, and your username does not exist in cron.deny, you can use crons.  The format of each file is one username per line.</p>
<p><strong>Commands:</strong> The most common command I use is &#8220;<em>crontab -e</em>&#8221; which means edit the crons that run under your user account.  This command opens up the default editor of your system to do this.  The &#8220;l&#8221; flag means display the crons that are configured under the user&#8217;s account.  The &#8220;r&#8221; flag removes the current crons under a user&#8217;s account.   Finally, the &#8220;v&#8221; tag shows the last modification time of the cron configuration for a user account, note that this command is not available on all systems.</p>
<p><strong>Syntax:</strong> The cron file is set up with a certain syntax.</p>
<p>The first line can configure a default email address to email the completion (any script output) to or it can immediately start with cron jobs, using the default email address of the account (defined in the .forward file or a local mail queue usually).</p>
<p>Defining an email address on the first line:</p>
<pre class="brush: bash; title: ; notranslate">
#Don't email anything by default
MAILTO=""
#email all cron job completions to admin@example.com by default
MAILTO="admin@example.com"
</pre>
<p>Each subsequent line looks like the following</p>
<pre class="brush: bash; title: ; notranslate">
* * * * * &lt;command&gt;
- - - - -
| | | | |
| | | | +----- day of week (0 - 6) (Sunday=0)
| | | +------- month (1 - 12)
| | +--------- day of month (1 - 31)
| +----------- hour (0 - 23)
+------------- minute (0 - 59)
</pre>
<p>In the above, if you enter * (the wildcard character), the job will run for all possible points of the value.  For example, if you do * for the minute value, this script will run at every minute.  If you want to run a job every second (not recommended), you can specify the minute value as &#8221; */60 &#8221; meaning run at every 60th of a minute.  This is not always supported, but for the majority of systems I use, it is.</p>
<p>The <command> section is the command you would run via command line, for example, if you want to update the spam assassin rules every night at midnight, the command is &#8220;<em>/usr/bin/sa-update</em>&#8220;.  The crontab entry to do this nightly would be &#8221; 0 0 * * * /usr/bin/sa-update &#8220;.</p>
<p><strong>Emails</strong>: Finally, if you want a certain command to not email you regardless of completion, you can do the following (using the above example):</p>
<pre class="brush: bash; title: ; notranslate">
0 0 * * * /usr/bin/sa-update  &gt; /dev/null 2&gt;&amp;amp;1
</pre>
<p>Adding &#8221; > /dev/null 2>&amp;1 &#8221; to the end of the command redirects the output of the script running to the null device (/dev/null), which is a special file that discards all data that is written to it.  Essentially /dev/null is the trash can.  The > symbol is a unix pipe symbol that redirects the output of the left side to a file descriptor (or device) located on the right side.  the &#8220;2>&amp;1&#8243; at the end says pipe the standard error output (device 2) to the standard output device (device 1), so this essentially unifies all error and regular messages from the program so that they both can be sent to /dev/null.  In case you&#8217;re wondering, device 0 is standard input from the command line.  You can understand this a lot more thoroughly by looking at Linux file descriptors and pipes.</p>
<p><strong>Path</strong>: Cron usually invokes commands using (/bin/sh) which is the default shell on most systems, it typically starts in the user&#8217;s home directory with a very simplified PATH.  If you believe your cron isn&#8217;t working properly, try using absolute paths in your commands from /.</p>
<p><strong>Credit</strong>: I&#8217;d like to finally credit <a href="http://adminschoice.com/crontab-quick-reference">http://adminschoice.com/crontab-quick-reference</a> in helping me make my reference more comprehensive, I didn&#8217;t want to completely write this from my own experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/07/crontab-usage-reference/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Revisiting Exchange 2010 SP1 PST Backups (Improved Script)</title>
		<link>http://famousphil.com/blog/2011/07/revisiting-exchange-2010-sp1-pst-backups-improved-script/</link>
		<comments>http://famousphil.com/blog/2011/07/revisiting-exchange-2010-sp1-pst-backups-improved-script/#comments</comments>
		<pubDate>Mon, 04 Jul 2011 01:33:16 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[exchange 2010]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[pst]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=1096</guid>
		<description><![CDATA[Phil revisits his Exchange 2010 SP1 PST backup script and introduces some server optimization tricks and an improved powershell script that emails detailed backup completion statuses. ]]></description>
			<content:encoded><![CDATA[<p>Over the past couple of months, I&#8217;ve found that the script that I posted at <a href="http://famousphil.com/blog/2011/01/a-decent-backup-strategy-for-exchange-2010-sp1/">http://famousphil.com/blog/2011/01/a-decent-backup-strategy-for-exchange-2010-sp1/</a> hasn&#8217;t been working perfectly for my needs.  This relatively short blog is kind of a back track blog to explain the issues and provide some fixes for them.</p>
<p>The original script I posted does not verify that the backups actually completed.  The emails I got were simply gibberish.  I was willing to accept that for a while until during monthly maintenance when I manually verify backups, I was finding that backups didn&#8217;t always complete.  I&#8217;ve tracked this down in the error logs and found that the memory in the server isn&#8217;t enough for the backups at times which has them fail at certain times.  Due to the lack of user base on my server (4 light users), I can&#8217;t justify adding more ram (I currently have 4GB) because I&#8217;d have to upgrade the entire server.  So instead, I did some RAM optimization and re-wrote the backup script to email me the actual backup names that completed successfully.</p>
<p>First for the tips.  I recently learned that Active Directory can be modified from the backend, so using this, I modified the Information Store service (store.exe) in Exchange to only use at most 512MB of ram.  I used the information at <a href="http://terrytlslau.blogspot.com/2011/03/limiting-exchange-server-2007-and-2010.html">http://terrytlslau.blogspot.com/2011/03/limiting-exchange-server-2007-and-2010.html</a> for doing this, I briefly repeat the procedure here in the even that this link is no longer reachable.</p>
<pre class="brush: bash; title: ; notranslate">
1. At Domain Controller, login as a Domain Administrator.
2. Click &quot;Start&quot;, enter &quot;adsiedit.msc&quot; into the search box, hit enter.
3. Right-click &quot;ADSI Edit&quot;, select &quot;Connect to&quot;.
4. Enable the Naming Context view, click ok to connect
4. Under the &quot;Naming Context&quot; menu, select &quot;Configuration&quot;.
6. Expand to &quot;Configuration &gt; Services &gt; Microsoft Exchange &gt;  &gt; Administrative Groups &gt; Exchnage Administrative Group &gt; Servers &gt;  &gt; InformationStore&quot;.
7. Right-click &quot;InformationStore&quot;, select &quot;Properties&quot;.
8. Select &quot;msExchESEParamCacheSizeMax&quot;.
9. This value is set in pages, in Exchange 2010 the size is 32KB/page; Exchange 2007 is 8KB/page.  Simply figure out the number of pages for the amount of ram you want to limit store.exe to using.

For instance, if you want to limit the Database Cache to 4 GB of an Exchange 2010 server, set msExchESEParamCacheSizeMax to 131072 (4 GB = 4.194.304 KB / 32 KB). If you want to limit the Database Cache to 2 GB of an Exchange 2007 server, set msExchESEParamCacheSizeMax to 262144 (2 GB = 2.097.152 KB / 8KB).
10. Ok everything and restart the Information Store service (possibly the server)
</pre>
<p>After limiting the Exchange Information Store service, I simply restarted the Information Store service and that seems to have fixed the gouging memory issue.</p>
<p>As a second optimization procedure, I started tackling the IIS Worker Processes.  Exchange has several application pools that it uses, you can think of an application pool in IIS as a separate instance of Tomcat or Apache for each website.  Application Pools isolate websites to that they can&#8217;t affect each other.  On the downside, application pools also hog a great amount of memory and for the features of Exchange that you may not use often (e.g. powershell, calendar, exchange control panel), it takes some time for these features to load initially (for me, its about 30 seconds).  My solution was to limit Exchange to two application pools.  For anything service related, I used the Exchange Service Pool (e.g. EWS, Powershell, Autodiscover), and anything client site based (e.g. OWA, Calendar, ECP, ActiveSync) in the OWA pool.  I still do not know if any update to Exchange may reverse this or break this, but I do keep it in mind during updates.  The result of doing this is that not only is memory consumption reduced significantly, but Outlook Web Access, Exchange&#8217;s Calendar display (for the public), and Exchange Control Panel all load much faster now since the overhead in IIS is already loaded.  Of course, I wouldn&#8217;t recommend doing this unless you can&#8217;t easily upgrade the amount of memory in your server.</p>
<p>Finally, I will leave you with an improved export script that replaces the script in my previous blog at <a href="http://famousphil.com/blog/2011/01/a-decent-backup-strategy-for-exchange-2010-sp1/">http://famousphil.com/blog/2011/01/a-decent-backup-strategy-for-exchange-2010-sp1/</a>.  This script verifies that all of the users were actually uploaded and emails the complete report to you (instead of some garble).  I&#8217;ve found it to be very helpful in determining if a mailbox was failing to export to a PST without having to login to the file server and check.  As always, use this script at your own risk, I am willing to provide limited support as time permits.</p>
<pre class="brush: powershell; title: ; notranslate">
# Exchange 2010 SP1 Mailbox Export Script
# Originally from Steve Goodman.
# Modified by Philip Matuskiewicz for Matthouse.us / famousphil.com 1/2/11 FIXED *7/2/11*

#define information here
$server = &quot;host.example.com&quot; #server hostname
$users = @(&quot;Joe&quot;, &quot;Mary&quot;, &quot;Phil&quot;) #users to archive
$destination = &quot;localhostpstbackups&quot; #network share to backup to
$emailfrom = &quot;server@yourdomain.com&quot;
$emailto = &quot;you@yourdomain.com&quot;
#define some internal variables
$output = &quot;&quot;
$error = 0
$date = Get-Date

#check for errors
if (!(Get-ExchangeServer $server -ErrorAction SilentlyContinue)){
    $output += &quot;Exchange Server $server not found`n&quot;;
	$error = 1
}
if (!(Get-MailboxDatabase -Server $server -ErrorAction SilentlyContinue)){
    $output += &quot;Exchange Server $server does not have mailbox databases&quot;;
	$error = 1
}

#create a batch job if the above tests succeeded
if ($error -ne 1){

	$jobname = &quot;Export_$($date.Year)-$($date.Month)-$($date.Day)_$($date.Hour)-$($date.Minute)-$($date.Second)&quot;
	$output += &quot;Job title is: '$($jobname)' `n&quot;
	Write-Output &quot;Job title is: '$($jobname)' &quot;

	foreach ($mailbox in $users){
		#remove existing PST file
		if (Get-Item &quot;$($destination)$($mailbox).PST&quot; -ErrorAction SilentlyContinue){
			Remove-Item &quot;$($destination)$($mailbox).PST&quot; -Confirm:$false
			$output += &quot;Existing PST was deleted (Normal): '$($mailbox)' `n&quot;
			Write-Output &quot;Existing PST was deleted (Normal): '$($mailbox)' &quot;
		} # end if

		#request a backup of the mailbox, Exclude the recoverable items / deleted items
		$mailboxjobname = &quot;$($mailbox)-$($jobname)&quot;
		New-MailboxExportRequest -BatchName $jobname -Mailbox $($mailbox) -FilePath &quot;$($destination)$($mailbox).PST&quot; -ExcludeDumpster -Name $mailboxjobname
		$output += &quot;Mailbox Queued: '$($mailbox)' `n&quot;
		Write-Output &quot;Mailbox Queued: '$($mailbox)' &quot;

	} #end foreach
} #end $error -ne 1

#wait for the jobs to complete
$time = 0;
while ((Get-MailboxExportRequest -BatchName $jobname | Where {$_.Status -eq &quot;Queued&quot; -or $_.Status -eq &quot;InProgress&quot;})){
	Write-Output &quot;Waiting on backup, it has been $($time) seconds&quot;
	$output += &quot;Waiting on backup, it has been $($time) seconds `n&quot;
	sleep 600 #10 minutes
	$time = $time + 720;
} #end while

#check for any jobs that didn't complete
$incomplete = Get-MailboxExportRequest -BatchName $jobname | Where {$_.Status -ne &quot;Completed&quot;} | Get-MailboxExportRequestStatistics | Format-List
$complete = Get-MailboxExportRequest -BatchName $jobname | Where {$_.Status -eq &quot;Completed&quot;} | Get-MailboxExportRequestStatistics | Format-List

if($incomplete){
	Write-Output &quot;ERROR: Something didn't complete, output is '$($incomplete)'&quot;
	$output += &quot;ERROR: Something didn't complete, output is '$($incomplete)' `n&quot;
}

if($complete){
	Write-Output &quot;Completed Successfully, output is '$($complete)'&quot;
	$output += &quot;Completed Successfully, output is '$($complete)' `n&quot;
}

# Remove Requests and clean up
Write-Output &quot;Cleaning up requests that were part of the job '$($jobname)'&quot;
$output += &quot;Cleaning up requests that were part of the job '$($jobname)' `n&quot;
Get-MailboxExportRequest -BatchName $jobname | Remove-MailboxExportRequest -Confirm:$false

#verify that all the PST files were created...
foreach ($mailbox in $users){
		#remove existing PST file
		if (Get-Item &quot;$($destination)$($mailbox).PST&quot; -ErrorAction SilentlyContinue){
			$output += &quot;PST FOUND!!!: '$($mailbox)' `n&quot;
			Write-Output &quot;PST FOUND!!!: '$($mailbox)' &quot;
		}else{
			$output += &quot;ERROR: PST NOT FOUND: '$($mailbox)' `n&quot;
			Write-Output &quot;ERROR: PST NOT FOUND: '$($mailbox)' &quot;
		}
}

$SmtpClient = new-object system.net.mail.smtpClient(&quot;double.matthouse.org&quot;)
$msg = new-object Net.Mail.MailMessage
$msg.From = &quot;$($emailfrom)&quot;
$msg.To.Add(&quot;$($emailto)&quot;)
$msg.Subject = &quot;EXCHANGE EMAIL BACKUP DETAILS&quot;
$msg.Body = $output
$SmtpClient.Send($msg)

Write-Output &quot;Script complete!&quot;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/07/revisiting-exchange-2010-sp1-pst-backups-improved-script/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Unzipping and Zipping large files (2GB+)</title>
		<link>http://famousphil.com/blog/2011/07/unzipping-and-zipping-large-files-2gb/</link>
		<comments>http://famousphil.com/blog/2011/07/unzipping-and-zipping-large-files-2gb/#comments</comments>
		<pubDate>Sat, 02 Jul 2011 19:58:59 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[archive]]></category>
		<category><![CDATA[end-of-central-directory signature]]></category>
		<category><![CDATA[large file]]></category>
		<category><![CDATA[large file support]]></category>
		<category><![CDATA[Unzip]]></category>
		<category><![CDATA[Zip]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=1088</guid>
		<description><![CDATA[How to add large file support to the unzip utility in Linux (Source Code version), also works for the zip utility.]]></description>
			<content:encoded><![CDATA[<p>Last night, I was tasked with moving 25,000 files (3GB worth) between two of my Linux systems.  Traditionally, I use tar and gunzip (<em>tar czf file.tar.gz directory/</em>) to archive files for network transfer, but for whatever reason, I used the zip utility that is bundled with most Linux distributions (<em>zip -r file.zip directory/</em>).</p>
<p>The zip process went through fine and created a zip archive of the directory, but this is because the zip was done on a 64 bit build of CentOS Linux (where zip is compiled for large file support).  I transferred the archive to the destination server (32 bit build of CentOS Linux).  As any decent admin does, I verified that the checksum (<em>openssl md5 file.zip</em>) matched on both ends (to check for corruption).  The md5 checksums matched, so I proceeded to unzip the file (<em>unzip file.zip</em>).  Below is the error I received:</p>
<pre class="brush: bash; title: ; notranslate">
End-of-central-directory signature not found. Either this file is nota zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive.

unzip: cannot find zipfile directory in one of file.zip or
file.zip.zip, and cannot find file.zip.ZIP, period.
</pre>
<p>It turns out that the 32 bit version of CentOS includes the zip utility that isn&#8217;t compiled with large file support.  To rectify this, we must download the zip source code and recompile with large file support.  The instructions that I used are at <a href="http://www.stevenbarre.com/blog/2007/03/04/how-to-unzip-large-files-greater-than-2-gb/">http://www.stevenbarre.com/blog/2007/03/04/how-to-unzip-large-files-greater-than-2-gb/</a></p>
<p>1. install zlib and zlib_devel using yum if you don&#8217;t already have them.</p>
<p>2. Download the source code of unzip from <a href="http://www.info-zip.org/">http://www.info-zip.org/</a>.</p>
<pre class="brush: bash; title: ; notranslate">
wget http://sourceforge.net/projects/infozip/files/UnZip%205.x%20and%20earlier/5.52/unzip552.tar.gz/download
</pre>
<p>3. Extract the source code and move the appropriate make file to the main directory</p>
<pre class="brush: bash; title: ; notranslate">
tar xzf unzip552.tar.gz
cd unzip-5.52/
mv unix/Makefile ./
</pre>
<p>4. Modify the MakeFile to enable large file support</p>
<p>Find:</p>
<pre class="brush: plain; title: ; notranslate">
CF=&quot;-O3 -Wall -I. -DASM_CRC $(LOC)&quot;
</pre>
<p>Replace With:</p>
<pre class="brush: plain; title: ; notranslate">
CF=&quot;-O3 -Wall -I. -DASM_CRC -DLARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(LOC)&quot;
</pre>
<p>5. Compile unzip</p>
<pre class="brush: bash; title: ; notranslate">
make linux
</pre>
<p>6. Use the executable unzip to extract file.zip</p>
<pre class="brush: bash; title: ; notranslate">
#assume file.zip is at /root/test/file.zip
mv unzip /root/test
cd ..
#clean up the directory, remove unzip's source code
rm -Rf unzip-5.52
rm unzip552.tar.gz
#unzip the file
cd /root/test
./unzip file.zip
</pre>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/07/unzipping-and-zipping-large-files-2gb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharing a screen session</title>
		<link>http://famousphil.com/blog/2011/07/sharing-a-screen-session/</link>
		<comments>http://famousphil.com/blog/2011/07/sharing-a-screen-session/#comments</comments>
		<pubDate>Fri, 01 Jul 2011 18:22:48 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[screen]]></category>
		<category><![CDATA[shared session]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=1082</guid>
		<description><![CDATA[Phil discusses the basic usage of screen and how to share a screen session.  He also discusses the fix to a permissions problem which denies normal users from using screen.]]></description>
			<content:encoded><![CDATA[<p>Often times, I find myself working in a remote Linux terminal window. The other day, I had the need to share what I was doing with a friend, but I didn&#8217;t want to share my entire local desktop because sharing a full desktop is slow and laggy. So I quickly looked into sharing a screen session with him so he&#8217;d only see the command line window that I was in, and I know I will need it again, so its going up here.  For those of you who have a Mac or Linux, you might know that you can have multiple desktops and go through them by some key combination (usually ctrl-alt-arrow).  In a very simplified nutshell, screen basically allows for the user to exploit multiple desktops.</p>
<p>Here is how you share a screen session:</p>
<pre class="brush: bash; title: ; notranslate">
#User 1, initiator of the screen session
screen -R sessionName

#User 2, connecting to an existing session
screen -x -R sessionName
</pre>
<p>The -R flag means try to reattach to an existing session, if the existing session does not exist, create a new session and attach to that.  The -x flag means to connect to an already attached session, which allows for session sharing.</p>
<p>I ran into a problem as a non-root user (that I normally run as) when I first started using shared screen sessions.  The error is as follows:</p>
<pre class="brush: bash; title: ; notranslate">
Cannot open your terminal '/dev/pts/0' - please check.
</pre>
<p>There are several terminal devices that screen can use under the /dev/pts directory, starting with 0.  Only root can traditionally access these terminal devices, therefore, we need to modify each necessary device to allow normal users access.  I didn&#8217;t research the security implications that the following fix has, so use this at your own risk.  The server that I was using has only trusted users on it, so I was not concerned about possible risks.</p>
<pre class="brush: bash; title: ; notranslate">
#run this as root, or as sudo
#this gives others read and write access to the device
chmod o+rw /dev/pts/0
</pre>
<p>Finally, up until last week, I could never get myself out of a screen session safely without completely closing my putty terminal window.  Here is the proper key sequence to detach from a screen session.</p>
<pre class="brush: bash; title: ; notranslate">
ctrl-A  followed by  ctrl-D
</pre>
<p>To terminate a session in screen, simply type exit.</p>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/07/sharing-a-screen-session/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Installing Nagios to CentOS 5</title>
		<link>http://famousphil.com/blog/2011/06/installing-nagios-to-centos-5/</link>
		<comments>http://famousphil.com/blog/2011/06/installing-nagios-to-centos-5/#comments</comments>
		<pubDate>Sun, 19 Jun 2011 02:41:31 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[monitor]]></category>
		<category><![CDATA[nagios]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=838</guid>
		<description><![CDATA[Phil describes the procedure for installing, upgrading, and configuring Nagios as a server monitoring solution for Windows and Linux machines.]]></description>
			<content:encoded><![CDATA[<p>This is a topic that I should have blogged about a long time ago (when I actually did it), but I was busy at the time and stuff gets pushed onto a back burner (or even the freezer) when I don’t have the time.  Oh well, this article is better late than never.  I will also provide a script that powers <a href="https://www.matthouse.us/status.php">https://www.matthouse.us/status.php</a>.</p>
<p>Nagios is a server monitoring solution that can monitor entire systems and services running on those systems.  For Matthouse, Nagios runs on a reliable virtual private server that has a SLA to be up all of the time, the provider I choose has complete redundancy so that this VPS will not go down due to localized hardware, network, or power failures.  Nagios also runs on a system that is completely off-site from all of my other servers, so it can see if a datacenter goes down and notify me properly.  If you’re going to host Nagios yourself, I’d strongly suggest getting a similar setup since you don’t want your monitoring system to fail with everything else!</p>
<p>So let’s get into the actual installation of Nagios. <strong>(THIS WAS UPDATED 6/23/11)</strong><span id="more-838"></span></p>
<p>We first need to install some supporting packages through yum and make a user that Nagios will work under.</p>
<pre class="brush: bash; title: ; notranslate">
yum install gcc glibc glibc-common gd gd-devel
/usr/sbin/useradd -d /home/nagios nagios
#You probably don't need to set the password
passwd nagios
&lt;CHOOSE A PASSWORD&gt;
groupadd nagcmd
usermod -a -G nagcmd nagios
usermod -a -G nagcmd apache
</pre>
<p>Now, as the user nagios, we want to download the latest version of Nagios.  My recommendation is to visit <a href="http://www.nagios.org/download/core/thanks/">http://www.nagios.org/download/core/thanks/</a> and download the latest stable release.  As of this blog, the latest release is 3.2.3, which is what I will use in the next section.</p>
<pre class="brush: bash; title: ; notranslate">
su nagios
cd ~
wget http://prdownloads.sourceforge.net/sourceforge/nagios/nagios-3.2.3.tar.gz
tar xzf nagios-3.2.3.tar.gz
cd nagios-3.2.3
./configure --with-command-group=nagcmd
make all
make install
#initialize the Nagios configuration files for the first time
make install-init
make install-config
make install-commandmode
</pre>
<p>Congratulations, Nagios is now installed.  Now you need to change to the /usr/local/nagios/etc directory and start modifying configuration files.  I’m going to provide some sample configuration files that I use in production, your environment may require different options to be specified.  Don’t worry about the check_nrpe command for now; we will be installing that onto the remote server(s) in a little while (before starting the Nagios service).</p>
<pre class="brush: plain; title: ; notranslate">
cat /usr/local/nagios/etc/nagios.cfg

log_file=/usr/local/nagios/var/nagios.log
cfg_file=/usr/local/nagios/etc/objects/commands.cfg
cfg_file=/usr/local/nagios/etc/objects/contacts.cfg
cfg_file=/usr/local/nagios/etc/objects/startup.cfg
cfg_file=/usr/local/nagios/etc/objects/templates.cfg
cfg_dir=/usr/local/nagios/etc/servers
object_cache_file=/usr/local/nagios/var/objects.cache
precached_object_file=/usr/local/nagios/var/objects.precache
resource_file=/usr/local/nagios/etc/resource.cfg
status_file=/usr/local/nagios/var/status.dat
status_update_interval=30
nagios_user=nagios
nagios_group=nagios
check_external_commands=1
command_check_interval=-1
command_file=/usr/local/nagios/var/rw/nagios.cmd
external_command_buffer_slots=4096
lock_file=/usr/local/nagios/var/nagios.lock
temp_file=/usr/local/nagios/var/nagios.tmp
temp_path=/tmp
event_broker_options=-1
log_rotation_method=d
log_archive_path=/usr/local/nagios/var/archives
use_syslog=1
log_notifications=1
log_service_retries=1
log_host_retries=1
log_event_handlers=1
log_initial_states=0
log_external_commands=1
log_passive_checks=1
service_inter_check_delay_method=s
max_service_check_spread=30
service_interleave_factor=s
host_inter_check_delay_method=s
max_host_check_spread=30
max_concurrent_checks=0
check_result_reaper_frequency=10
max_check_result_reaper_time=30
check_result_path=/usr/local/nagios/var/spool/checkresults
max_check_result_file_age=3600
cached_host_check_horizon=15
cached_service_check_horizon=15
enable_predictive_host_dependency_checks=1
enable_predictive_service_dependency_checks=1
soft_state_dependencies=0
auto_reschedule_checks=0
auto_rescheduling_interval=30
auto_rescheduling_window=180
sleep_time=0.25
service_check_timeout=60
host_check_timeout=30
event_handler_timeout=30
notification_timeout=30
ocsp_timeout=5
perfdata_timeout=5
retain_state_information=1
state_retention_file=/usr/local/nagios/var/retention.dat
retention_update_interval=60
use_retained_program_state=1
use_retained_scheduling_info=1
retained_host_attribute_mask=0
retained_service_attribute_mask=0
retained_process_host_attribute_mask=0
retained_process_service_attribute_mask=0
retained_contact_host_attribute_mask=0
retained_contact_service_attribute_mask=0
interval_length=30
check_for_updates=1
bare_update_check=0
use_aggressive_host_checking=0
execute_service_checks=1
accept_passive_service_checks=1
execute_host_checks=1
accept_passive_host_checks=1
enable_notifications=1
enable_event_handlers=1
process_performance_data=0
obsess_over_services=0
obsess_over_hosts=0
translate_passive_host_checks=0
passive_host_checks_are_soft=0
check_for_orphaned_services=1
check_for_orphaned_hosts=1
check_service_freshness=1
service_freshness_check_interval=60
check_host_freshness=0
host_freshness_check_interval=60
additional_freshness_latency=15
enable_flap_detection=0
low_service_flap_threshold=5.0
high_service_flap_threshold=20.0
low_host_flap_threshold=5.0
high_host_flap_threshold=20.0
date_format=us
p1_file=/usr/local/nagios/bin/p1.pl
enable_embedded_perl=1
use_embedded_perl_implicitly=1
illegal_object_name_chars=`~!$%^&amp;amp;*|'&quot;?,()=
illegal_macro_output_chars=`~$&amp;amp;|'&quot;
use_regexp_matching=0
use_true_regexp_matching=0
admin_email=root@localhost
admin_pager=root@localhost
daemon_dumps_core=0
use_large_installation_tweaks=0
enable_environment_macros=1
debug_level=0
debug_verbosity=1
debug_file=/usr/local/nagios/var/nagios.debug
max_debug_file_size=1000000
</pre>
<pre class="brush: plain; title: ; notranslate">
cat /usr/local/nagios/etc/objects/command.cfg

define command{
        command_name        notify-host-by-email
        command_line        /usr/bin/printf &quot;%b&quot; &quot;***** Nagios *****nnNotification Type: $NOTIFICATIONTYPE$nHost: $HOSTNAME$nState: $HOSTSTATE$nAddress: $HOSTADDRESS$nInfo: $HOSTOUTPUT$nnDate/Time: $LONGDATETIME$n&quot; | /bin/mail -s &quot;** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **&quot; $CONTACTEMAIL$
}

define command{
        command_name        notify-service-by-email
        command_line        /usr/bin/printf &quot;%b&quot; &quot;***** Nagios *****nnNotification Type: $NOTIFICATIONTYPE$nnService: $SERVICEDESC$nHost: $HOSTALIAS$nAddress: $HOSTADDRESS$nState: $SERVICESTATE$nnDate/Time: $LONGDATETIME$nnAdditional Info:nn$SERVICEOUTPUT$&quot; | /bin/mail -s &quot;** $NOTIFICATIONTYPE$ Service Alert: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$ **&quot; $CONTACTEMAIL$
}

define command{
        command_name        check_nrpe
        command_line        $USER1$/check_nrpe -H $HOSTADDRESS$ -p 5666 -c $ARG1$
}

define command{
        command_name        check_ping
        command_line        $USER1$/check_ping -H $HOSTADDRESS$ -w $ARG1$ -c $ARG2$ -p 5
}

define  command {
        command_name        check_bl
        command_line        $USER1$/check_bl -H $HOSTADDRESS$ -B zen.spamhaus.org bl.spamcop.net dnsbl.ahbl.org dnsbl.njabl.org dnsbl.sorbs.net virbl.dnsbl.bit.nl rbl.efnet.org phishing.rbl.msrbl.net 0spam.fusionzero.com list.dsbl.org multihop.dsbl.org unconfirmed.dsbl.org will-spam-for-food.eu.org blacklist.spambag.org blackholes.brainerd.net blackholes.uceb.org spamsources.dnsbl.info map.spam-rbl.com ns1.unsubscore.com psbl.surriel.com l2.spews.dnsbl.sorbs.net bl.csma.biz sbl.csma.biz dynablock.njabl.org no-more-funn.moensted.dk  ubl.unsubscore.com dnsbl-1.uceprotect.net dnsbl-2.uceprotect.net dnsbl-3.uceprotect.net spamguard.leadmon.net opm.blitzed.org bl.spamcannibal.org rbl.schulte.org dnsbl.ahbl.org virbl.dnsbl.bit.nl combined.rbl.msrbl.net
}

define command{
        command_name        check_nt
        command_line        $USER1$/check_nt -H $HOSTADDRESS$ -p 12489 -s nID83kjIUHShsi -v $ARG1$ $ARG2$
}
</pre>
<pre class="brush: plain; title: ; notranslate">
cat /usr/local/nagios/etc/objects/contacts.cfg
#You can define many contacts here

define contact{
        contact_name           nagiosadmin
        use                               generic-contact
        alias                             Nagios Admin
        email                           admin@matthouse.us
}
define contactgroup{
        contactgroup_name      admins
        alias                                  Nagios Administrators
        members                         nagiosadmin, nagiosadminpage
}&lt;/pre&gt;
</pre>
<pre class="brush: plain; title: ; notranslate">
&lt;pre&gt;cat /usr/local/nagios/etc/objects/startup.cfg

define hostgroup{
        hostgroup_name   generic-servers
        alias            Production Server
}

define timeperiod{
        timeperiod_name 24x7
        alias           24 Hours A Day, 7 Days A Week
        sunday          00:00-24:00
        monday          00:00-24:00
        tuesday         00:00-24:00
        wednesday       00:00-24:00
        thursday        00:00-24:00
        friday          00:00-24:00
        saturday        00:00-24:00
}&lt;/pre&gt;
</pre>
<p>Finally, we need to add servers.  Below are two sample configuration files, one that monitors the CPanel server (bit.matthouse.us), another that monitors our Exchange server(double.matthouse.us), and one that monitors the local monitoring server (short.matthouse.us).  We only want to configure servers after we have installed NRPE on the remote server(s) (as below).  For now, it is probably best to only configure the local server.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;pre&gt;cat /usr/local/nagios/etc/servers/bit.cfg

define host{
        use                             generic-server
        host_name                       bit.matthouse.us
        alias                           Matthouse CPanel Web Server
        address                         64.85.172.184
}
define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             Not on Any Spam Blacklists
        check_command                   check_bl
}
define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             Disk: SMART STATUS System Drive
        check_command                   check_nrpe!check_smarta
}
define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             PING
        check_command                   check_ping!150.0,20%!500.0,60%
}
define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             Uptime
        check_command                   check_nrpe!check_uptime
}

define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             Total Processes
        check_command                   check_nrpe!check_total_procs
}

define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             SWAP
        check_command                   check_nrpe!check_swap
}

define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             Current Load
        check_command                   check_nrpe!check_load
}

define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             Disk: Root Partition
        check_command                   check_nrpe!check_root
}

define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             Disk: Tmp Partition
        check_command                   check_nrpe!check_tmp
}

define service{
        use                             generic-service
        host_name                       bit.matthouse.us
        service_description             Disk: Home Partition
        check_command                   check_nrpe!check_home
}&lt;/pre&gt;
</pre>
<pre class="brush: plain; title: ; notranslate">
&lt;pre&gt;cat /usr/local/nagios/etc/servers/double.cfg

define host{
        use                          generic-server
        host_name                    double.matthouse.us
        alias                        Double - Exchange 2010 Server
        address                      64.85.167.224
}
define service{
        use                          generic-service
        host_name                    double.matthouse.us
        service_description          PING
        check_command                check_ping!150.0,20%!500.0,60%
}
define service{
        use                          generic-service
        host_name                    double.matthouse.us
        service_description          NSClient++ Version
        check_command                check_nt!CLIENTVERSION
}
define service{
        use                          generic-service
        host_name                    double.matthouse.us
        service_description          Uptime
        check_command                check_nt!UPTIME
}
define service{
        use                          generic-service
        host_name                    double.matthouse.us
        service_description          CPU Load
        check_command                check_nt!CPULOAD!-l 60,99,100
}
define service{
        use                          generic-service
        host_name                    double.matthouse.us
        service_description          C: Drive Space
        check_command                check_nt!USEDDISKSPACE!-l c -w 80 -c 90
}
define service{
        use                          generic-service
        host_name                    double.matthouse.us
        service_description          D: Drive Space
        check_command                check_nt!USEDDISKSPACE!-l d -w 97 -c 99
}
define service{
        use                          generic-service
        host_name                    double.matthouse.us
        service_description          Not on Any Spam Blacklists
        check_command                check_bl
}&lt;/pre&gt;
</pre>
<pre class="brush: plain; title: ; notranslate">
&lt;pre&gt;cat /usr/local/nagios/etc/servers/short.cfg

define host{
        use                     generic-server
        host_name               short.matthouse.us
        alias                   Short - Main Site, Backup, SVN, Monitoring Server
        address                 127.0.0.1
}

define command{
        command_name    check_disk
        command_line    $USER1$/check_disk -w $ARG1$ -c $ARG2$ -p $ARG3$
}
define command{
        command_name    check_localram
        command_line    $USER1$/check_mem -w 1 -c .1 -f
}
define  command {
        command_name    check_local_uptime
        command_line    $USER1$/check_uptime
}
define command{
        command_name    check_procs
        command_line    $USER1$/check_procs -w $ARG1$ -c $ARG2$ -s $ARG3$
}
define command{
        command_name    check_load
        command_line    $USER1$/check_load -w $ARG1$ -c $ARG2$
}

define service{
        use                             generic-service
        host_name                       short.matthouse.us
        service_description             Root Partition
        check_command                   check_disk!10%!5%!/
}
define service{
        use                             generic-service
        host_name                       short.matthouse.us
        service_description             Memory
        check_command                   check_localram
}
define service{
        use                             generic-service
        host_name                       short.matthouse.us
        service_description             Uptime
        check_command                   check_local_uptime
}
define service{
        use                             generic-service
        host_name                       short.matthouse.us
        service_description             Total Processes
            check_command               check_procs!250!400!RSZDT
}
define service{
        use                             generic-service
        host_name                       short.matthouse.us
        service_description             Current Load
        check_command                   check_load!5.0,4.0,3.0!10.0,6.0,4.0
}
define service{
        use                             generic-service
        host_name                       short.matthouse.us
        service_description             Not on Any Spam Blacklists
        check_command                   check_bl
}&lt;/pre&gt;
</pre>
<p>Up next, we need to create a username and password for the Nagios configuration web page (to protect it).</p>
<pre class="brush: bash; title: ; notranslate">
&lt;pre&gt;cd ~nagios/nagios-3.2.3
make install-webconf
htpasswd -c /usr/local/nagios/etc/htpasswd.users nagiosadmin
#enter a password, the user nagiosadmin will be the username to the Nagios website interface
#exit to root to execute the following command
service httpd restart&lt;/pre&gt;
</pre>
<p>There is a small chance that I modified the Apache configuration to make <a href="http://www.matthouse.us/nagios">http://www.matthouse.us/nagios</a> the website interface.  Therefore, I am including the configuration file that works on my server.  You will want to remove the suPHP directive if your server doesn’t run suPHP (unlike mine).  If you are using suPHP, you will need to modify your suphp.conf file (under /etc), I had to set “docroot=/” since my web files were under /home and nagios is under /usr.  This isn’t a huge security risk provided none of your PHP scripts are owned by root, but you may want to install nagios under /home to tighten this up slightly.</p>
<p>As an aside, suPHP is a module for Apache that runs all PHP scripts as the user who owns those scripts (instead of apache or nobody).  This helps isolate PHP attacks to only the files that the user owns.  suPHP is fairly easy to install so I will leave that up to the user.  If someone requests the installation procedure, I might blog about it in the future.</p>
<p>&lt;pre&gt;cat /etc/httpd/conf.d/nagios.conf</p>
<p>ScriptAlias /nagios/cgi-bin &quot;/usr/local/nagios/sbin&quot;<br />
&lt;Directory &quot;/usr/local/nagios/sbin&quot;&gt;<br />
#  SSLRequireSSL<br />
   Options ExecCGI<br />
   AllowOverride None<br />
   Order allow,deny<br />
   Allow from all<br />
#  Order deny,allow<br />
#  Deny from all<br />
#  Allow from 127.0.0.1<br />
   AuthName &quot;Nagios Access&quot;<br />
   AuthType Basic<br />
   AuthUserFile /usr/local/nagios/etc/htpasswd.users<br />
   Require valid-user<br />
   suPHP_Engine on<br />
   suPHP_UserGroup nagios nagios<br />
&lt;/Directory&gt;<br />
Alias /nagios &quot;/usr/local/nagios/share&quot;<br />
&lt;Directory &quot;/usr/local/nagios/share&quot;&gt;<br />
#  SSLRequireSSL<br />
   Options None<br />
   AllowOverride None<br />
   Order allow,deny<br />
   Allow from all<br />
#  Order deny,allow<br />
#  Deny from all<br />
#  Allow from 127.0.0.1<br />
   AuthName &quot;Nagios Access&quot;<br />
   AuthType Basic<br />
   AuthUserFile /usr/local/nagios/etc/htpasswd.users<br />
   Require valid-user<br />
   suPHP_Engine on<br />
   suPHP_UserGroup nagios nagios<br />
&lt;/Directory&gt;&lt;/pre&gt;</p>
<p>Next, we need to install nagios-plugins to enable the actual server check commands.  These will also be installed on each server that we monitor using NRPE.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;pre&gt;su nagios
cd ~
#get the latest plugins from http://www.nagios.org/download/plugins/
wget http://prdownloads.sourceforge.net/sourceforge/nagiosplug/nagios-plugins-1.4.15.tar.gz
tar xzf nagios-plugins-1.4.15.tar.gz
cd nagios-plugins-1.4.15
export LDFLAGS=-ldl
./configure --with-nagios-user=nagios --with-nagios-group=nagios --enable-redhat-pthread-workaround
make
make install&lt;/pre&gt;
</pre>
<p>We will now install NRPE to enable monitoring of remote Linux servers.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;pre&gt;#download the latest NRPE from http://sourceforge.net/projects/nagios/files/nrpe-2.x/
#as nagios user
cd ~
wget http://sourceforge.net/projects/nagios/files/nrpe-2.x/nrpe-2.12/nrpe-2.12.tar.gz/download
tar xvfz nrpe-2.12.tar.gz
cd nrpe-2.1.2
./configure
make all
make install-plugin&lt;/pre&gt;
</pre>
<p>We will need to enable the check_bl plugin to check spam blacklists.  This isn’t included by the nagios-plugins, so we create the script manually.</p>
<pre class="brush: perl; title: ; notranslate">
&lt;pre&gt;touch /usr/local/nagios/libexec/check_bl
chmod 755 /usr/local/nagios/libexec/check_bl
vim /usr/local/nagios/libexec/check_bl

#!/usr/bin/perl -w
#
# check_bl plugin for nagios
# $Revision: 1.0 $
#
# Nagios plugin designed to warn you if you mail servers appear in one of the
# many anti-spam 'blacklists'
#
# By Sam Bashton, Bashton Ltd
# bashton.com/content/nagios-plugins
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

use strict;
use lib &quot;/usr/local/nagios/libexec/&quot;;
use utils qw($TIMEOUT %ERRORS &amp;amp;print_revision &amp;amp;support);
use Net::DNS;
use vars qw($PROGNAME);
my ($verbose,$host),;
my ($opt_V,$opt_h,$opt_B,$opt_H,$opt_c);
$opt_V = $opt_h = $opt_B = $opt_H = $opt_c = '';
my $state = 'UNKNOWN';
sub print_help();
sub print_usage();

$PROGNAME = &quot;check_bl&quot;;

$ENV{'BASH_ENV'}='';
$ENV{'ENV'}='';
$ENV{'PATH'}='';
$ENV{'LC_ALL'}='C';

use Getopt::Long;
Getopt::Long::Configure('bundling');
GetOptions(
  &quot;V&quot;   =&gt; $opt_V,   &quot;version&quot;       =&gt; $opt_V,
  &quot;h&quot;   =&gt; $opt_h,   &quot;help&quot;          =&gt; $opt_h,
  &quot;H=s&quot; =&gt; $opt_H,   &quot;hostname=s&quot;    =&gt; $opt_H,
  &quot;B=s&quot; =&gt; $opt_B,   &quot;blacklists=s&quot;  =&gt; $opt_B,
  &quot;c=s&quot; =&gt; $opt_c,   &quot;critical=s&quot;    =&gt; $opt_c
);

# -h means display verbose help screen
if ($opt_h) { print_help(); exit $ERRORS{'OK'}; }

# -V means display version number
if ($opt_V) {
  print_revision($PROGNAME,'$Revision: 1.0 $ ');
  exit $ERRORS{'OK'};
}

# First check the hostname is OK..
unless ($opt_H) { print_usage(); exit $ERRORS{'UNKNOWN'}; }

if (! utils::is_hostname($opt_H)){
  print &quot;$opt_H is not a valid host namen&quot;;
  print_usage();
  exit $ERRORS{&quot;UNKNOWN&quot;};
}else{
  if ($opt_H =~ /[a-zA-Z]/ )
  # If the host contains letters we assume it's a hostname, not an IP
  {
    $host = lookup($opt_H);
  }
  else { $host = $opt_H }
}

# $opt_c is a count of the blacklists a mail server is in,
# after which state will be CRITICAL rather than WARNING
# By default any listing is CRITICAL
my $critcount = 0;
if ($opt_c) { $critcount = $opt_c };

# $opt_B is a comma seperated list of blacklists
$opt_B = shift unless ($opt_B);
unless ($opt_B) { print_usage(); exit -1 }
my @bls = split(/,/, $opt_B);

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
  print (&quot;ERROR: No response from BL server (alarm)n&quot;);
  exit $ERRORS{&quot;UNKNOWN&quot;};
};
alarm($TIMEOUT);

my %listed; # Hash of blacklists we're listed in.
foreach(@bls)
{
  if (blcheck($host,$_)) { $listed{$_} = 1 }
}

if (scalar(keys(%listed)) == 0) { $state = 'OK' }
elsif (scalar(keys(%listed)) &lt; $critcount) { $state = 'WARNING' }
else { $state = 'CRITICAL' }

if (%listed)
{
  print &quot;Listed at&quot;;
  foreach (keys(%listed)) { print &quot; $_&quot; }
  print &quot;n&quot;;
}
else { print &quot;Not black-listedn&quot; }

exit $ERRORS{$state};

########  Subroutines ==========================

sub print_help() {
  print_revision($PROGNAME,'$Revision: 1.0 $ ');
  print &quot;n&quot;;
  support();
}

sub print_usage () {
  print &quot;Usage: n&quot;;
  print &quot; $PROGNAME -H host -B [blacklist1],[blacklist2] [-c critnum]n&quot;;
  print &quot; $PROGNAME [-h | --help]n&quot;;
  print &quot; $PROGNAME [-V | --version]n&quot;;
}

sub blcheck
{
  my ($ip, $bl) = @_;
  my $lookupip = $ip;
  $lookupip =~
  s/([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})/$4.$3.$2.$1.$bl/;
  if (lookup($lookupip)) { return 1 }
  else { return 0 }
}

sub lookup
{
  my $tolookup = shift;
  my $res = Net::DNS::Resolver-&gt;new;
  my $query = $res-&gt;search($tolookup);
  if ($query)
  {
    foreach my $rr ($query-&gt;answer)
    {
      next unless $rr-&gt;type eq &quot;A&quot;; # We're not interested in TXT records
      return $rr-&gt;address;
    }
  }
}&lt;/pre&gt;
</pre>
<p>It’s now time to enable Nagios on the monitoring server. We will execute the following command to verify that there are no errors, this might have to be done as root, I can’t remember.  Finally, as root, you will need to add Nagios to the automatic startup list and start it.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;pre&gt;#exit to root
exit
/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg
#if no errors, continue
chkconfig --add nagios
chkconfig nagios on
service nagios start&lt;/pre&gt;
</pre>
<p>Finally, to check that Nagios is working, login using http:///nagios using the username and password that you defined above with the htpasswd command.  The username is most likely nagiosadmin.</p>
<p><strong>I will now cover how to remotely monitor a remote machine</strong>.</p>
<p>Let’s first cover a Linux box.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;pre&gt;yum install xinetd
chkconfig xinetd on
service xinetd start

useradd -d /home/nagios nagios
passwd nagios
&lt;CHOOSE A PASSWORD&gt;
groupadd nagcmd
usermod -a -G nagcmd nagios&lt;/pre&gt;
&lt;pre&gt;cd ~nagios
#get the latest plugins from http://www.nagios.org/download/plugins/
wget http://prdownloads.sourceforge.net/sourceforge/nagiosplug/nagios-plugins-1.4.15.tar.gz
tar xzf nagios-plugins-1.4.15.tar.gz
cd nagios-plugins-1.4.15
export LDFLAGS=-ldl
./configure --with-nagios-user=nagios --with-nagios-group=nagios --enable-redhat-pthread-workaround
make
make install

cd ~
wget http://sourceforge.net/projects/nagios/files/nrpe-2.x/nrpe-2.12/nrpe-2.12.tar.gz/download
tar xvfz nrpe-2.12.tar.gz
cd nrpe-2.12
./configure
make all
make install-plugin
make install-daemon
make install-daemon-config
make install-xinetd&lt;/pre&gt;
&lt;pre&gt;chown -R nagios:nagcmd /usr/local/nagios&lt;/pre&gt;
</pre>
<p>We now need to modify some files to enable NRPE’s service.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;pre&gt;#Add to /etc/xinetd.d/nrpe:
only_from       = 127.0.0.1 98.142.216.195

#Add to /etc/services
nrpe 5666/tcp # NRPE

service xinetd restart

#finally test NRPE

netstat -at | grep nrpe
#you will see something like:
#       tcp 0      0 *:nrpe *:*                         LISTEN

#yet another test
/usr/local/nagios/libexec/check_nrpe -H localhost
#you should see:
#   NRPE v2.12&lt;/pre&gt;
</pre>
<p>Finally, we need to modify a file to enable the remote check_nrpe command from the Nagios monitoring server.  At this point, you will also want to unblock port 5656 in both directions on both the monitoring server and remote server so that NRPE can freely communicate.  In my case, my backup server ignores / allows all traffic from internal network servers, so this wasn’t an issue for me.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;pre&gt;cat /usr/local/nagios/etc/nrpe.cfg
#from my CPanel server, I only included the COMMAND DEFINITIONS section at the end of the file

command[check_smarta]=/usr/local/nagios/libexec/check_ide_smart -d /dev/sda
command[check_uptime]=/usr/local/nagios/libexec/check_uptime
command[check_total_procs]=/usr/local/nagios/libexec/check_procs -w 250 -c 300
command[check_swap]=/usr/local/nagios/libexec/check_swap -w 10% -c 5%
command[check_load]=/usr/local/nagios/libexec/check_load -w 25,20,15 -c 30,25,20
command[check_sda1]=/usr/local/nagios/libexec/check_disk -w 20% -c 10% -p /dev/sda1
command[check_mem]=/usr/local/nagios/libexec/check_mem -w .2 -c .1 -f
command[check_users]=/usr/local/nagios/libexec/check_users -w 5 -c 10&lt;/pre&gt;
</pre>
<p>Smart Status checking (a way to determine if a hard disk is going to die before it actually dies) in Nagios has some special permissions requirements.  Below is a list of commands you can execute to make the check_ide_smart script work correctly.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;pre&gt;chown root:root /usr/local/nagios/libexec/check_ide_smart
chmod u+s /usr/local/nagios/libexec/check_ide_smart
chmod o+x /usr/local/nagios/libexec/check_ide_smart
ls -l /usr/local/nagios/libexec/check_ide_smart
#should look like
#-rwsr-x--x 1 root root 18052 Jun 11 21:56 /usr/local/nagios/libexec/check_ide_smart&lt;/pre&gt;
</pre>
<p>To enable uptime monitoring, we need to make a script for this:</p>
<pre class="brush: bash; title: ; notranslate">
&lt;pre&gt;cat /usr/local/nagios/libexec/check_uptime

#!/bin/sh
echo &quot;OK `uptime`&quot;&lt;/pre&gt;
</pre>
<p>To enable memory checks, we have to make the check_mem executable in the libexec directory.</p>
<pre class="brush: perl; title: ; notranslate">
&lt;pre&gt;touch /usr/local/nagios/libexe/check_mem
chmod 755 /usr/local/nagios/libexe/check_mem
vim /usr/local/nagios/libexe/check_mem

#!/usr/bin/perl -w
# $Id: check_mem.pl 2 2002-02-28 06:42:51Z egalstad $
# Original script stolen from:
# check_mem.pl Copyright (C) 2000 Dan Larsson &lt;dl@tyfon.net&gt;
# hacked by
# Justin Ellison &lt;justin@techadvise.com&gt;
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# you should have received a copy of the GNU General Public License
# along with this program (or with Nagios);  if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA

# Tell Perl what we need to use
use strict;
use Getopt::Std;

#TODO - Convert to Nagios::Plugin
#TODO - Use an alarm

# Predefined exit codes for Nagios
use vars qw($opt_c $opt_f $opt_u $opt_w $opt_C $opt_v %exit_codes);
%exit_codes   = ('UNKNOWN' ,-1,
                         'OK'      , 0,
                 'WARNING' , 1,
                 'CRITICAL', 2,
                 );

# Get our variables, do our checking:
init();

# Get the numbers:
my ($free_memory_kb,$used_memory_kb,$caches_kb) = get_memory_info();
print &quot;$free_memory_kb Freen$used_memory_kb Usedn$caches_kb Cachen&quot; if ($opt_v);

if ($opt_C) { #Do we count caches as free?
    $used_memory_kb -= $caches_kb;
    $free_memory_kb += $caches_kb;
}

# Round to the nearest KB
$free_memory_kb = sprintf('%d',$free_memory_kb);
$used_memory_kb = sprintf('%d',$used_memory_kb);
$caches_kb = sprintf('%d',$caches_kb);

# Tell Nagios what we came up with
tell_nagios($used_memory_kb,$free_memory_kb,$caches_kb);

sub tell_nagios {
    my ($used,$free,$caches) = @_;

    # Calculate Total Memory
    my $total = $free + $used;
    print &quot;$total Totaln&quot; if ($opt_v);

    my $perfdata = &quot;|TOTAL=${total}KB;;;; USED=${used}KB;;;; FREE=${free}KB;;;; CACHES=${caches}KB;;;;&quot;;

    if ($opt_f) {
      my $percent    = sprintf &quot;%.1f&quot;, ($free / $total * 100);
      if ($percent &lt;= $opt_c) {
          finish(&quot;CRITICAL - $percent% ($free kB) free!$perfdata&quot;,$exit_codes{'CRITICAL'});
      }
      elsif ($percent &lt;= $opt_w) {
          finish(&quot;WARNING - $percent% ($free kB) free!$perfdata&quot;,$exit_codes{'WARNING'});
      }
      else {
          finish(&quot;OK - $percent% ($free kB) free.$perfdata&quot;,$exit_codes{'OK'});
      }
    }
    elsif ($opt_u) {
      my $percent    = sprintf &quot;%.1f&quot;, ($used / $total * 100);
      if ($percent &gt;= $opt_c) {
          finish(&quot;CRITICAL - $percent% ($used kB) used!|$perfdata&quot;,$exit_codes{'CRITICAL'});
      }
      elsif ($percent &gt;= $opt_w) {
          finish(&quot;WARNING - $percent% ($used kB) used!|$perfdata&quot;,$exit_codes{'WARNING'});
      }
      else {
          finish(&quot;OK - $percent% ($used kB) used.|$perfdata&quot;,$exit_codes{'OK'});
      }
    }
}

# Show usage
sub usage() {
  print &quot;ncheck_mem.pl v1.0 - Nagios Pluginnn&quot;;
  print &quot;usage:n&quot;;
  print &quot; check_mem.pl -&lt;f|u&gt; -w &lt;warnlevel&gt; -c &lt;critlevel&gt;nn&quot;;
  print &quot;options:n&quot;;
  print &quot; -f           Check FREE memoryn&quot;;
  print &quot; -u           Check USED memoryn&quot;;
  print &quot; -C           Count OS caches as FREE memoryn&quot;;
  print &quot; -w PERCENT   Percent free/used when to warnn&quot;;
  print &quot; -c PERCENT   Percent free/used when criticaln&quot;;
  print &quot;nCopyright (C) 2000 Dan Larsson &lt;dl@tyfon.net&gt;n&quot;;
  print &quot;check_mem.pl comes with absolutely NO WARRANTY either implied or explicitn&quot;;
  print &quot;This program is licensed under the terms of then&quot;;
  print &quot;GNU General Public License (check source code for details)n&quot;;
  exit $exit_codes{'UNKNOWN'};
}

sub get_memory_info {
    my $used_memory_kb  = 0;
    my $free_memory_kb  = 0;
    my $total_memory_kb = 0;
    my $caches_kb       = 0;

    my $uname;
    if ( -e '/usr/bin/uname') {
        $uname = `/usr/bin/uname -a`;
    }
    elsif ( -e '/bin/uname') {
        $uname = `/bin/uname -a`;
    }
    else {
        die &quot;Unable to find uname in /usr/bin or /bin!n&quot;;
    }
    print &quot;uname returns $uname&quot; if ($opt_v);
    if ( $uname =~ /Linux/ ) {
        my @meminfo = `/bin/cat /proc/meminfo`;
        foreach (@meminfo) {
            chomp;
            if (/^Mem(Total|Free):s+(d+) kB/) {
                my $counter_name = $1;
                if ($counter_name eq 'Free') {
                    $free_memory_kb = $2;
                }
                elsif ($counter_name eq 'Total') {
                    $total_memory_kb = $2;
                }
            }
            elsif (/^(Buffers|Cached):s+(d+) kB/) {
                $caches_kb += $2;
            }
        }
        $used_memory_kb = $total_memory_kb - $free_memory_kb;
    }
    elsif ( $uname =~ /SunOS/ ) {
        eval &quot;use Sun::Solaris::Kstat&quot;;
        if ($@) { #Kstat not available
            if ($opt_C) {
                print &quot;You can't report on Solaris caches without Sun::Solaris::Kstat available!n&quot;;
                exit $exit_codes{UNKNOWN};
            }
            my @vmstat = `/usr/bin/vmstat 1 2`;
            my $line;
            foreach (@vmstat) {
              chomp;
              $line = $_;
            }
            $free_memory_kb = (split(/ /,$line))[5] / 1024;
            my @prtconf = `/usr/sbin/prtconf`;
            foreach (@prtconf) {
                if (/^Memory size: (d+) Megabytes/) {
                    $total_memory_kb = $1 * 1024;
                }
            }
            $used_memory_kb = $total_memory_kb - $free_memory_kb;

        }
        else { # We have kstat
            my $kstat = Sun::Solaris::Kstat-&gt;new();
            my $phys_pages = ${kstat}-&gt;{unix}-&gt;{0}-&gt;{system_pages}-&gt;{physmem};
            my $free_pages = ${kstat}-&gt;{unix}-&gt;{0}-&gt;{system_pages}-&gt;{freemem};
            # We probably should account for UFS caching here, but it's unclear
            # to me how to determine UFS's cache size.  There's inode_cache,
            # and maybe the physmem variable in the system_pages module??
            # In the real world, it looks to be so small as not to really matter,
            # so we don't grab it.  If someone can give me code that does this,
            # I'd be glad to put it in.
            my $arc_size = (exists ${kstat}-&gt;{zfs} &amp;amp;&amp;amp; ${kstat}-&gt;{zfs}-&gt;{0}-&gt;{arcstats}-&gt;{size}) ?
                 ${kstat}-&gt;{zfs}-&gt;{0}-&gt;{arcstats}-&gt;{size} / 1024
                 : 0;
            $caches_kb += $arc_size;
            my $pagesize = `pagesize`;

            $total_memory_kb = $phys_pages * $pagesize / 1024;
            $free_memory_kb = $free_pages * $pagesize / 1024;
            $used_memory_kb = $total_memory_kb - $free_memory_kb;
        }
    }
    else {
        if ($opt_C) {
            print &quot;You can't report on $uname caches!n&quot;;
            exit $exit_codes{UNKNOWN};
        }
        my $command_line = `vmstat | tail -1 | awk '{print $4,$5}'`;
        chomp $command_line;
        my @memlist      = split(/ /, $command_line);

        # Define the calculating scalars
        $used_memory_kb  = $memlist[0]/1024;
        $free_memory_kb = $memlist[1]/1024;
        $total_memory_kb = $used_memory_kb + $free_memory_kb;
    }
    return ($free_memory_kb,$used_memory_kb,$caches_kb);
}

sub init {
    # Get the options
    if ($#ARGV le 0) {
      &amp;amp;usage;
    }
    else {
      getopts('c:fuCvw:');
    }

    # Shortcircuit the switches
    if (!$opt_w or $opt_w == 0 or !$opt_c or $opt_c == 0) {
      print &quot;*** You must define WARN and CRITICAL levels!n&quot;;
      &amp;amp;usage;
    }
    elsif (!$opt_f and !$opt_u) {
      print &quot;*** You must select to monitor either USED or FREE memory!n&quot;;
      &amp;amp;usage;
    }

    # Check if levels are sane
    if ($opt_w &lt;= $opt_c and $opt_f) {
      print &quot;*** WARN level must not be less than CRITICAL when checking FREE memory!n&quot;;
      &amp;amp;usage;
    }
    elsif ($opt_w &gt;= $opt_c and $opt_u) {
      print &quot;*** WARN level must not be greater than CRITICAL when checking USED memory!n&quot;;
      &amp;amp;usage;
    }
}

sub finish {
    my ($msg,$state) = @_;
    print &quot;$msgn&quot;;
    exit $state;
}&lt;/pre&gt;
</pre>
<p>Finally modify permissions of these scripts.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;pre&gt;chown -R nagios:nagcmd /usr/local/nagios/libexec/check_mem
chown -R nagios:nagcmd /usr/local/nagios/libexec/check_uptime
chmod 755 /usr/local/nagios/libexec/check_uptime
chmod 755 /usr/local/nagios/libexec/check_mem&lt;/pre&gt;
</pre>
<p>On <strong>Windows</strong>, we will use nsclient++.  At the time of this writing, the latest stable version is 0.3.8 and we want the msi installer file for it (either 32 bit or 64 bit).  Once its downloaded, install the msi with all the default options.</p>
<p>Then modify the file at C:Program FilesNSClient++NSC.ini.  Here is what I did:</p>
<ul>
<li>Uncomment all the modules listed in the [modules] section, except for CheckWMI.dll and RemoteConfiguration.dll</li>
<li>Optionally require a password for clients by changing the &#8216;password&#8217; option in the [Settings] section.</li>
<li>Uncomment the &#8216;allowed_hosts&#8217; option in the [Settings] section. Add the IP address of the Nagios server to this line, or leave it blank to allow all hosts to connect.</li>
<li>Make sure the &#8216;port&#8217; option in the [NSClient] section is uncommented and set to &#8217;12489&#8242; (the default port).</li>
</ul>
<p>Then open up an elevated command prompt (right click on command prompt and run as administrator).</p>
<p>&lt;pre&gt;cd c:program filesnsclient++<br />
nsclient++ /install&lt;/pre&gt;</p>
<p>Finally, reboot the system (or start the service from the services control panel) and Nagios should be able to monitor your Windows server!</p>
<p><strong>My final bit is on how to upgrade Nagios in the future. </strong>To upgrade Nagios, you will want to download the latest archives of nagios-core, nagios-plugins, and nrpe/nsclient++.  You will install all of them as above, except for, once you’re done with the make install step, you are finished with the upgrade.  Nagios doesn’t touch the existing configuration files, so it’s very easy to upgrade.</p>
<p>&nbsp;</p>
<p>With all of the above said, Nagios is actually very easy to configure and install once you understand it.  I’m hopeful that this blog will help you understand Nagios better and have more confidence in deploying it on your systems!  As always, thanks for reading!</p>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/06/installing-nagios-to-centos-5/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Making a skin for the Subtext Blog</title>
		<link>http://famousphil.com/blog/2011/06/subtext-skin-on-your-website/</link>
		<comments>http://famousphil.com/blog/2011/06/subtext-skin-on-your-website/#comments</comments>
		<pubDate>Mon, 13 Jun 2011 12:01:29 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Student Life]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[asp]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[engine]]></category>
		<category><![CDATA[skin]]></category>
		<category><![CDATA[subtext]]></category>
		<category><![CDATA[theme]]></category>
		<category><![CDATA[wordpress alternative]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=824</guid>
		<description><![CDATA[Jason from the subtext project wrote a great article about the subtext blog engine!  You can visit their site at http://www.subtextproject.com]]></description>
			<content:encoded><![CDATA[<p>I bring you a guest post from Jason who is associated with the subtext project which is a blog written in ASP.net!  Disclaimer&#8230; I do not guarantee (or verify) the accuracy of guest posts.</p>
<p>A webmaster has many things to think about from choosing the right <a href="http://www.webhostingsearch.com/">host</a> to making sure everything is running smoothly on the backend servers. Fortunately, different tools, applications and developments exist that can help us simplify the process of running a website. Subtext skins can help designers more effectively and efficiently create the styles used for personal blogs on their website.</p>
<p>While you can always decrease your workload by choosing options like <a href="http://www.webhostingsearch.com/managed-web-hosting.php">managed hosting</a>, if you are responsible for web design then you should look into the many advantages of Subtext skins for blogging.</p>
<p><strong>What is a Subtext skin?</strong><br />
Subtext is a blogging platform offered as open source software under the BSD license. The whole concept behind Subtext was to create a very simplified blogging engine that allows bloggers to concentrate on creating actual blog content rather than trying to figure out how to use the blogging software.</p>
<p>Almost all websites these days have their own blogs. In addition, many sites offer blogging as a service to their users who can sign up to create their own personal blogs. You can use Subtext both for the site&#8217;s own blog and to offer blogs to site members.</p>
<p>A Subtext skin refers to the styling and layout of the blog page. Skins are versatile as they allow you to create page formats and designs without coding from scratch. A Subtext skin is actually made up of five separate style sheets that can be used to format different elements on the page like divs, spans, boxes, headers, footers, sidebars and forms.<br />
<strong></strong></p>
<p><strong>The five style sheets used for each Subtext skin are:</strong></p>
<p>• style.css – the default style sheet that determines the basic underlying skin layout.<br />
• secondary style sheet – this file handles the specific Stylesheet attribute of the skin. The secondary style sheet is generally used to create styling contrasts over the style.css file. For example, the web designer may choose to give the header a different border than the sidebars where in the style.css file they use the same border.<br />
• custom.css – this style sheet is used for custom design features set by the blog author. Primarily used to set styles and layout for personal badges or for the actual post content.<br />
• non-attribute css files – generally used for CSS frameworks or for system styles.<br />
• css files with limited attributes – these stylesheets have a title and media attribute, and cannot be merged with other css files. The attributes specify IE version compatibility and that they are applicable only in screen mode or in printing mode.</p>
<p><strong>Packaged and custom Subtext skins</strong><br />
Web designers can choose from a large library of pre-designed skins or they can create their own custom skins. Creating a custom Subtext skin requires some basic knowledge of CSS scripting and also learning the basic Subtext parsing rules.</p>
<p>Fortunately, Subtext is highly simplified to allow users to quickly master the underlying script.</p>
<p>Skin templates are folders that can be used to render different Subtext skins. Each folder actually contains a number of skins that are related in certain attributes and themes. The folders or templates have their own series of controls that are used to render a skin in that template along with associated style sheets.</p>
<p>Once you have a library of packaged and/or custom skins, you will be able to style blogs quickly after learning how to tweak the skins and templates.</p>
<p>Instead of racking your brain each time you need to come up with a new design, you can simply browse through your selection of Subtext skins. Each skin can be modified according to the primary and secondary CSS files associated with the skin. You can easily find the types of skins you are looking for because they will be arranged in skin templates or families according to related attributes. For example, you can have a Rainbow template. a Geometric template and an Origami template – each having multiple skins that express the same theme. The number of templates is only limited by your imagination and willingness to create custom skins.</p>
<p>When using the Subtext blogging software, the skin templates are arranged in folders in an easy to manage directory system. The setup makes it simple to find the skin you are looking for and simply click on the selection to implement it on the Subtext blog.</p>
<p>By using Subtext skins, you can save time and energy creating page designs and layouts for multiple blogs. No need to code style sheets from scratch when you can access an easy-to-use Subtext skin library and quickly find what you need.</p>
<p>Each skin will handle the styling and layout of all page elements including headers, footers, sidebars, text format, boxes and forms.</p>
<p>You can find out more about Subtext and skins at the Subtext Project Site: <a href="http://www.subtextproject.com/">http://www.subtextproject.com/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/06/subtext-skin-on-your-website/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Pdflib installation on CPanel</title>
		<link>http://famousphil.com/blog/2011/06/pdflib-installation-on-cpanel/</link>
		<comments>http://famousphil.com/blog/2011/06/pdflib-installation-on-cpanel/#comments</comments>
		<pubDate>Sun, 12 Jun 2011 02:40:20 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[CPanel]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[pdflib]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=820</guid>
		<description><![CDATA[Guide to installing Pdflib PECL extension to CPanel (and non-cpanel) servers.]]></description>
			<content:encoded><![CDATA[<p>Here is a relatively short blog for a change!  A client came to me today to have PDFLib installed onto the Matthouse CPanel server.  PDFLib allows you to create PDF files programatically (in this case, PHP), so I can see a lot of uses for this extension.  As expected, CPanel wasn&#8217;t able to install this extension through PECL without a little help, so below is the procedure that I used.</p>
<pre class="brush: bash; title: ; notranslate">
#get latest pdflib lite 7 from http://www.pdflib.com/download/
#http://www.pdflib.com/download/pdflib-family/pdflib-lite-7/

cd ~
wget http://www.pdflib.com/binaries/PDFlib/705/PDFlib-Lite-7.0.5.tar.gz
tar xzf PDFlib-Lite-7.0.5.tar.gz
cd PDFlib-Lite-7.0.5
#java isn't installed on the server, compile without java
./configure --prefix=/usr/local/pdflib --without-java
make
make install
pecl install pdflib 
#when asked for a path, enter &quot;/usr/local/pdflib&quot; then hit &lt;enter&gt;
</pre>
<p>I opted to install the lite version of PDFLib since its free and my client didn&#8217;t need all of the features that the program includes.  I installed pdflib to its own directory that isn&#8217;t included in path since I don&#8217;t anticipate anyone actually using this via other languages on the server (besides PHP).  Once PDFLib is installed, we will need to use the command line (as root) to install the pecl extension and tell it where to find the compiled version of pdflib.  Note that CPanel&#8217;s PECL installer will not be able to install this extension since there is no way to enter the path (and I&#8217;d prefer to not add this to the global PATH variable on my server).  The extension is now installed, in order to test the extension, make a PHP file for the below code and execute it in a web browser, you should see &#8220;Hello World&#8221; as a PDF document.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

try {
$p = new PDFlib();

/*  open new PDF file; insert a file name to create the PDF on disk */
if ($p-&gt;begin_document(&quot;&quot;, &quot;&quot;) == 0) {
die(&quot;Error: &quot; . $p-&gt;get_errmsg());
}

$p-&gt;set_info(&quot;Creator&quot;, &quot;hello.php&quot;);
$p-&gt;set_info(&quot;Author&quot;, &quot;AUTHOR&quot;);
$p-&gt;set_info(&quot;Title&quot;, &quot;Hello world (PHP)!&quot;);

$p-&gt;begin_page_ext(595, 842, &quot;&quot;);

$font = $p-&gt;load_font(&quot;Helvetica-Bold&quot;, &quot;winansi&quot;, &quot;&quot;);

$p-&gt;setfont($font, 24.0);
$p-&gt;set_text_pos(50, 700);
$p-&gt;show(&quot;Hello world!&quot;);
//$p-&gt;continue_text(&quot;continue text&quot;);
$p-&gt;end_page_ext(&quot;&quot;);

$p-&gt;end_document(&quot;&quot;);

$buf = $p-&gt;get_buffer();
$len = strlen($buf);

header(&quot;Content-type: application/pdf&quot;);
header(&quot;Content-Length: $len&quot;);
header(&quot;Content-Disposition: inline; filename=hello.pdf&quot;);
print $buf;
}
catch (PDFlibException $e) {
die(&quot;PDFlib exception occurred in hello sample:n&quot;. $e-&gt;get_errnum() .&quot; &quot; . $e-&gt;get_apiname() . &quot; : &quot; .$e-&gt;get_errmsg() . &quot;nn&quot;);
}
catch (Exception $e) {
die($e);
}
$p = 0;
?&gt;
</pre>
<p>Source: I used the guide at <a href="http://www.supportfacility.com/blog/cpanel/install-pdflib-php-on-cpanel-dedicated-server/">http://www.supportfacility.com/blog/cpanel/install-pdflib-php-on-cpanel-dedicated-server/</a> to write an updated version for my blog.  I&#8217;d like to thank them for blogging about this topic!</p>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/06/pdflib-installation-on-cpanel/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Installing Gitorious on CentOS 5.6 x64</title>
		<link>http://famousphil.com/blog/2011/06/installing-gitorious-on-centos-5-6-x64/</link>
		<comments>http://famousphil.com/blog/2011/06/installing-gitorious-on-centos-5-6-x64/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 22:07:53 +0000</pubDate>
		<dc:creator>Famous Phil</dc:creator>
				<category><![CDATA[Hosting / Server Administration]]></category>
		<category><![CDATA[My Site]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[gitorious]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[openvz]]></category>
		<category><![CDATA[vps]]></category>
		<category><![CDATA[Xen]]></category>

		<guid isPermaLink="false">http://famousphil.com/?p=801</guid>
		<description><![CDATA[Phil provides a tutorial for installing Gitorious on CentOS 5.6 X64 (under OpenVZ).  He explains the difficulty of installing and maintaining this software.]]></description>
			<content:encoded><![CDATA[<p>There are many reasons why you might be reading this post, but likely, you’re trying to figure out how to install this complex heap of code (that has its root node removed, no doubt, ha ha).  If you didn’t get my last joke, I feel sorry for you, but the show must go on.</p>
<p>Gitorious is an open source repository management system similar to Trac on SVN.  The software looks really nice (gitorious.org), and it has a lot of built in features for managing git repositories.  For those of you who are not familiar with coding, code repositories are often set up to enable many coders to work on the same project simultaneously (different portions of course).  Repositories also enable versioning so that you can easily revert to an older copy of your code base if something breaks along the way.  Repositories are often centralized so that only a single location has to be backed up, in this case Gitorious centralizes git repositories.</p>
<p>Truthfully, there are three memorable software programs that have been notoriously difficult to install and configure in my experience, these are as follows:</p>
<ul>
<li>Shibboleth- I never did successfully install this myself, this was because I was asked to help a friend install it over the phone.  I don’t work well when I can’t see the problem and play with stuff, I test hunches, and doing it with this method would have taken way too long.  From what I’ve seen of Shibboleth, I would rate this as worst of the worst programs to install.</li>
<li>Gitorious – This is probably the second worst application I’ve ever installed.  It required a lot of research and resources since it is poorly documented and requires a lot of Ruby Gems to operate successfully.  Of course, I will hopefully document it a little more today!</li>
<li>Exchange – I wish I would have documented the install of my Exchange server internally so I could have shared it here.  Exchange isn’t awful to install, but the configuration of Exchange is very tricky and there are many gotchas.  This is why I place it as the best of the worst software programs to install.</li>
</ul>
<p>With all of the above said, the installation process of gitorious isn’t for the leisure system administrator to install.  This took me approximately 3 days of research to successfully install and understand.  I installed it on a separate system only because I didn’t want it hurting any of my existing production systems.  In the end, I’m glad I did this because I learned that Ruby isn’t very memory efficient and this application easily eats up most of the 1GB of ram allocated to it in a VPS (Virtual Private Server).  And with this said, I invite you to continue reading if you really want to know how to install this software.</p>
<p>Update 6/14: After a few requests, I&#8217;ve decided that I will provide a Gitorious installation service on your CentOS server.  I will be happy to install Gitorious and make it work (as described below) for a one time paypal payment of $100.  For details, contact me directly (see my contact page).</p>
<p><strong>LAST UPDATE: 6/8/2011 &#8211; Suggestions from<a href="http://groups.google.com/group/gitorious/browse_thread/thread/5bb8b2a6f0a2d645"> Gitorious Discussion Group</a></strong></p>
<p><span id="more-801"></span></p>
<p>Before I begin, I’d like to note that although I used OpenVZ for my deployment of Gitorious, it should work on Xen and other platforms  (even dedicated servers).  I say should because I originally deployed this on Amazon Web Services, and the installation process had a few changes here and there (due to errors with package dependencies, etc) when I finally moved it over to OpenVZ.  The procedure below was used for an OpenVZ machine as detailed below.  Finally, my last note is that you can expect this installation process to take roughly an hour or two to complete as a lower bound (provided everything goes well).</p>
<p>I decided to use a VPS from <a href="http://chicagovps.net/">chicagovps</a> to host this software program because of a good past experience with them.  Although<strong> </strong>I normally bash OpenVZ virtualization (with really good reasons because Xen is better), I chose to use OpenVZ since it is typically faster and I wanted performance.  OpenVZ doesn’t have swap space, and its memory management isn’t that great, so in the end, applications can use almost 3x the amount of memory on OpenVZ VPS containers compared to running on equivalent Xen containers.  I can easily see Xen requiring less than 384MB of dedicated Ram for Gitorious.  On OpenVZ, I strongly suggest not getting less than 1GB of dedicated memory.  With ChicagoVPS, I got the professional package, and my memory usage hovers around 800MB for this install.  For the Operating System, I chose the CentOS 5.5 x64 template and using yum update, the operating system became CentOS 5.6.  Everything below is performed as root unless otherwise noted.</p>
<p>The first thing that I did was set my DNS to have 2 A-records pointing to the hostname of my server (string.matthouse.us), and another that points to the future Gitorious website URL (git.matthouse.us).  After that was done, I logged into the VPS and set up public keys for the root account to make logging into the machine easier in the future.  I’ve written two blogs about public key authentication, so I won’t detail this portion of the process (that’s optional anyways).  I’d also recommend setting up a secure root password (also mentioned sometime in the past).</p>
<p>Next, I’d recommend disabling SELinux if it is enabled, thankfully, on VPS nodes, its typically disabled out of the box.  If you’re on Xen, you might want to make and enable a swap file (which I detailed on my AWS install of Tomcat blog).  The next step is to execute the following commands, which remove common packages that you won’t need and turn off common services which you won’t use.  In this stack of commands, you will also need to edit the SSH configuration to disable DNS lookups, which in my experience speeds up the login process to SSH by a lot!</p>
<pre class="brush: bash; title: ; notranslate">
yum remove -y samba-common bind-libs dnsmasq portmap postgresql-libs nscd
service atd stop
chkconfig atd off
service nfslock stop
chkconfig nfslock off
service rpcidmapd stop
chkconfig rpcidmapd off
service bluetooth stop
chkconfig bluetooth off
service anacron stop
chkconfig anacron off
service gpm stop
chkconfig gpm off
service hidd stop
chkconfig hidd off
service pcscd stop
chkconfig pcscd off
service portmap stop
chkconfig portmap off
service avahi-daemon stop
chkconfig avahi-daemon off
service pcscd stop
chkconfig pcscd off
service sendmail start
chkconfig sendmail on
vim /etc/ssh/sshd_config
#uncomment UseDNS and change to no
UseDNS no

service sshd restart
</pre>
<p>Next, we need to enable the RPMForge repository.  I enable the EPEL and REMI repositories later on, but at this point, if those are enabled, you will hit a certain known bug with MySQL that has yet to be fixed by CentOS.</p>
<pre class="brush: bash; title: ; notranslate">

http://rpmrepo.org/RPMforge/Using

wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm
rpm -ivh rpmforge-release-0.5.2-2.el5.rf.i386.rpm
</pre>
<p>Now lets update the system and install some required packages.  This should take roughly 10 or 15 minutes.</p>
<pre class="brush: bash; title: ; notranslate">
yum update -y
yum groupinstall -y &quot;Development tools&quot; &quot;Development Libraries&quot;
yum install -y git-core git-svn java-1.6.0-openjdk vim-* apg pcre pcre-devel zlib zlib-devel libyaml-devel GeoIP-devel sphinx mysql-devel mysql-server mysql
</pre>
<p>&nbsp;</p>
<p>At this point, I configure MySQL before adding other software that triggers bugs with its initial setup phase.</p>
<pre class="brush: bash; title: ; notranslate">
service mysqld start
/usr/bin/mysql_secure_installation
</pre>
<p>&nbsp;</p>
<p>In the secure installation, I set the root password of MySQL to something tricky and I answer yes to all of the prompts.</p>
<p>The next step is to add some configuration to the my.cnf file to minimize the footprint of MySQL (which will still use a lot of memory on OpenVZ).</p>
<pre class="brush: bash; title: ; notranslate">
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
old_passwords=1
max_connections = 5
key_buffer = 1K
read_buffer_size = 1K
max_allowed_packet = 512K
thread_stack = 16K
table_cache = 32
sort_buffer = 16K
net_buffer_length = 1K
thread_stack = 4K
query_cache_type = 1
query_cache_limit = 1K
query_cache_size = 1K
innodb_buffer_pool_size = 1K
innodb_additional_mem_pool = 1K
# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
# symbolic-links=0
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
</pre>
<p>&nbsp;</p>
<p>At this point, lets restart mysql.</p>
<pre class="brush: bash; title: ; notranslate">
service mysqld restart
</pre>
<p>&nbsp;</p>
<p>Now let’s install Ruby Enterprise Edition.  The enterprise version of Ruby is still free, but it uses older, more stable components of Ruby, it’s also focused towards memory conservation (although it still compares to Java’s memory appetite).  I would strongly recommend not using any other version/distribution of Ruby since I found many compatibility errors that caused me to have to start all over again many times!  Remember that # is a comment and the command line will NOT process the command.</p>
<pre class="brush: bash; title: ; notranslate">
#- get latest stable ruby enterprise (the rubylang 1.9 branch will not work properly)
#-http://www.rubyenterpriseedition.com/download.html
wget http://rubyenterpriseedition.googlecode.com/files/ruby-enterprise-1.8.7-2011.03.tar.gz
tar xzf ruby-enterprise-1.8.7-2011.03.tar.gz
cd ruby-enterprise-1.8.7-2011.03
./installer
#(accept the defaults, 2 prompts will come up)
</pre>
<p>&nbsp;</p>
<p>Next, we need to configure ruby and path variables.  Follow the comments in my notes.</p>
<pre class="brush: bash; title: ; notranslate">
cd /opt
ln -s ruby-enterprise-1.8.7-2011.03 ruby
vim /etc/profile

#add the following to /etc/profile [ &quot;$EUID&quot; = &quot;0&quot; ]
pathmunge /opt/ruby/bin
export RAILS_ENV=production
export PATH=/usr/local/sphinx/bin:/usr/local/bin:$PATH
export _JAVA_OPTIONS=-Xmx64m
export MAGICK_HOME=/usr/local
export DYLD_LIBRARY_PATH=/usr/local/lib
</pre>
<p>&nbsp;</p>
<p>Strange enough, later on, another bug will surface where the profile isn’t read to setup these paths and options.  Therefore, I also added the following to my internal documentation install script.</p>
<pre class="brush: bash; title: ; notranslate">
vim /etc/bashrc
#add to the very bottom

pathmungea () {
                if ! echo $PATH | /bin/egrep -q &quot;(^|:)$1($|:)&quot; ; then
                        if [ &quot;$2&quot; = &quot;after&quot; ] ; then
                                PATH=$PATH:$1
                        else
                                PATH=$1:$PATH
                        fi
                fi
        }
pathmungea /opt/ruby/bin
export RAILS_ENV=production
export PATH=/usr/local/sphinx/bin:/usr/local/bin:$PATH
export _JAVA_OPTIONS=-Xmx64m
export MAGICK_HOME=/usr/local
export DYLD_LIBRARY_PATH=/usr/local/lib
unset pathmungea
</pre>
<p>&nbsp;</p>
<p>At this point, restart the shell that you’re in to pick up the new path information.  You might want to reboot, but that isn’t necessary at this point.  After the restart, we need to install ImageMagick.</p>
<pre class="brush: bash; title: ; notranslate">
#Imagemagick on yum is outdated, so a bug will show up if we don’t do this for now.
cd ~
yum install -y tcl-devel libpng-devel libjpeg-devel ghostscript-devel bzip2-devel freetype-devel libtiff-devel
#wget url to ImageMagick download
wget ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick-6.7.0-2.tar.gz
tar xzf ImageMagick-6.7.0-2.tar.gz
cd ImageMagick-6.7.0-2
./configure --prefix=/usr/local --with-bzlib=yes --with-fontconfig=yes --with-freetype=yes --with-gslib=yes --with-gvc=yes --with-jpeg=yes --with-jp2=yes --with-png=yes --with-tiff=yes
make
make install
</pre>
<p>&nbsp;</p>
<p>Up next, we need to install some ruby gems.  This list isn’t comprehensive (there will be more to come later), but it will get us started.  I omitted mongrel as a webserver (which would come at this step according to other guides) because I intend on using Apache.  I also know that echoe, textpow, and oniguruma are either included or incompatible with this version of Ruby, so they were omitted.  I didn’t find any problems at the end without them, so I’m assuming they were extras.</p>
<p><strong>UPDATE 6/8: You probably don&#8217;t need to do this since bundle exec (below) will cover this for you.  You will need to run &#8220;gem install bundle&#8221; instead at this step.</strong></p>
<pre class="brush: bash; title: ; notranslate">
gem install sphinx rmagick ultrasphinx mime-types chronic ruby-hmac daemons mime-types BlueCloth ruby-yadis ruby-openid rspec rspec-rails RedCloth stompserver --no-ri --no-rdoc
</pre>
<p>&nbsp;</p>
<p>Now let’s add the extra repositories and fix some centos bugs.  Don’t worry if the packages aren’t found.</p>
<pre class="brush: bash; title: ; notranslate">
#fix some centos bugs:
yum remove perl-Net-SSLeay perl-IO-Socket-SSL

#install some repositories
wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
wget http://rpms.famillecollet.com/enterprise/remi-release-5.rpm
rpm -Uvh remi-release-5*.rpm epel-release-5*.rpm
</pre>
<p>&nbsp;</p>
<p>Finally, its time to move onto the installation of gitorious.  The su command will drop you into a shell owned by git (cool huh?).</p>
<pre class="brush: bash; title: ; notranslate">
useradd -d /home/git git

su git
cd ~
mkdir log
mkdir conf
git clone git://gitorious.org/gitorious/mainline.git gitorious
cd gitorious/
mkdir -p tmp/pids
exit
#(exit here will return to root)

ln -s /home/git/gitorious/script/gitorious /usr/local/bin/gitorious
cd /home/git/gitorious/
chmod ug+x script/*
chmod -R g+w config/ log/ public/ tmp/
</pre>
<p>&nbsp;</p>
<p>Next, we need to modify several files and begin preparing Gitorious to run.</p>
<p><strong>Update 6/8/11: When getting to the gem install portions, you probably only need to run the bundle commands, skipping the gem commands all together.</strong></p>
<pre class="brush: bash; title: ; notranslate">
su git

#modify each vim'd file appropriately

vim /home/git/gitorious/doc/templates/centos/git-daemon
RUBY_HOME=&quot;/opt/ruby&quot;
GITORIOUS_HOME=&quot;/home/git/gitorious&quot;

vim /home/git/gitorious/doc/templates/centos/git-ultrasphinx
GITORIOUS_HOME=&quot;/home/git/gitorious&quot;

vim /home/git/gitorious/doc/templates/centos/git-poller
RUBY_HOME=&quot;/opt/ruby&quot;
GITORIOUS_HOME=&quot;/home/git/gitorious&quot;
export _JAVA_OPTIONS=-Xmx64m

vim /home/git/gitorious/doc/templates/centos/stomp
RUBY_HOME=&quot;/opt/ruby&quot;
GEMS_HOME=&quot;/opt/ruby&quot;
GITORIOUS_HOME=&quot;/home/git/gitorious&quot;

exit  #return to root

#next as root:

gem install --no-ri --no-rdoc -v 1.5.0 json
gem install --no-ri --no-rdoc -v 1.3.1.1 rdiscount

cd /home/git/gitorious
bundle install
bundle exec rake gems:install

gem install --no-ri --no-rdoc -v 0.8.7 rake
gem install --no-ri --no-rdoc -v 1.1.0 daemons

gem uninstall rake -v 0.9.1
gem uninstall daemons -v 1.1.3

gem uninstall geoip
#select all

gem install --no-ri --no-rdoc -v 0.8.9 geoip
gem install --no-ri --no-rdoc -v 1.0 raspell

cp config/database.sample.yml config/database.yml
cp config/gitorious.sample.yml config/gitorious.yml
cp config/broker.yml.example config/broker.yml

su git
mkdir /home/git/data
mkdir /home/git/data/repositories
mkdir /home/git/data/tarballs
mkdir /home/git/data/tarball-work
chown -R git:git /home/git/data
#enable key management
mkdir /home/git/.ssh
chmod -R 700 /home/git/.ssh
touch /home/git/.ssh/authorized_keys
chmod 600 /home/git/.ssh/authorized_keys
chmod -R 700 /home/git/data
exit #back to root

#permissions fix:
chown -R git:git /home/git
chmod 711 /home/git
</pre>
<p>At this point, we need to make a secret cookie for a configuration file, make note of the output from this command.</p>
<pre class="brush: bash; title: ; notranslate">
apg -m 64
#sample output below, DON’T use it!
[root@string ~]# apg -m 64
SwouncievNivJucivrevnisfookEcnasiarHamgogdipmopyicbyctyikBagArim
gronugAmIsUkDifpoyftEggobviuzIpArgecHewElsOcubnuejEtDecerlyooHib
smivyecivfalakMarfAvikokip^ojyorwahonkIrEdeibZepbivsaftIdmapmic)
frivetcetEceivepJuxNeipnidzaroyffAgVevfuIvDesemAfyacAppAtdeavays
wenEjUcoofnafryefGewboshkyersufcawJontIavZenFeifWoitGejEajnoiWry
sawidHewofOkheTwiOjFigWigbobinCushBurnErnodedLuenAtTeyznoynoryop
</pre>
<p>There are several ruby environments for different modes of Ruby, these are Test, Development, and Production.  Although we have to set up the Development and Test environments (mostly to avoid errors and warnings), I will only use the Production Environment in the end.  Also, don’t use the key above, or below, I just inserted it to give you an idea of how it should look.</p>
<pre class="brush: bash; title: ; notranslate">
vim /home/git/gitorious/config/gitorious.yml

#For production, development, and test sections:
#copy paste exactly (new lines count), if you get an error below, this file will be where to look.
development:
  cookie_secret: SwouncievNivJucivrevnisfookEcnasiarHamgogdipmopyicbyctyikBagArimgronugAmIsUkDifpoyftEggobviuzIpArgecHewElsOcubnuejEtDecerlyooHibsmivyecivfalakMarfAvikokip^ojyorwahonkIrEdeibZepbivsaftIdmapmic)frivetcetEceivepJuxNeipnidzaroyffAgVevfuIvDesemAfyacAppAtdeavayswenEjUcoofnafryefGewboshkyersufcawJontIavZenFeifWoitGejEajnoiWrysawidHewofOkheTwiOjFigWigbobinCushBurnErnodedLuenAtTeyznoynoryop
  repository_base_path: &quot;/home/git/data/repositories&quot;
  extra_html_head_data:
  system_message:
  gitorious_client_port: 80
  gitorious_client_host: git.matthouse.us
  gitorious_host: git.matthouse.us
  gitorious_user: git
  exception_notification_emails: admin@matthouse.us
  mangle_email_addresses: true
  public_mode: true
  locale: en
  archive_cache_dir: &quot;/home/git/data/tarballs&quot;
  archive_work_dir: &quot;/home/git/data/tarball-work&quot;
  only_site_admins_can_create_projects: true
  hide_http_clone_urls: false
  is_gitorious_dot_org: false

test:
  cookie_secret: SwouncievNivJucivrevnisfookEcnasiarHamgogdipmopyicbyctyikBagArimgronugAmIsUkDifpoyftEggobviuzIpArgecHewElsOcubnuejEtDecerlyooHibsmivyecivfalakMarfAvikokip^ojyorwahonkIrEdeibZepbivsaftIdmapmic)frivetcetEceivepJuxNeipnidzaroyffAgVevfuIvDesemAfyacAppAtdeavayswenEjUcoofnafryefGewboshkyersufcawJontIavZenFeifWoitGejEajnoiWrysawidHewofOkheTwiOjFigWigbobinCushBurnErnodedLuenAtTeyznoynoryop
  repository_base_path: &quot;/home/git/data/repositories&quot;
  extra_html_head_data:
  system_message:
  gitorious_client_port: 80
  gitorious_client_host: git.matthouse.us
  gitorious_host: git.matthouse.us
  gitorious_user: git
  exception_notification_emails: admin@matthouse.us
  mangle_email_addresses: true
  public_mode: true
  locale: en
  archive_cache_dir: &quot;/home/git/data/tarballs&quot;
  archive_work_dir: &quot;/home/git/data/tarball-work&quot;
  only_site_admins_can_create_projects: true
  hide_http_clone_urls: false
  is_gitorious_dot_org: false

production:
  cookie_secret: SwouncievNivJucivrevnisfookEcnasiarHamgogdipmopyicbyctyikBagArimgronugAmIsUkDifpoyftEggobviuzIpArgecHewElsOcubnuejEtDecerlyooHibsmivyecivfalakMarfAvikokip^ojyorwahonkIrEdeibZepbivsaftIdmapmic)frivetcetEceivepJuxNeipnidzaroyffAgVevfuIvDesemAfyacAppAtdeavayswenEjUcoofnafryefGewboshkyersufcawJontIavZenFeifWoitGejEajnoiWrysawidHewofOkheTwiOjFigWigbobinCushBurnErnodedLuenAtTeyznoynoryop
  repository_base_path: &quot;/home/git/data/repositories&quot;
  extra_html_head_data:
  system_message:
  gitorious_client_port: 80
  gitorious_client_host: git.matthouse.us
  gitorious_host: git.matthouse.us
  gitorious_user: git
  exception_notification_emails: admin@matthouse.us
  mangle_email_addresses: true
  public_mode: true
  locale: en
  archive_cache_dir: &quot;/home/git/data/tarballs&quot;
  archive_work_dir: &quot;/home/git/data/tarball-work&quot;
  only_site_admins_can_create_projects: true
  hide_http_clone_urls: false
  is_gitorious_dot_org: false
</pre>
<p>Now let’s configure the broker.  For a while, I was confused about why other guides had me install both stomp and activemq.  It turns out that you only need one or the other.  For me, stomp was more memory friendly, so I choose that.  Towards the end of this blow, I also provide the procedure for installing ActiveMQ (which doesn’t pertain to what I’m installing).  If you want ActiveMQ, you simply have to replace “stomp” below with “activemq” to get this to work I believe (although I didn’t test that) and install ActiveMQ around this point (as detailed at the end).</p>
<pre class="brush: bash; title: ; notranslate">
vim /home/git/gitorious/config/broker.yml

production:
    adapter: stomp
development:
    adapter: stomp
test:
    adapter: stomp
</pre>
<p>Now let’s go through some more commands, including database configuration.  Replace the <PASSWORD> prompts with your own.</p>
<p>f
<pre class="brush: bash; title: ; notranslate">
#permissions fix:
chown -R git:git /home/git

mysql -uroot –p’&lt;ROOT’S MYSQL PASSWORD&gt;'

create database gitorious;
create database gitorious_test;
create database gitorious_dev;
CREATE user 'git'@'localhost' IDENTIFIED BY '&lt;PASWORD&gt;';
GRANT ALL ON gitorious.* TO 'git'@'localhost';
GRANT ALL ON gitorious_test.* TO 'git'@'localhost';
GRANT ALL ON gitorious_dev.* TO 'git'@'localhost';
FLUSH privileges;
exit;
</pre>
<p>One more major edit to a file to go!  Once again, replace <PASSWORD> with the one you used above.</p>
<pre class="brush: bash; title: ; notranslate">
vim /home/git/gitorious/config/database.yml

development:
  adapter: mysql
  database: gitorious_dev
  username: git
  password: &lt;PASWORD&gt;
  host: localhost
  encoding: utf8

test:
  adapter: mysql
  database: gitorious_test
  username: git
  password: &lt;PASWORD&gt;
  host: localhost
  encoding: utf8

production:
  adapter: mysql
  database: gitorious
  username: git
  password: &lt;PASWORD&gt;
  host: localhost
  encoding: utf8
</pre>
<p>Now some more commands to configure gitorious.  I was a little obsessive with fixing permissions (since I did a lot as root), but I wanted to make sure that I wouldn’t hit unknown errors and bugs.</p>
<pre class="brush: bash; title: ; notranslate">
#fix permissions
cd /home
chown -R git:git /home/git
cd /home/git
chmod -R 755 data
chmod 755 gitorious

cd /home/git/gitorious
bundle exec rake db:create:all
bundle exec rake db:setup
bundle exec rake db:migrate

#fix permissions
cd /home
chown -R git:git /home/git
cd /home/git
chmod -R 755 data
chmod 755 gitorious
</pre>
<p>It’s now time to start some services related to Gitorious.  Make sure that there are no errors in this section.  I recommend executing line by line.</p>
<pre class="brush: bash; title: ; notranslate">
ln -s /home/git/gitorious/doc/templates/centos/git-daemon /etc/init.d/git-daemon
chmod +x /etc/init.d/git-daemon
chkconfig --add git-daemon
service git-daemon start

ln -s /home/git/gitorious/doc/templates/centos/stomp /etc/init.d/stomp
chmod +x /etc/init.d/stomp
chkconfig --add stomp
service stomp start

ln -s /home/git/gitorious/doc/templates/centos/git-poller /etc/init.d/git-poller
chmod +x /etc/init.d/git-poller
chkconfig --add git-poller
service git-poller start
</pre>
<p>At this point, we can get into the Apache configuration.  To download from gitorious, we need mod_xsendfile.  To the best of my knowledge, Gitorious drops the executable bit off from the tar archives it creates, so the files cannot be accessed traditionally.  This presents a problem and this modification makes the files downloadable without the executable bit being set.</p>
<pre class="brush: bash; title: ; notranslate">
yum install -y httpd httpd-devel mod_xsendfile
#mod qos for sloworis attack control and DOS attack control
cd ~
mkdir apachemod
cd apachemod
wget http://sourceforge.net/projects/mod-qos/files/mod_qos-9.57.tar.gz/download
tar xzf mod_qos-9.57.tar.gz
cd mod_qos-9.57/apache2
apxs -i -c mod_qos.c
chmod 755 /usr/lib64/httpd/modules/mod_qos.so
#configure xsendfile

vim /etc/httpd/conf.d/xsendfile.conf
#add below LoadModule line
XSendFile on
XSendFilePath /home/git/data/tarballs
#UPDATE 6/8/11: Add a path to the repositories folder for git to work over http.
XSendFilePath /home/git/data/repositories

#install ruby Passenger to make Ruby applications work on Apache.

/opt/ruby-enterprise-1.8.7-2011.03/bin/passenger-install-apache2-module
#accept the defaults
</pre>
<p>At this point, we now need to configure Apache.  I do this with a two file approach separating the website configuration from the server configuration.  If you copy paste my httpd.conf file, it will serve you well, provided you change the “ServerAdmin” and “ServerName” directives (options).  The same isn’t true of my host.conf file, you’re going to have to modify that for your particular installation.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/httpd/conf
vim httpd.conf

### Section 1: Global Environment
ServerTokens OS
ServerRoot &quot;/etc/httpd&quot;
PidFile run/httpd.pid
Timeout 120
KeepAlive Off
MaxKeepAliveRequests 100
KeepAliveTimeout 15
Listen 80

LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_alias_module modules/mod_authn_alias.so
LoadModule authn_anon_module modules/mod_authn_anon.so
LoadModule authn_dbm_module modules/mod_authn_dbm.so
LoadModule authn_default_module modules/mod_authn_default.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_owner_module modules/mod_authz_owner.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_dbm_module modules/mod_authz_dbm.so
LoadModule authz_default_module modules/mod_authz_default.so
LoadModule ldap_module modules/mod_ldap.so
LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
LoadModule include_module modules/mod_include.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule logio_module modules/mod_logio.so
LoadModule env_module modules/mod_env.so
LoadModule ext_filter_module modules/mod_ext_filter.so
LoadModule mime_magic_module modules/mod_mime_magic.so
LoadModule expires_module modules/mod_expires.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule headers_module modules/mod_headers.so
LoadModule usertrack_module modules/mod_usertrack.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule info_module modules/mod_info.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule actions_module modules/mod_actions.so
LoadModule speling_module modules/mod_speling.so
LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule cache_module modules/mod_cache.so
LoadModule suexec_module modules/mod_suexec.so
LoadModule disk_cache_module modules/mod_disk_cache.so
LoadModule file_cache_module modules/mod_file_cache.so
#LoadModule mem_cache_module modules/mod_mem_cache.so
LoadModule cgi_module modules/mod_cgi.so
LoadModule version_module modules/mod_version.so
#LoadModule cern_meta_module modules/mod_cern_meta.so
#LoadModule asis_module modules/mod_asis.so

LoadModule unique_id_module modules/mod_unique_id.so
LoadModule qos_module /usr/lib64/httpd/modules/mod_qos.so

LoadModule passenger_module /opt/ruby/lib/ruby/gems/1.8/gems/passenger-3.0.7/ext/apache2/mod_passenger.so
   PassengerRoot /opt/ruby/lib/ruby/gems/1.8/gems/passenger-3.0.7
   PassengerRuby /opt/ruby/bin/ruby

Include conf.d/*.conf
#ExtendedStatus On
User apache
Group apache

### Section 2: 'Main' server configuration

ServerAdmin admin@matthouse.us
ServerName string.matthouse.us:80
UseCanonicalName Off
DocumentRoot &quot;/var/www/html&quot;

&lt;Directory /&gt;
    Options FollowSymLinks
    AllowOverride All
&lt;/Directory&gt;

&lt;IfModule mod_userdir.c&gt;
    UserDir public_html
&lt;/IfModule&gt;

DirectoryIndex index.html index.html.var index.htm
AccessFileName .htaccess

&lt;Files ~ &quot;^.ht&quot;&gt; #deny serving ht files
    Order allow,deny
    Deny from all
&lt;/Files&gt;

TypesConfig /etc/mime.types
DefaultType text/plain
&lt;IfModule mod_mime_magic.c&gt;
#   MIMEMagicFile /usr/share/magic.mime
    MIMEMagicFile conf/magic
&lt;/IfModule&gt;

HostnameLookups Off
#EnableMMAP off
#EnableSendfile off
ErrorLog logs/error_log
LogLevel warn

LogFormat &quot;%h %l %u %t &quot;%r&quot; %&gt;s %b &quot;%{Referer}i&quot; &quot;%{User-Agent}i&quot;&quot; combined
LogFormat &quot;%h %l %u %t &quot;%r&quot; %&gt;s %b&quot; common
LogFormat &quot;%{Referer}i -&gt; %U&quot; referer
LogFormat &quot;%{User-agent}i&quot; agent
#LogFormat &quot;%h %l %u %t &quot;%r&quot; %&gt;s %b &quot;%{Referer}i&quot; &quot;%{User-Agent}i&quot; %I %O&quot; combinedio

#CustomLog logs/access_log common
#CustomLog logs/referer_log referer
#CustomLog logs/agent_log agent
CustomLog logs/access_log combined

ServerSignature On

Alias /icons/ &quot;/var/www/icons/&quot;
&lt;Directory &quot;/var/www/icons&quot;&gt;
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
&lt;/Directory&gt;

#
# WebDAV module configuration section.
#
&lt;IfModule mod_dav_fs.c&gt;
    # Location of the WebDAV lock database.
    DAVLockDB /var/lib/dav/lockdb
&lt;/IfModule&gt;
ScriptAlias /cgi-bin/ &quot;/var/www/cgi-bin/&quot;
&lt;Directory &quot;/var/www/cgi-bin&quot;&gt;
    AllowOverride All
    Options None
    Order allow,deny
    Allow from all
&lt;/Directory&gt;

# Redirect permanent /foo http://www.example.com/bar

# Directives controlling the display of server-generated directory listings.
IndexOptions FancyIndexing VersionSort NameWidth=* HTMLTable
AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
AddIconByType (TXT,/icons/text.gif) text/*
AddIconByType (IMG,/icons/image2.gif) image/*
AddIconByType (SND,/icons/sound2.gif) audio/*
AddIconByType (VID,/icons/movie.gif) video/*
AddIcon /icons/binary.gif .bin .exe
AddIcon /icons/binhex.gif .hqx
AddIcon /icons/tar.gif .tar
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
AddIcon /icons/a.gif .ps .ai .eps
AddIcon /icons/layout.gif .html .shtml .htm .pdf
AddIcon /icons/text.gif .txt
AddIcon /icons/c.gif .c
AddIcon /icons/p.gif .pl .py
AddIcon /icons/f.gif .for
AddIcon /icons/dvi.gif .dvi
AddIcon /icons/uuencoded.gif .uu
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
AddIcon /icons/tex.gif .tex
AddIcon /icons/bomb.gif core
AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README
AddIcon /icons/folder.gif ^^DIRECTORY^^
AddIcon /icons/blank.gif ^^BLANKICON^^
DefaultIcon /icons/unknown.gif
#AddDescription &quot;GZIP compressed document&quot; .gz
#AddDescription &quot;tar archive&quot; .tar
#AddDescription &quot;GZIP compressed tar archive&quot; .tgz
ReadmeName README.html
HeaderName HEADER.html
IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t

AddLanguage ca .ca
AddLanguage cs .cz .cs
AddLanguage da .dk
AddLanguage de .de
AddLanguage el .el
AddLanguage en .en
AddLanguage eo .eo
AddLanguage es .es
AddLanguage et .et
AddLanguage fr .fr
AddLanguage he .he
AddLanguage hr .hr
AddLanguage it .it
AddLanguage ja .ja
AddLanguage ko .ko
AddLanguage ltz .ltz
AddLanguage nl .nl
AddLanguage nn .nn
AddLanguage no .no
AddLanguage pl .po
AddLanguage pt .pt
AddLanguage pt-BR .pt-br
AddLanguage ru .ru
AddLanguage sv .sv
AddLanguage zh-CN .zh-cn
AddLanguage zh-TW .zh-tw
LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
ForceLanguagePriority Prefer Fallback
AddDefaultCharset UTF-8
#AddType application/x-tar .tgz
#AddEncoding x-compress .Z
#AddEncoding x-gzip .gz .tgz
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz

AddHandler cgi-script .cgi .pl
#AddHandler send-as-is asis
AddHandler type-map var
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

# 1) plain text 2) local redirects 3) external redirects
#ErrorDocument 500 &quot;The server made a boo boo.&quot;
#ErrorDocument 404 /missing.html
#ErrorDocument 404 &quot;/cgi-bin/missing_handler.pl&quot;
#ErrorDocument 402 http://www.example.com/subscription_info.html

Alias /error/ &quot;/var/www/error/&quot;

&lt;IfModule mod_negotiation.c&gt;
&lt;IfModule mod_include.c&gt;
    &lt;Directory &quot;/var/www/error&quot;&gt;
        AllowOverride None
        Options IncludesNoExec
        AddOutputFilter Includes html
        AddHandler type-map var
        Order allow,deny
        Allow from all
        LanguagePriority en es de fr
        ForceLanguagePriority Prefer Fallback
    &lt;/Directory&gt;

#    ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
#    ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
#    ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
#    ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
#    ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
#    ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
#    ErrorDocument 410 /error/HTTP_GONE.html.var
#    ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
#    ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
#    ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
#    ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
#    ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
#    ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
#    ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
#    ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
#    ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
#    ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var

&lt;/IfModule&gt;
&lt;/IfModule&gt;

BrowserMatch &quot;Mozilla/2&quot; nokeepalive
BrowserMatch &quot;MSIE 4.0b2;&quot; nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch &quot;RealPlayer 4.0&quot; force-response-1.0
BrowserMatch &quot;Java/1.0&quot; force-response-1.0
BrowserMatch &quot;JDK/1.0&quot; force-response-1.0
BrowserMatch &quot;Microsoft Data Access Internet Publishing Provider&quot; redirect-carefully
BrowserMatch &quot;MS FrontPage&quot; redirect-carefully
BrowserMatch &quot;^WebDrive&quot; redirect-carefully
BrowserMatch &quot;^WebDAVFS/1.[0123]&quot; redirect-carefully
BrowserMatch &quot;^gnome-vfs/1.0&quot; redirect-carefully
BrowserMatch &quot;^XML Spy&quot; redirect-carefully
BrowserMatch &quot;^Dreamweaver-WebDAV-SCM1&quot; redirect-carefully

&lt;IfModule prefork.c&gt;
StartServers       1
MinSpareServers    1
MaxSpareServers  1
ServerLimit      128
MaxClients       128
MaxRequestsPerChild  1000
&lt;/IfModule&gt;

### Section 3: CONF STUFF
Include conf/host.conf
</pre>
<p>Next is the virtual host configuration.  I chose to use https / ssl with a self-signed certificate, so that procedure is below.  The following probably won’t be a perfect cut / paste for you, but it will be close enough provided you fill in the blanks.  If you wish to not use https, simply copy the basic host.conf file and remove the SSL elements (including the port 443 stuff).</p>
<pre class="brush: bash; title: ; notranslate">
cd ~
yum install –y mod_ssl openssl
openssl genrsa -out ca.key 2048
openssl req -new -key ca.key -out ca.csr
#Enter in the information

#sample information
#Country Name (2 letter code) [GB]:US
#State or Province Name (full name) [Berkshire]:NEW YORK
#Locality Name (eg, city) [Newbury]:GREAT VALLEY
#Organization Name (eg, company) [My Company Ltd]:MATTHOUSE
#Organizational Unit Name (eg, section) []:
#Common Name (eg, your name or your server's hostname) []:string.matthouse.us
#Email Address []:admin@matthouse.us
#
#Please enter the following 'extra' attributes to be sent with your certificate request
#A challenge password []:
#An optional company name []:

openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
cp ca.crt /etc/pki/tls/certs
cp ca.key /etc/pki/tls/private/ca.key
cp ca.csr /etc/pki/tls/private/ca.csr
mv /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.disabled
</pre>
<p>Now we make the virtualhost include file.</p>
<pre class="brush: bash; title: ; notranslate">
vim /etc/httpd/conf/host.conf

#enable ~user home directories.
&lt;Directory /home/*/public_html&gt;
    Options MultiViews Indexes SymLinksIfOwnerMatch Includes ExecCGI
    AllowOverride All
    Order allow,deny
    Allow from all
&lt;/Directory&gt;

NameVirtualHost *:80

&lt;VirtualHost *:80&gt;
        ServerName  string.matthouse.us
        ServerAlias www.string.matthouse.us
        ServerAdmin admin@matthouse.us
        DocumentRoot /var/www
        ErrorLog  /var/www/error.log
        CustomLog /var/www/access.log combined
&lt;/VirtualHost&gt;

&lt;VirtualHost *:80&gt;
        ServerName  git.matthouse.us
        ServerAdmin admin@matthouse.us
        DocumentRoot /home/git/gitorious/public
        ErrorLog  /var/www/errorgit.log
        CustomLog /var/www/accessgit.log combined
#customlog is good for awstats software
        &lt;Directory /home/git/gitorious/public&gt;
          AllowOverride all
          Options -MultiViews
        &lt;/Directory&gt;
&lt;/VirtualHost&gt;

LoadModule ssl_module modules/mod_ssl.so
Listen 443
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl
SSLPassPhraseDialog  builtin
SSLSessionCache         shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout  300
SSLMutex default
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

NameVirtualHost *:443

&lt;VirtualHost *:443&gt;
        SSLEngine on
        SSLCertificateFile /etc/pki/tls/certs/ca.crt
        SSLCertificateKeyFile /etc/pki/tls/private/ca.key
        SSLProtocol all -SSLv2
        SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
        ServerName  git.matthouse.us
        ServerAdmin admin@matthouse.us
        DocumentRoot /home/git/gitorious/public
        ErrorLog  /var/www/errorgit.log
        CustomLog /var/www/accessgit.log combined
        &lt;Directory /home/git/gitorious/public&gt;
          AllowOverride all
          Options -MultiViews
        &lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p>At this point, test the Apache server configuration and start it.  Then we will fix permissions once more.</p>
<pre class="brush: bash; title: ; notranslate">
service httpd configtest
service httpd start
#fix permissions again
cd /home
chmod 711 git
chown -R git:git git
</pre>
<p>It’s now time to add a Gitorious user!</p>
<pre class="brush: bash; title: ; notranslate">
su git
cd ~/gitorious
env RAILS_ENV=production script/create_admin

#sample
Type in Administrator's e-mail:
admin@matthouse.us
Type in Administrator's password:
&lt;APASSWORD&gt;
Admin user created successfully.

exit
#exit back to root
</pre>
<p>Next, if you wish to disable most of the SSL links on your Gitorious install, do the following (I did this).  In the install that I did, I enabled SSL so that for the few links that went to https sites, Gitorious would continue to work (with a few warnings of course because self-signed certificates aren’t trusted and I’m not paying for a trusted rapidssl certificate for how little I am going to use Gitorious myself).</p>
<p><strong>UPDATE 6/8/11: The SSLRequirement directive is no longer required in production.rb (below).  Instead, add &#8220;disable_ssl&#8221; OR &#8220;enable_ssl&#8221; as a line to the file /home/git/gitorious/config/gitorious.yml (as the git user).</strong></p>
<pre class="brush: bash; title: ; notranslate">
#disable SSL links (for the most part
su git
vim ~/gitorious/config/environments/production.rb
#add the following line somewhere in the file at the top:
SslRequirement.disable_ssl_check = true
exit
#exit back to root
</pre>
<p>It’s now time to configure ultrasphinx.  I believe that this is used mostly for indexing and searching the Gitorious site, but it could be used for other functionality too.</p>
<pre class="brush: bash; title: ; notranslate">
cd /home/git/gitorious 

export RAILS_ENV=production
export PATH=/usr/local/sphinx/bin:$PATH

bundle exec rake ultrasphinx:configure RAILS_ENV=production
bundle exec rake ultrasphinx:index RAILS_ENV=production
bundle exec rake ultrasphinx:daemon:start RAILS_ENV=production

#the following command builds the sphinx dictionary.  For me it seg faults, but gets rid of a pesky dictionary error.
cd /home/git/gitorious
aspell config dict-dir
   /usr/lib64/aspell-0.60
cp vendor/plugins/ultrasphinx/examples/ap.multi /usr/lib64/aspell-0.60/
#the next command segfaults, but it makes an annoying error go away in a log
bundle exec rake ultrasphinx:spelling:build

#due to some deprecation in code, the following two changes need to happen:
vim /home/git/gitorious/config/ultrasphinx/production.conf

#change &quot;address&quot; to &quot;listen&quot; due to deprecation
  listen = 0.0.0.0
#change memlimit from 256 to 64 to conserve memory
indexer {
  mem_limit = 64M

#Finally, we need to make git-ultrasphinx a daemon.
ln -s /home/git/gitorious/doc/templates/centos/git-ultrasphinx /etc/init.d/git-ultrasphinx
chmod +x /etc/init.d/git-ultrasphinx

#make mysqld and httpd start automatically
chkconfig mysqld on
chkconfig httpd on

#a few bug fixes
ln -s /usr/local/bin/gitorious /usr/bin

#install imagemagick via yum
#yes, we compiled from source to get rid of an error… but gitorious will have other errors if we don’t
yum –y install ImageMagick

#One last time, I will fix the permissions
cd /home
chown -R git:git /home/git
cd /home/git
chmod -R 755 data
chmod 755 gitorious
</pre>
<p>We now need to install memcached for Gitorious.  I originally thought this was strictly for performance, but Gitorious expects it to be installed.  I use the remi repository for this since the other repositories have broken dependencies.</p>
<pre class="brush: bash; title: ; notranslate">
yum install -y --enablerepo=remi memcached
service memcached start
chkconfig memcached on
</pre>
<p>At this point, everything is almost configured fully.  I don’t start the git daemons / services automatically with chkconfig because they won’t run at system startup (I don’t know why).  Therefore, I created a special script and made that start automatically upon reboot using the cron daemon (using the @reboot option).</p>
<pre class="brush: bash; title: ; notranslate">
vim /root/startup.sh

#!/bin/sh
/etc/init.d/stomp start
/etc/init.d/git-daemon start
/etc/init.d/git-poller start
/etc/init.d/git-ultrasphinx start
</pre>
<pre class="brush: bash; title: ; notranslate">
crontab –e
#add the following to root’s crontab
MAILTO=&quot;&quot;
@reboot /root/startup.sh
</pre>
<p>Next, we need to index the Gitorious site every hour.</p>
<pre class="brush: bash; title: ; notranslate">
su git
crontab –e
#add the following to git’s cron, which indexes the site every hour
MAILTO=&quot;&quot;
* */1 * * * cd /home/git/gitorious &amp;amp;&amp;amp; /opt/ruby/bin/rake ultrasphinx:index RAILS_ENV=production
exit
#exit to root
</pre>
<p>Finally, reboot the VPS.  With any luck, everything will work once its rebooted.  I went to the site and tested the following functionality:</p>
<ul>
<li>Adding an ssh key</li>
<li>Adding a new repository</li>
<li>Adding a wiki page</li>
<li>Deleting the above stuff</li>
<li>Committing to the repository from a local repository</li>
</ul>
<p>The above is all I required of Gitorious.  Unfortunately, the included tests did not successfully complete for me due to the memory restrictions, but I saw several errors.  I don’t think the tests would fully pass, but the basic functionality that I need is present and that is what matters.  Below is what you can do (as root) to run the tests for yourself.</p>
<pre class="brush: bash; title: ; notranslate">
cd /home/git/gitorious
bundle exec rake test
</pre>
<p>With the above said, I then went ahead and configured a simple firewall to protect the Gitorious machine.  Below was the procedure for that.</p>
<pre class="brush: bash; title: ; notranslate">
vim /etc/firewall.sh

#!/bin/bash
# My system IP/set ip address of server
SERVER_IP=&quot;205.234.203.115&quot;
# Flushing all rules
iptables -F
iptables -X

# Setting default filter policy
service iptables restart
iptables -F
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

#allowed inbound
#ssh
iptables -A INPUT -p tcp -s 0/0 -d $SERVER_IP --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -s 0/0 -d $SERVER_IP --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -s 0/0 -d $SERVER_IP --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -s 0/0 -d $SERVER_IP --dport 9418 -m state --state NEW,ESTABLISHED -j ACCEPT

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
#allow ping
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
iptables  -A INPUT -j DROP
</pre>
<p>Next, we need to add the firewall to system startup.</p>
<pre class="brush: bash; title: ; notranslate">
chmod +x /etc/firewall.sh

crontab –e
#add the following at the bottom
@reboot /etc/firewall.sh
</pre>
<p>The (relatively simple) firewall is now configured to allow incoming pings to the server, SSH access, HTTP access, and GIT access using the git protocol.  If you have issues like I did with an unknown error, your VPS provider will have to enable the connection tracking feature of IPTables for you, otherwise committing to a gitorious repository will not work.</p>
<p>I also configured sendmail to send mail from this machine appropriately.  Below is a simple procedure for this.  You could get a lot more in depth, but it isn’t necessary.  Note that using this method, all mail will be sent from <a href="mailto:user@string.matthouse.us">user@string.matthouse.us</a> in my case (since this is the machine hostname).</p>
<pre class="brush: bash; title: ; notranslate">
vim /etc/mail/local-host-names
#add local hosts as appropriate
localhost
string.matthouse.us
git.matthouse.us

vim /root/.forward
#add your email address to the first line
admin@matthouse.us

service sendmail restart
</pre>
<p><strong>With that, the Gitorious install is officially Installed</strong>.  I will not continue onto the ActiveMQ installation as mentioned above, this is only required if you chose to use ActiveMQ as a broker instead of Stomp.</p>
<p>Below is the ActiveMQ installation procedure (as written in my internal documentation) for your enjoyment.  I will not explain this, but I thought it would be appropriate to include it since I originally followed it to a dead end!  This is strictly not required for the above installation and will do nothing to help you if you’re getting errors above (while using stomp as I did).</p>
<pre class="brush: bash; title: ; notranslate">
wget http://apache.spd.co.il/activemq/apache-activemq/5.5.0/apache-activemq-5.5.0-bin.tar.gz
tar xzvf apache-activemq-5.5.0-bin.tar.gz
mv apache-activemq-5.5.0 /usr/local/apache-activemq5.50
cd /usr/local
ln -s apache-activemq5.50 apache-activemq
cd ~
adduser activemq
chown -R activemq /usr/local/apache-activemq/data

cd /usr/local/apache-activemq5.50/

vim bin/activemq

#change comments to:

 ACTIVEMQ_SUNJMX_START=&quot;$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.ssl=false&quot;
#ACTIVEMQ_SUNJMX_START=&quot;$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote&quot;

vim /usr/local/apache-activemq/bin/activemq-admin
find: ACTIVEMQ_OPTS=&quot;-Xmx512M -Dorg.apache.activemq.UseDedicatedTaskRunner=true -Djava.util.logging.config.file=logging.properties&quot;
replace: ACTIVEMQ_OPTS=&quot;-Xmx64M -Dorg.apache.activemq.UseDedicatedTaskRunner=true -Djava.util.logging.config.file=logging.properties&quot;

vim activemqstart.sh

#!/bin/bash
export JAVA_HOME=/usr/lib/jvm/jre
export _JAVA_OPTIONS=-Xmx64m
/usr/local/apache-activemq/bin/activemq-admin start &amp;amp;

vim activemqstop.sh

#!/bin/bash
export JAVA_HOME=/usr/lib/jvm/jre
export _JAVA_OPTIONS=-Xmx64m
/usr/local/apache-activemq/bin/activemq-admin stop

chmod +x activemqstart.sh
chmod +x activemqstop.sh

cd /etc/init.d
vim activemq

#!/bin/bash
#
# activemq       Starts ActiveMQ.
#
#
# chkconfig: 345 88 12
# description: ActiveMQ is a JMS Messaging Queue Server.
### BEGIN INIT INFO
# Provides: $activemq
### END INIT INFO

# Source function library.
. /etc/init.d/functions

export _JAVA_OPTIONS=-Xmx64m

[ -f /usr/local/apache-activemq/activemqstart.sh ] || exit 0
[ -f /usr/local/apache-activemq/activemqstop.sh ] || exit 0

RETVAL=0

umask 077

start() {
       echo -n $&quot;Starting ActiveMQ: &quot;
       daemon /usr/local/apache-activemq/activemqstart.sh
       echo
       return $RETVAL
}
stop() {
       echo -n $&quot;Shutting down ActiveMQ: &quot;
       daemon su -c /usr/local/apache-activemq/activemqstop.sh activemq
       echo
       return $RETVAL
}
restart() {
       stop
       start
}
case &quot;$1&quot; in
 start)
       start
       ;;
 stop)
       stop
       ;;
 restart|reload)
       restart
       ;;
 *)
       echo $&quot;Usage: $0 {start|stop|restart}&quot;
       exit 1
esac

exit $?

#run these commands
chmod +x activemq
chkconfig activemq on
</pre>
<p>Whew, this is the longest blog I’ve ever written!  That just goes to show the complexity of Gitorious, not to mention the administrative overhead of maintaining Ruby and Imagemagick, possible even ActiveMQ (since they were installed from source).  This blog post is in no way shape or form a complete guide to getting Gitorious installed and functional, but it will help get you most of the way there.  Because of the complexity of this software, I will likely not be of much help for any problems that I might be asked to help resolve.  As a disclaimer, use the information in this blog post at your own risk, I’m not responsible for the loss of any data, time or profits that you might incur from following this guide.</p>
<p>As always, thanks for reading!</p>
<p><strong>Special thanks to Marius Mathiesen for comments about inaccuracies in this tutorial.  Information is up to date as of 6/8/2011.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://famousphil.com/blog/2011/06/installing-gitorious-on-centos-5-6-x64/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
	</channel>
</rss>

<!-- Served from: famousphil.com @ 2012-02-10 20:33:58 by W3 Total Cache -->
