<?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>Orange is my favorite color &#187; Linux</title>
	<atom:link href="http://www.ghidinelli.com/c/webinternet/linux/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ghidinelli.com</link>
	<description></description>
	<lastBuildDate>Fri, 27 Jan 2017 17:45:50 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Jstat in Java 1.8 Can&#8217;t Find Process Run as Root</title>
		<link>http://www.ghidinelli.com/2015/08/20/jstat-in-java-1-8-cant-find-process-run-as-root</link>
		<comments>http://www.ghidinelli.com/2015/08/20/jstat-in-java-1-8-cant-find-process-run-as-root#comments</comments>
		<pubDate>Thu, 20 Aug 2015 17:55:29 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jvm]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1649</guid>
		<description><![CDATA[Jstat not working under Java 1.7 u75 or higher including Java 8? There's a bug! Here's how to work around it to get your JVM details.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a handful of times on <a href="https://www.ghidinelli.com/2009/07/16/finding-memory-leaks-coldfusion-jvm">observing and tuning the JVM</a> using tools such as Jstat. I recently upgraded our servers to Java 8 and found that my Jstat script could no longer find the process no matter what I tried.</p>
<p>It turns out <a href="https://bugs.openjdk.java.net/browse/JDK-8073858">there is a bug</a> from JDK 1.7 u75 onwards that is present at least through JDK 1.8 u60 which prevents Jstat, when run as root, from introspecting JREs running as other users.</p>
<p>To solve, simply run jstat as the user who owns the JRE process.  You can pass the username to sudo when running jstat like:</p>
<p><code>sudo -u nobody jstat -gcutil -t &lt;pid&gt; 1s 30</code></p>
<p>And you&#8217;ll be treated to your output again. In my case, I have two server instances running so I like to see their output side by side at the console.  Here&#8217;s my script for doing that using /usr/bin/paste and some console redirection trickery:</p>
<p><script src="https://gist.github.com/ghidinelli/a57dd23c03005f0980e8.js"></script></p>
<p>The username can be figured out from the process but this was a quick fix for the above bug.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2015/08/20/jstat-in-java-1-8-cant-find-process-run-as-root/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bypass Oracle License Agrement to Download JDK</title>
		<link>http://www.ghidinelli.com/2012/04/16/bypass-oracle-license-agrement-to-download-jdk</link>
		<comments>http://www.ghidinelli.com/2012/04/16/bypass-oracle-license-agrement-to-download-jdk#comments</comments>
		<pubDate>Tue, 17 Apr 2012 03:20:53 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1461</guid>
		<description><![CDATA[Feed Oracle magic cookies so you can download the JDK to your server directly and bypass their license acknowledgement which doesn't work from text mode browsers such as elinks, lynx and wget.]]></description>
			<content:encoded><![CDATA[<p>Oracle recently switched to force everyone to acknowledge their license before downloading the JDK.  That&#8217;s not a big deal, except that <em>it doesn&#8217;t work from text-mode console browsers like lynx or elinks</em>.  Those of us who need Java on the server (like CentOS/RedHat) are stuck in an endless loop.</p>
<p>Thankfully @kdecherf <a href="http://blog.kdecherf.com/2012/04/12/oracle-i-download-your-jdk-by-eating-magic-cookies/">hacked up a wget command</a> to force-feed the proper cookies.</p>
<p>If you want to grab 1.6.0_31, replace the URL in his example with:</p>
<pre><code>http://download.oracle.com/otn-pub/java/jdk/6u31-b04/jdk-6u31-linux-x64-rpm.bin</code></pre>
<p>Note: I&#8217;ve already agreed to the terms from my desktop; I just can&#8217;t download it to the server.</p>
<p><strong>UPDATE 2016</strong> &#8211; @kdecherf&#8217;s URL has been updated above for JDK7. I find myself returning to it regularly so I&#8217;m capturing a JDK8 download URL here for posterity:</p>
<pre><code>wget --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie;" http://download.oracle.com/otn-pub/java/jdk/8u92-b14/jdk-8u92-linux-x64.rpm</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2012/04/16/bypass-oracle-license-agrement-to-download-jdk/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>October Qmail Follow-up</title>
		<link>http://www.ghidinelli.com/2011/10/20/october-qmail-follow-up</link>
		<comments>http://www.ghidinelli.com/2011/10/20/october-qmail-follow-up#comments</comments>
		<pubDate>Thu, 20 Oct 2011 20:04:54 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Research/HOWTO]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[qmail]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1365</guid>
		<description><![CDATA[A couple of tweaks for QmailToaster install to update CHKUSER 2.0.9 and improve DSPAM integration]]></description>
			<content:encoded><![CDATA[<p>Some notes that I don&#8217;t want to forget to follow-up on my <a href="https://www.ghidinelli.com/2011/05/04/march-qmail-server-madness">March (Q)mail Server Madness</a> post earlier this year.  Things are running great with the exception of SpamAssassin being pretty useless.  An SA rules update in the last couple of weeks has been quarantining every email from Facebook plus another 25% of my legitimate email so we&#8217;ve disabled it and we&#8217;re just letting DSPAM do it&#8217;s thing instead.  Here&#8217;s a couple of tweaks we&#8217;ve made:</p>
<h2>Upgrade to CHKUSER 2.0.9</h2>
<p>CHKUSER 2.0.9 includes one update that is very important to us: CHKUSER_DISABLE_VARIABLE.  This enhancements allows us to disable CHKUSER checks for certain relays.  In our case, our web application servers relay mail and sometimes the TO address is invalid.  Without this change, CHKUSER would deny even sending the email so bad emails would queue up on the web servers.  What we want to happen is for the mail server to accept them, bounce them and let our bounce handling routines run notifying the sender of the bad address.  Here&#8217;s the necessary steps:</p>
<ol>
<li>Download development package <a href="http://qmailtoaster.com/testing/qmail-toaster-1.03-1.3.21.src.rpm">qmail-toaster-1.03-1.3.21.src.rpm</a> which includes the CHKUSER 2.0.9 code and a few other enhancements (see <a href="http://comments.gmane.org/gmane.mail.qmail.toaster.devel/693">this thread</a>)</li>
<li>rpm -Uvh qmail-toaster-1.03-1.3.21.src.rpm</li>
<li>bunzip2 /usr/src/redhat/SOURCES/qmailtoaster-1.3.2.patch.bz2</li>
<li>vi /usr/src/redhat/SOURCES/qmailtoaster-1.3.2.patch</li>
<li>Search for &#8220;/* #define CHKUSER_DISABLE_VARIABLE&#8221; and remove the comments, save</li>
<li>Search for &#8220;/* #define CHKUSER_ENABLE_USERS_EXTENSIONS&#8221; and remove the comments to <a href="http://www.mail-archive.com/vchkpw@inter7.com/msg27903.html">re-enable dash-aliasing</a></li>
<li>bzip2 /usr/src/redhat/SOURCES/qmailtoaster-1.3.2.patch</li>
<li>cd /usr/src/redhat/SPECS</li>
<li>rpmbuild -bb &#8211;with cnt50 &#8211;target i686 qmail-toaster.spec</li>
<li>rpm -Uvh /usr/src/redhat/RPMS/i686/qmail-toaster-1.3.2.rpm</li>
</ol>
<p>Note, I&#8217;m running on x64 CentOS 5.  For some reason I had to specify the target as i686 as without the target it wanted to generate an i386 binary while everything else is i686.  I didn&#8217;t know if that would cause problems so I specified the target explicitly.</p>
<p>For any IP address we want to bypass the CHKUSER checks, we simply add an entry to /etc/tcprules.d/tcp.smtp with a RELAYCLIENT variable.  An entry might look like:</p>
<p><code>192.168.0.1:allow,RELAYCLIENT=""</code></p>
<p>Finally, the RPM update for qmail-toaster overrides your SSL certificates for SMTP.  To restore my real certificates, I had to perform the following steps (lifted from <a href="http://coreygilmore.com/blog/2008/03/14/chained-ssl-certificates-and-qmail-error-140943f2/">coregilmore.com</a>):</p>
<pre><code># cp /etc/httpd/certs/mail.msr.com.pem /var/qmail/control/servercert.pem
# ln -s /var/qmail/control/servercert.pem /var/qmail/control/clientcert.pem
# chown -h qmaild:root /var/qmail/control/clientcert.pem
# chmod 400 /var/qmail/control/servercert.pem
# qmailctl restart</code></pre>
<p>mail.msr.com.pem is simply a single concatenated file containing your key, certificate and any intermediate certificates (required for registrars like Go Daddy for example):</p>
<p><code># cat /path/to/ssl_cert.key /path/to/ssl_cert.crt /path/to/gd_intermediate_bundle.crt &amp;gt; /var/qmail/control/servercert.pem</code></p>
<h2>Updated Mailfilter Script</h2>
<p>We also expanded our mailfilter script to be a little bit smarter and handle DSPAM better.  Here&#8217;s the latest:</p>
<pre><code>SHELL="/bin/bash"
import EXT
import HOST

VUSER=`echo ${EXT%-*}`
export VUSER
USERHOME=`/mail/bin/vuserinfo -d $VUSER@$HOST`
export USERHOME

MARKTIME=`date +%s.%N`
UNIQUE=`date +%N`

logfile "/var/log/maildrop/mailfilter.log"

# Test for the existance of the Junk directory.  Create it if it doesn't exist
VERBOSE=1
log "$VUSER@$HOST[$UNIQUE] : Start user filter"

# make sure the Junk folder exists and is subscribed too
`test -d $USERHOME/Maildir/.Junk`

if ( $RETURNCODE == 1 )
{
    `/usr/bin/maildirmake -f Junk $USERHOME/Maildir`
    `echo INBOX.Junk &gt;&gt; $USERHOME/Maildir/courierimapsubscribed`
}

# make sure the retrain folder exists
`test -d $USERHOME/Maildir/.JunkRetrain`

if ( $RETURNCODE == 1 )
{
    `/usr/bin/maildirmake -f JunkRetrain $USERHOME/Maildir`
    `echo INBOX.JunkRetrain &gt;&gt; $USERHOME/Maildir/courierimapsubscribed`
}

# now analyze the SA header
if (/^X-Spam-Status: Yes/)
{
        log "$VUSER@$HOST[$UNIQUE] : SpamAssassin found SPAM"
        to "$USERHOME/Maildir/.Junk"
}
else
{
        # spamassassin thinks its ham, which means nothing, because SA sucks
        # so now we check with dspam

        # warning: exception must have one space and then the curly bracket or else syntax errors are generatead
        exception {
                xfilter "/usr/local/bin/dspam --deliver=innocent,spam --stdout --user $USERHOME"
        }

        if (/^X-DSPAM-Result: Spam/)
        {
                # dspam says spam
                log "$VUSER@$HOST[$UNIQUE] : DSPAM found SPAM"
                to "$USERHOME/Maildir/.Junk"
        }
        else
        {
                # ham in both places, deliver
                log "$VUSER@$HOST[$UNIQUE] : DSPAM found HAM (returncode = $RETURNCODE)"
                if (/^X-DSPAM-Result: Innocent/)
                {
                        log "$VUSER@$HOST[$UNIQUE] : HAM includes X-DSPAM-Result: Innocent"
                }
                else
                {
                        if (/^X-DSPAM-Result: Whitelisted/)
                        {
                                log "$VUSER@$HOST[$UNIQUE] : HAM includes X-DSPAM-Result: Whitelisted"
                        }
                        else
                        {
                                log "$VUSER@$HOST[$UNIQUE] : HAM does NOT include X-DSPAM-Result: Innocent/Whitelisted"
                        }
                }
                to "$USERHOME/Maildir/"
        }
}</code></pre>
<p>Since we&#8217;re dropping SpamAssassin, this file could be streamlined to be DSPAM specific but it doesn&#8217;t hurt to leave it in the event we decide to re-enable it at a later date.  Simply save the script somewhere and enable it via a .qmail file in a user directory with the following:</p>
<p><code>|preline /usr/bin/maildrop /path/to/mailfilter-to-spam-plus-dspam</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/10/20/october-qmail-follow-up/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>March (Q)Mail Server Madness</title>
		<link>http://www.ghidinelli.com/2011/05/04/march-qmail-server-madness</link>
		<comments>http://www.ghidinelli.com/2011/05/04/march-qmail-server-madness#comments</comments>
		<pubDate>Wed, 04 May 2011 20:14:02 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Research/HOWTO]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1258</guid>
		<description><![CDATA[March was a busy month &#8211; we were upgrading and consolidating infrastructure around here which meant taking a 2U VA Linux 2230 server that had &#8211; quite literally &#8211; been serving mail for more than a decade, and upgrading it to a more contemporary machine for which spare parts exist.  Knock on wood the [...]]]></description>
			<content:encoded><![CDATA[<p>March was a busy month &#8211; we were upgrading and consolidating infrastructure around here which meant taking a 2U VA Linux 2230 server that had &#8211; quite literally &#8211; been serving mail for more than a decade, and upgrading it to a more contemporary machine for which spare parts exist.  Knock on wood the new machine can have the same reliable track record.</p>
<p>I had been considering outsourcing everything &#8211; move incoming email to Google Apps and use someone like SMTP.com or SendGrid for outbound but there&#8217;s a few wrinkles like mailing lists and customer-relayed email.  We ultimately decided to roll a new machine but given how quickly email deliverability evolves, we needed to get up to date with the various authentication and verification technologies that help get emails into the inbox.  That meant getting waist-deep in <a href="http://en.wikipedia.org/wiki/Sender_Policy_Framework">SPF</a>, <a href="http://www.microsoft.com/mscorp/safety/technologies/senderid/default.mspx">Sender-ID</a>, <a href="http://en.wikipedia.org/wiki/DomainKeys">DomainKeys</a> and <a href="http://www.dkim.org/">DKIM</a>.  (See current <a href="https://fit.nokia.com/lars/meter/dkim.html">DKIM</a> and <a href="https://fit.nokia.com/lars/meter/spf.html">SPF</a> deployment rates &#8211; 23% and 51% globally as of this writing)</p>
<p>This isn&#8217;t a step-by-step guide; writing one would simply repeat what other people have already done a good job of documenting.  What this <em>is</em>, is an overview that ties together missing pieces and endless Google searches to move from concept to execution with one full set of examples.</p>
<h2>The Moving Pieces</h2>
<p>If you&#8217;re new to all this, here&#8217;s how these technologies work briefly: Sender ID is basically a Microsoft version of Sender Policy Framework (SPF).  If you get SPF to work, Sender ID is backwards compatible and will verify successfully.  DKIM is almost the same thing to DomainKeys but it adds <a href="http://en.wikipedia.org/wiki/Author_Domain_Signing_Practices">Author Domain Signing Practices (ADSP)</a> as an optional component that specifies how strict you are about signing messages.</p>
<p>SPF and Sender ID rely on specially crafted DNS records that identify which mail servers are allowed to send mail for your domain.  By contrast, DomainKeys/DKIM take pieces of your message, cryptographically hash them with a key (part of which only your server knows) and embed the signature as a header which is verified using the other half of your key (which is public) that is stored in a specially crafted DNS record for your domain or mail server.   You must have the ability to create DNS TXT records or none of these will work for you.  Here&#8217;s a good article with a <a href="http://www.digitalsanctuary.com/tech-blog/debian/setting-up-spf-senderid-domain-keys-and-dkim.html">more details on how it all works</a>.</p>
<p><img src="https://www.ghidinelli.com/wp-content/uploads/2011/03/dkim-verified.png" alt="DomainKeys verified mail on Yahoo gets a special lock icon showing it&#039;s verified" title="DomainKeys verified mail on Yahoo gets a special lock icon showing it&#039;s verified" width="357" height="61" class="aligncenter" /></p>
<p>The idea is to eliminate any joe spammer from using an arbitrary From address in spam, phishing and other email attacks.  None of these approaches are perfect but they are used by large ISPs like Hotmail, Gmail and Yahoo so if you want your email to reach those inboxes, you need to play along.</p>
<h2>QmailToaster</h2>
<p>Step one, set up a <a href="http://www.qmailtoaster.com">QmailToaster</a>.  Our current server is (older) Qmail + Vpopmail + Courier based and it has worked well so we stuck with what we know.  Not to mention, Jake Vickers and the QmailToaster team have removed all of the pain of setting it up so now you just speed along to the part where it works well.  Other than getting the needed dependencies on my CentOS/RHEL box, the installation was a piece of cake using the <a href="http://qtp.qmailtoaster.com/trac/wiki/qtp-newmodel">qtp-newmodel approach</a>.</p>
<ul>
<li><a href="http://wiki.qmailtoaster.com/index.php/CentOS_5_QmailToaster_Install#Add_a_domain">http://wiki.qmailtoaster.com/index.php/CentOS_5_QmailToaster_Install</a> &#8211; the CentOS/RHEL 5 Toaster install gives the quick and dirty of adding DomainKeys support</li>
<li><a href="http://wiki.qmailtoaster.com/index.php/Domainkeys">http://wiki.qmailtoaster.com/index.php/Domainkeys</a> &#8211; detailed directions for DomainKeys support</li>
<li><a href="http://wiki.qmailtoaster.com/index.php/How_to_Setup_DKIM_with_Qmail_Toaster">http://wiki.qmailtoaster.com/index.php/How_to_Setup_DKIM_with_Qmail_Toaster</a> &#8211; Add DKIM support with a new qmail-queue</li>
</ul>
<p>After you install the DKIM package from above on RHEL/CentOS 5, you <em>would</em> see this error in your qmail logs:</p>
<p><code>@400000004d7d3bc00da74aec delivery 21: success: ould_not_find_ParserDetails.ini_in_/usr/lib/perl5/vendor_perl/5.8.8/XML/SAX/rUser_and_password_not_set,_continuing_without_authentication./&lt;check-auth@verifier.port25.com&gt;_96.244.219.19_accepted_message./Remote_host_said:_250_2.6.0_message_received/</code></p>
<p>Basically, something is borked in the CPAN-installed SAX package.  You can fix it by pre-emptively running (thanks to <a href="http://centosfiles.blogspot.com/2009/09/could-not-find-parserdetailsini-in.html">centosfiles</a> for the fix):</p>
<pre><code>perl -MXML::SAX -e "XML::SAX-&gt;add_parser(q(XML::SAX::PurePerl))-&gt;save_parsers()"</code></pre>
<p>At this point you have a mail server <em>capable</em> of handling SPF, Sender ID, DomainKeys and DKIM.  Now you need to enable it in your configuration and your DNS.</p>
<h2>SPF/Sender ID</h2>
<p>Unlike DomainKeys and DKIM which require public/private keys and some computational effort when delivering email, SPF and Sender ID are exclusively a DNS configuration option.</p>
<ul>
<li><a href="http://wiki.qmailtoaster.com/index.php/SPF">http://wiki.qmailtoaster.com/index.php/SPF</a> &#8211; there technically isn&#8217;t anything to set up with the QmailToaster since your outbound configuration is all DNS.  However, you can configure how to handle incoming email that doesn&#8217;t pass using /var/qmail/control/spfbehavior.</li>
<li><a href="http://www.saout.de/misc/spf/">Qmail SPF</a> &#8211; The underlying implementation of SPF for qmail</li>
<li><a href="http://old.openspf.org/wizard.html?mydomain=example.com&#038;submit=Go!">OpenSPF.org&#8217;s Record Wizard</a> &#8211; generate an SPF record for your domain to be placed in a DNS TXT record</li>
</ul>
<p>Once generated, take the TXT record and put it into your DNS files.  If you&#8217;re using <a href="http://cr.yp.to/djbdns.html">djbdns</a>, a simple record with one mail server would look something like:</p>
<pre><code>'sample.com:v=spf1 ip4:your.ip.add.ress ~all:3600</code></pre>
<p>The ~all says to softfail messages that don&#8217;t verify.  If you are sure you have listed all of your possible outbound MTAs, then you can set it to -all which will tell remote servers to kill emails that don&#8217;t pass.</p>
<h2>DomainKeys/DKIM</h2>
<p>Once installed, you enable incoming verification and outgoing signing through the tcp.smtp file stored in /etc/tcprules.d:</p>
<ul>
<li><a href="http://wiki.qmailtoaster.com/index.php/Domainkeys#Outgoing">http://wiki.qmailtoaster.com/index.php/Domainkeys#Outgoing</a> &#8211; using DKSIGN for outgoing messages and DKQUEUE/DKVERIFY for incoming messages.  Has a flag-by-flag breakdown of how to configure DKVERIFY for how to respond to incoming mail that passes or fails verification.</li>
<li><a href="http://wiki.qmailtoaster.com/index.php/Tcp.smtp">http://wiki.qmailtoaster.com/index.php/Tcp.smtp</a> &#8211; a complete breakdown of the tcp.smtp file that includes DKSIGN, DKVERIFY and DKQUEUE breakdown</li>
<li><a href="http://www.zytrax.com/books/dns/ch9/dkim.html">HOWTO define DKIM/ADSP RRs</a> &#8211; from the &#8220;Pro DNS and BIND&#8221; book, this page does a phenomenal job of explaining the components of the DomainKeys/DKIM records with examples.  Also explains selectors clearly.</li>
</ul>
<p>For DKVERIFY, the default is &#8220;DEGIJKfh&#8221;.  If you want to permanently reject incoming mail that has a DomainKey signature but fails to verify, add a &#8220;B&#8221; to the list: &#8220;BDEGIJKfh&#8221;.  </p>
<h3>Outbound</h3>
<p>To sign an outbound message for DomainKeys/DKIM, you need to generate a public/private key pair.  Part of it you keep secret and sign your outgoing messages and the other half you publish in your DNS so other mail servers can verify it&#8217;s authentic.  Here&#8217;s what the docs say to do:</p>
<pre><code># cd /var/qmail/control/domainkeys
# mkdir yourdomain.com
# cd yourdomain.com
# dknewkey private &gt; public.txt
# chmod 440 private
# cd ..
# chown -R root:vchkpw yourdomain.com</code></pre>
<p>The word &#8220;private&#8221; above is going to be our <strong>selector</strong>.  It&#8217;s 100% arbitrary but must be used consistently.  QmailToaster defaults to the word &#8220;private&#8221;.  In your DNS, you need a TXT record that looks something like:</p>
<p><code>private._domainkey.yourdomain.com:k=rsa; p=MEwwDQYJKoZIhvcNAQEBBQ . . .</code></p>
<p>The rest of the record comes out of the file we just created with dknewkey in /var/qmail/control/domainkeys/yourdomain.com/public.txt.   In my last Qmail install, I used &#8220;default&#8221; for my selector, so my DNS entries look like:</p>
<p><code>default._domainkey.yourdomain.com:k=rsa; p=MEwwDQYJKoZIhvcNAQEBBQ . . .</code></p>
<p>This selector, be it &#8220;private&#8221;, &#8220;default&#8221; or something else, MUST match what you use to generate your public/private key using dknewkey and it must also match what you use in your /etc/tcprules.d/tcp.smtp rules where you specify when to sign outgoing messages:</p>
<pre><code># example record using QmailToaster defaults
127.:allow,RELAYCLIENT="",DKSIGN="/var/qmail/control/domainkeys/%/private"

# since I used 'default' as my selector, this is what my file looks like:
127.:allow,RELAYCLIENT="",DKSIGN="/var/qmail/control/domainkeys/%/default"</code></pre>
<h4>Crypto Warning</h4>
<p>dknewkey creates a (relatively) short 384-bit public/private keypair.  There are <a href="http://mipassoc.org/pipermail/dkim-ops/2010-June/thread.html#202">people who don&#8217;t think that&#8217;s good enough</a> and they&#8217;re probably right.  You can edit /usr/bin/dknewkey to change it to something more secure like 512 or (better yet) 1024 bits.</p>
<p>A quick recap with how this selector is used throughout your Qmail and DNS configuration:</p>
<ol>
<li>Generate the public/private key: dknewkey my-selector-name > public.txt; this leaves behind a file like /var/qmail/control/domainkeys/yourdomain.com/my-selector-name.</li>
<li>Create the DNS TXT record: my-selector-name._domainkey.yourdomain.com:k=rsa; p=MEwwDQYJKoZIhvcNAQEBBQ&#8230; (using the contents of the public.txt file dknewkey creates)</li>
<li>In tcp.smtp, use a DKSIGN environment variable: DKSIGN=&#8221;/var/qmail/control/domainkeys/%/my-selector-name&#8221;</li>
</ol>
<h2>Testing</h2>
<p>Once you have it set up <strong>and</strong> your DNS has propagated, there are a number of online services and email reflectors that will verify your configuration and report back to you:</p>
<h3>Web Tools</h3>
<ul>
<li><a href="http://domainkeys.sourceforge.net/policycheck.html">SourceForge DomainKeys Policy Checker</a></li>
<li><a href="http://www.kitterman.com/spf/validate.html">Scott Kitterman&#8217;s SPF record checker</a> &#8211; test your SPF record from the web</li>
<li><a href="http://www.dnswatch.info/dkim/create-dns-record">DKIM DNS Record Wizard</a> &#8211; based on  RFC 4871, helps construct the TXT record for your DNS for DKIM signing</li>
<li><a href="http://www.sendmail.org/dkim/tools">SendMail ADSP wizard and DKIM verifier</a> &#8211; helps build an (optional) ADSP TXT record and can check your DKIM DNS entries</li>
</ul>
<h3>Email Reflectors</h3>
<p>Unlike the above services which try to see if things look OK, these are email addresses you can send a test message to that will actually tell you how your email performed:</p>
<ul>
<li><a href="mailt:check-auth@verifier.port25.com">check-auth@verifier.port25.com</a> &#8211; the port25 reflector sends you an email report with a summary and breakdown by type.  This is the best one in my opinion.</li>
<li><a href="mailto:spf-test@openspf.org">spf-test@openspf.org</a> &#8211; this message will be rejected but the rejection will say what happened to the SPF test.  You must tail the logs (like /var/log/qmail/smtp/current) to see the results.</li>
<li><a href="mailto:autorespond+dkim@dk.elandsys.com">autorespond+dkim@dk.elandsys.com</a> &#8211; Eland Systems offers a DKIM reflector along with <a href="http://www.elandsys.com/resources/sendmail/dkim.html">some notes</a></li>
<li><a href="http://www.myiptest.com/staticpages/index.php/DomainKeys-DKIM-SPF-Validator-test">MyIpTest.com Tester</a> &#8211; tests DK, DKIM and SPF.  Web page gives you a random email address to send to and then you can load your results after sending a test message.</li>
<li><a href="http://www.brandonchecketts.com/emailtest.php">http://www.brandonchecketts.com/emailtest.php</a> &#8211; similar to above, send an email to a random address provided on the web page and then you can check results.</li>
</ul>
<p>Port25&#8217;s reflector report should look like this when everything is working:</p>
<pre><code>Summary of Results
==========================================================
SPF check: pass
DomainKeys check: pass
DKIM check: pass
Sender-ID check: pass
SpamAssassin check: ham</code></pre>
<p>Microsoft will let you &#8220;register&#8221; your Sender ID settings with them.  Not sure how important this is, but it can&#8217;t hurt to let them know at <a href="https://support.msn.com/eform.aspx?productKey=senderid&#038;page=support_senderid_options_form_byemail">https://support.msn.com/eform.aspx?productKey=senderid&#038;page=support_senderid_options_form_byemail</a>.</p>
<h3>Email Services</h3>
<p>Better than a reflector is to see how a real mail service will treat your message.  Once you think you&#8217;re configured correctly, try sending an email to Gmail and Yahoo.  Then you can view the headers for each to see how your SPF and DK records were interpreted.</p>
<p><strong>Gmail</strong>:<br />
<img src="https://www.ghidinelli.com/wp-content/uploads/2011/03/gmail-test.png" alt="Verify SPF, DomainKeys and DKIM headers on Gmail" title="Verify SPF, DomainKeys and DKIM headers on Gmail" width="624" height="243" class="alignnone" /></p>
<p><strong>Yahoo</strong>:<br />
<img src="https://www.ghidinelli.com/wp-content/uploads/2011/03/yahoo-test.png" alt="View SPF, DomainKeys and DKIM headers on Yahoo mail" title="View SPF, DomainKeys and DKIM headers on Yahoo mail" width="486" height="168" class="alignnone" /></p>
<h2>Final Thoughts</h2>
<p>Putting it all together, here&#8217;s how my setup looks (using the selector &#8216;default&#8217;):</p>
<h3>Public/private key pairs on file system</h3>
<pre><code>[root@mail domainkeys]# ls -al /var/qmail/control/domainkeys/sample.com/
total 32
drwxr-xr-x 2 qmailq root  4096 Mar 13 13:46 .
drwxr-xr-x 7 root   qmail 4096 Mar 13 13:46 ..
-r--r----- 1 qmailq root   396 Mar 13 13:46 default
-rw-r--r-- 1 qmailq root   142 Mar 13 13:46 public.txt</code></pre>
<h3>DKIM signconf.xml</h3>
<p>On the file system in /var/qmail/control/dkim/signconf.xml:</p>
<pre><code>&lt;dkimsign&gt;
  &lt;global algorithm="rsa-sha1" domain="/var/qmail/control/me" keyfile="/var/qmail/control/dkim/global.key" method="simple" selector="dkim1"&gt;
    &lt;types id="dkim" /&gt;
  &lt;/global&gt;
&lt;/dkimsign&gt;</code></pre>
<p>You could override the use of /var/qmail/control/me or change the selector from &#8216;dkim1&#8242; if needed.</p>
<p><strong>Alternative note:</strong> It is also possible to sign your DomainKeys using the DKIM package.  You can change signconf.xml to have a per-domain record with DK and then abandon DKSIGN altogether (this is the route I&#8217;ve gone):</p>
<pre><code>&lt;sample.com domain="sample.com" selector="default"&gt;
  &lt;types id="dkim" /&gt;
  &lt;types id="domainkey" method="nofws" /&gt;
&lt;/sample.com&gt;</code></pre>
<h3>tcp.smtp</h3>
<pre><code># localhost relaying
127.:allow,RELAYCLIENT="",QMAILQUEUE="/var/qmail/bin/simscan",DKVERIFY="DEGIJKfh",DKQUEUE="/var/qmail/bin/qmail-queue.orig",DKSIGN="/var/qmail/control/domainkeys/%/default"
# external web box
69.36.226.12:allow,RELAYCLIENT="",DKSIGN="/var/qmail/control/domainkeys/%/default"
# everyone else that connects gets the full cavity check
:allow,BADMIMETYPE="",BADLOADERTYPE="M",CHKUSER_RCPTLIMIT="50",CHKUSER_WRONGRCPTLIMIT="3",QMAILQUEUE="/var/qmail/bin/simscan",DKVERIFY="DEGIJKfh",DKQUEUE="/var/qmail/bin/qmail-queue.orig",DKSIGN="/var/qmail/control/domainkeys/%/default"</code></pre>
<h3>DNS TXT Records</h3>
<p>Using djbdns: </p>
<pre><code>'sample.com:v=spf1 ip4\07269.36.226.12 include\072emailcenterpro.com ~all:3600
'_domainkey.sample.com.:o=-;:3600
'default._domainkey.sample.com.:k=rsa; p=MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAPBdKl9mx3KIjLwGfq83LNzUN4aDWc4t3PVTnc0d+duI9HVD+UG+i1suifV6obDzo4ugHji6EH+zei39Cch9vTXcpVWkaFCEmVu0AXjY/98WIjYb5Hh5+SYQFyQkz0Mq0wIDAQAB;:3600
'dkim1._domainkey.mail.sample.com.:v=DKIM1; k=rsa; p=MEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxAK+vhWHoPv+3DhM1u3MaHk7AayBa+CdNnjPHhg3/3Nv7hEIYUbOfKSUqNxDtjJkgcQIDAQAB;:3600
'_adsp._domainkey.mail.sample.com:dkim=all:3600
'_adsp._domainkey.sample.com:dkim=all:3600</code></pre>
<p>First line is my SPF/Sender ID record.  It also uses an <em>include</em> to allow a third party (in this case, <a href="http://www.emailcenterpro.com">EmailCenterPro</a>) to send mail on our behalf.</p>
<p>The second line says that we sign all outgoing messages with DomainKeys/DKIM (o=-).</p>
<p>Third line is for DomainKeys using our selector &#8216;default&#8217; (which correspondingly shows up in tcp.smtp in DKSIGN and on the filesystem as /var/qmail/control/domainkeys/sample.com/<em>default</em>).</p>
<p>The fourth line is the DKIM record which uses the global.key and public.txt stored in /var/qmail/control/dkim.  Why is it dkim1._domainkey?  Because that&#8217;s the arbitrary selector specified in the signconf.xml file as listed above.  Again, totally arbitrary, could be &#8216;private&#8217; or &#8216;default&#8217; or something else, but best to have it different from your DomainKeys.  You might also notice that it is mail.sample.com instead of sample.com?  By default it must match /var/qmail/control/me file because that&#8217;s how the message will be signed by the QmailToaster DKIM package.</p>
<p>The fifth and sixth line are ADSP records that say we sign all outbound messages with DKIM.  Some hosts appear to be checking for it without the mail subdomain so I&#8217;m currently running both.  I don&#8217;t think it should be strictly required but at this time seems to cover the bases.</p>
<p>The 3600 on every line is the TTL, meaning these records expire after 1 hour.</p>
<h2>Quarantining Spam in IMAP Folder</h2>
<p>Before upgrading, we used <a href="http://dspam.nuclearelephant.com">DSPAM</a> as our spam filter of choice.  In a word, it&#8217;s awesome.  It quarantined mail so effectively that I eventually stopped checking the quarantine until it became so large I could no longer view or delete it from the web interface.  The secret sauce in my setup, which involves <a href="http://www.mozillamessaging.com">Mozilla Thunderbird</a> was to use Thunderbird&#8217;s built-in &#8220;Junk&#8221; folder as a feedback loop for DSPAM.  For some reason, Thunderbird is really good at catching certain kinds of spam that DSPAM was not and, if a spam did get through, I can select it and press &#8220;J&#8221; which trains Thunderbird and moves the message to my Junk folder.  The server processed those Junk folders nightly, feeding them to DSPAM to further increase its accuracy.</p>
<p>I like not downloading all of the assumed junk mail to my phone or, worse yet, on a slow net connection while traveling somewhere around the world.  Unfortunately, QmailToaster&#8217;s SpamAssassin approach is to flag but leave it in your inbox.  No bueno.  Luckily we can use some of the software already installed and a very short script to replicate the previous behavior.</p>
<h3>Create generic mailfilter</h3>
<p>If you accept users will use a &#8220;Junk&#8221; folder (or &#8220;Spam&#8221; or whatever you want to call it), then you can create a single maildrop mailfilter script in ~vpopmail/etc/mailfilter-to-spam:</p>
<pre><code>SHELL="/bin/bash"
import EXT
import HOST

VUSER=`echo ${EXT%-*}`
export VUSER
USERHOME=`/mail/bin/vuserinfo -d $VUSER@$HOST`
export USERHOME

logfile "/var/log/maildrop/mailfilter.log"

# Test for the existance of the Junk directory.  Create it if it doesn't exist
#VERBOSE=9
#log "testing for $VUSER@$HOST in $USERHOME"

if ( /^X-Spam-Status: Yes/ )
{
        `test -d $USERHOME/Maildir/.Junk`

        if ( $RETURNCODE == 1 )
        {
            `/usr/bin/maildirmake -f Junk $USERHOME/Maildir`
            `echo INBOX.Junk &gt;&gt; $USERHOME/Maildir/courierimapsubscribed`
        }

        to "$USERHOME/Maildir/.Junk"
}
else
{
        to "$USERHOME/Maildir/"
}</code></pre>
<p>Now create a ~vpopmail/domains/sample.com/username/.qmail file for those users who want their spam quarantined in a &#8220;Junk&#8221; folder rather than just tagged:</p>
<p><code>|preline /usr/bin/maildrop ~vpopmail/etc/mailfilter-to-spam</code></p>
<p>Done!  All messages that meet your SpamAssassin minimum score (default of 5.0) will be quarantined in the &#8220;Junk&#8221; folder for review from SquirrelMail or your IMAP client.  You can process these folders using a script like the following (<em>warning, not tested in production yet!</em>):</p>
<pre><code>#!/bin/bash
cd ~vpopmail/domains

# find all Junk folders
for ii in `find . -type d -name '.Junk'`; do

  # find all mail 5 days or older
  for jj in `find $ii/cur/ -type f -mtime +4`; do

    # learn from it and delete it
    echo "processing $jj"
    /usr/bin/sa-learn --spam --no-sync $jj
    rm -f $jj

  done;

done;

# now synchronize the overall SA database
/usr/bin/sa-learn --sync</code></pre>
<p>The argument &#8220;-mtime +4&#8243; says look for files that are 5 days or older.  You could adjust that to +1 for 48 hours or &#8220;-mmin +60&#8243; for 60 minutes or older depending on your policies.  Schedule this to run as a cronjob nightly and you&#8217;ll be provided an ongoing set of spam to learn from.</p>
<p>Hope these links and notes help someone else in the future!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/05/04/march-qmail-server-madness/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Push the last X backups to Amazon S3</title>
		<link>http://www.ghidinelli.com/2011/02/15/push-last-x-backups-amazon-s3</link>
		<comments>http://www.ghidinelli.com/2011/02/15/push-last-x-backups-amazon-s3#comments</comments>
		<pubDate>Wed, 16 Feb 2011 00:54:19 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1247</guid>
		<description><![CDATA[Store only a subset of files on Amazon S3 using s3cmd and a little date logic.  Lets us put the last 5 database backups (or something similar) in a safe place without saving every dump forever and costing us $$$.]]></description>
			<content:encoded><![CDATA[<p>Not going to get fancy with this one: it&#8217;s a bash shell script that will take the last X backups and push them to Amazon S3 for disaster recovery.   I wrote a couple of versions until I settled on this simple one.  It requires you to have <a href="http://s3tools.org/s3tools">s3cmd</a>, which if you&#8217;re using Linux, is pretty much the only way you could interface S3 and stay sane.  Here are docs on how to <a href="">install it with yum</a> if you are on Redhat/CentOS.</p>
<p>Now, to the script:</p>
<pre><code>#!/bin/bash

# init vars
BACKUP_ROOT=/dblogs/backups
S3CMD=/usr/bin/s3cmd
S3DIR=s3://your-bucket-name/your-folder-name

# take the last X backups and make sure they are on S3 (but not older ones)
BACKUP_COUNT=5
BACKUP_FILELIST=/tmp/.pgbackup_s3cmd_filelist

# first list out the files we want to sync up
ls -1 $BACKUP_ROOT | tail -$BACKUP_COUNT &gt; $BACKUP_FILELIST

# now sync them; requires trailing slash to sync directories
$S3CMD sync --progress --delete-removed --acl-private --exclude '*' --include-from $BACKUP_FILELIST $BACKUP_ROOT $S3DIR/

# clean up
rm -f $BACKUP_FILELIST
</code></pre>
<p>Setup s3cmd after installing it by running <tt>s3cmd --configure</tt> with your Amazon credentials handy.  I also use s3fox, a Firefox add-on, as another way of quickly accessing S3 with a GUI.</p>
<p>This script maintains only the last 5 backups on S3 and it deletes what would be the 6th backup each night via cron.  You could adjust the number to keep with the BACKUP_COUNT parameter.  I&#8217;m personally using this to backup a <a href="http://www.postgresql.org">PostgreSQL server</a> but you can adjust it to back up any type of directory with files in it.</p>
<p><strong>Update 2/17</strong> &#8211; realized the default behavior is not to delete files on the remote host that are not included locally.  I updated the above to include the &#8211;delete-removed argument and now it deletes the oldest file as expected.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/02/15/push-last-x-backups-amazon-s3/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ColdFusion hangs or slow on startup due to MessageBrokerServlet</title>
		<link>http://www.ghidinelli.com/2011/01/11/cold-fusion-slow-start-messagebrokerservlet</link>
		<comments>http://www.ghidinelli.com/2011/01/11/cold-fusion-slow-start-messagebrokerservlet#comments</comments>
		<pubDate>Tue, 11 Jan 2011 22:20:13 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jvm]]></category>
		<category><![CDATA[SSL]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1208</guid>
		<description><![CDATA[I&#8217;m setting up a new server as recent posts and tweets have suggested.  Just about everything was working with one exception: horribly slow startup times of 2-4 minutes on a dual quad-core Xeon machine with 16GB of RAM.  Tailing the cfusion-event.log during startup, ColdFusion would hang either when starting the SQL manager pool [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m setting up a new server as recent posts and <a href="http://twitter.com/ghidinelli">tweets</a> have suggested.  Just about everything was working with one exception: horribly slow startup times of 2-4 minutes on a dual quad-core Xeon machine with 16GB of RAM.  Tailing the cfusion-event.log during startup, ColdFusion would hang either when starting the SQL manager pool or MessageBrokerServlet.  It looked something like this (note the timestamps):</p>
<pre><code>01/10 13:03:28 user MessageBrokerServlet: init
**** 90 seconds of "working" ****
01/10 13:05:13 user CFFormGateway: init</code></pre>
<pre><code>01/10 12:32:58 Information [scheduler-12] - Starting debugging...
01/10 12:32:58 Information [scheduler-12] - Starting sql...
****  almost 2 minutes here ****
01/10 12:34:46 Information [scheduler-12] - Pool Manager Started
01/10 12:34:46 Information [scheduler-12] - Starting mail... </code></pre>
<p>This simply would not do.  Not only was it slow, it was unpredictable, sometimes taking 90-115 seconds and other times as long as 224 seconds.  We generally restart our CF servers when we do deployments and the sluggish startup meant more queued requests and timeouts as we come back from an update.  No bueno.</p>
<p>I turned to my friends on the CFGURU list hoping someone had the answer.  The always helpful <a href="http://www.pengoworks.com">Dan Switzer</a> pointed me to a <a href="http://www.mail-archive.com/cfaussie@googlegroups.com/msg14524.html">cfaussie thread</a> which was Ubuntu specific but had my same behavior:</p>
<blockquote><p>With the startup you can see that cranking up the Message Broker Servlet (ie Livecycle/Blaze) is taking almost a minute, which I find is usually due to some network ports used by LCDS still being open from the last time ColdFusion was run.</p></blockquote>
<p>The good news was that they were experiencing the exact same problem I was.  The bad news is that I have nothing to do with Blaze or LiveCycle so I wasn&#8217;t sure this was related.   We are also running RHEL/CentOS but the Ubuntu connection proved helpful later in my research.</p>
<p>Anytime I see hanging processes in ColdFusion, I generate a <a href="https://www.ghidinelli.com/2009/07/16/finding-memory-leaks-coldfusion-jvm">complete JVM stack trace</a>.  Unfortunately, I&#8217;m quite bad at reading them.  I identified a BLOCKED process but <a href="http://www.darylb.net/">Daryl Banttari</a> took a look and set me straight:</p>
<pre><code>This is the thread that's your root problem:

"scheduler-10" prio=10 tid=0x00002aaaac28c800 nid=0x5edd runnable [0x00000000441de000]
   java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:199)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
- locked &lt;0x00002b4fc75a5018&gt; (a java.io.BufferedInputStream)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
- locked &lt;0x00002b4fc75a4ce0&gt; (a java.io.BufferedInputStream)
at sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedByte(SeedGenerator.java:453)
at sun.security.provider.SeedGenerator.getSeedBytes(SeedGenerator.java:123)
at sun.security.provider.SeedGenerator.generateSeed(SeedGenerator.java:118)
at sun.security.provider.SecureRandom.engineGenerateSeed(SecureRandom.java:114)
at java.security.SecureRandom.generateSeed(SecureRandom.java:495)
at com.rsa.jsafe.provider.c7.engineGenerateSeed(Unknown Source)
at java.security.SecureRandom.generateSeed(SecureRandom.java:495)
at java.security.SecureRandom.getSeed(SecureRandom.java:482)
at com.rsa.jsafe.crypto.au.g(Unknown Source)
at com.rsa.jsafe.crypto.au.a(Unknown Source)
at com.rsa.jsafe.provider.JSA_FIPS186PRNGXChangeNoticeGeneral.engineNextBytes(Unknown Source)
at java.security.SecureRandom.nextBytes(SecureRandom.java:433)
- locked &lt;0x00002b4fdca32370&gt; (a java.security.SecureRandom)
at java.security.SecureRandom.next(SecureRandom.java:455)
at java.util.Random.nextInt(Random.java:253)
at flex.messaging.util.UUIDUtils.createUUID(UUIDUtils.java:110)
at flex.messaging.util.UUIDUtils.createUUID(UUIDUtils.java:97)
at flex.messaging.log.AbstractTarget.&lt;init&gt;(AbstractTarget.java:52)
at flex.messaging.log.LineFormattedTarget.&lt;init&gt;(LineFormattedTarget.java:79)
at flex.messaging.log.ConsoleTarget.&lt;init&gt;(ConsoleTarget.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at flex.messaging.config.MessagingConfiguration.createLogger(MessagingConfiguration.java:298)
at flex.messaging.MessageBrokerServlet.init(MessageBrokerServlet.java:114)
at coldfusion.flex.ColdFusionMessageBrokerServlet.init(ColdFusionMessageBrokerServlet.java:24)
at coldfusion.bootstrap.ClassloaderHelper.initServletClass(ClassloaderHelper.java:94)
at coldfusion.bootstrap.BootstrapServlet.init(BootstrapServlet.java:59)
at jrun.servlet.WebApplicationService.loadServlet(WebApplicationService.java:1213)
- locked &lt;0x00002b4fdbc4e5c8&gt; (a java.lang.Object)
at jrun.servlet.WebApplicationService.preloadServlets(WebApplicationService.java:793)
at jrun.servlet.WebApplicationService.postStart(WebApplicationService.java:295)
at jrun.ea.EnterpriseApplication.start(EnterpriseApplication.java:203)
at jrun.deployment.DeployerService.initModules(DeployerService.java:708)
at jrun.deployment.DeployerService.createWatchedDeployment(DeployerService.java:243)
at jrun.deployment.DeployerService.deploy(DeployerService.java:428)
- locked &lt;0x00002b4ed0c3f140&gt; (a java.util.HashMap)
at jrun.deployment.DeployerService.checkWatchedDirectories(DeployerService.java:179)
at jrun.deployment.DeployerService.run(DeployerService.java:889)
- locked &lt;0x00002b4ed0c3f140&gt; (a java.util.HashMap)
at jrunx.scheduler.SchedulerService.invokeRunnable(SchedulerService.java:230)
at jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)
at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
at jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)
at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

Looks like it's stuck trying to read from /dev/random while trying to create a UUID?</code></pre>
<p>The key was that Java was waiting on input to the secure number generator code.  Thanks to Daryl&#8217;s stack trace reading kung fu, I had something to Google.  On Linux, /dev/random is a &#8220;blocking&#8221; number generator meaning if it doesn&#8217;t have enough random data to provide, it will simply wait until it does.   Here&#8217;s some <a href="http://en.wikipedia.org/wiki//dev/random">background on /dev/random</a>.  Keyboard and mouse input as well as disk activity can generate the randomness, or entropy, needed but perhaps not fast enough for particular applications.   A lack of random data would force the JVM and ColdFusion to wait, for eternity if necessary, until chaos caught up with /etc/init.d/coldfusion8multi. </p>
<p>It turns out a lot of applications experience this problem: any that use random number generators.  I found frustrated users of Apache, SSL, Livecycle/Blaze DS and a myriad of other applications as my search terms refined.</p>
<h2>Verify the culprit</h2>
<p>Before you try the changes below, verify that this is indeed your problem.  It&#8217;s easy!  First, start by checking how much entropy you have:</p>
<pre><code>cat /proc/sys/kernel/random/entropy_avail</code></pre>
<p>This kernel facility in /proc has been available since 2.3.16 so it should work on any reasonably recent Linux.  A full pool should be 4096 (check your poolsize config in /proc/sys/kernel/random/poolsize).  On my normal servers, I had values around 3500 but this particular server was 150.  Stop ColdFusion (or Apache or LCDS or whatever app is giving you fits) and run the following command before starting CF again:</p>
<pre><code>watch –interval 0.1 cat /proc/sys/kernel/random/entropy_avail</code></pre>
<p>Now start ColdFusion and what you may see is as it gets to MessageBrokerServlet, the available entropy drops to near-zero, climbs back up to around 50-70, then drops to zero and repeats like a stairmaster until it completes and CF can resume at a normal pace.</p>
<h2>Make random data non-randomly appear</h2>
<p>Now we know roughly what the problem is: there ain&#8217;t enough random data.  How do we make it so ColdFusion and JRun can start up faster?  We need to ensure that there is a constantly available source of entropy so the JVM can seed its secure number generator quickly.</p>
<p>Armed with new search terms for Java&#8217;s SecureRandom, I came across a StackOverflow thread which offered a JVM argument to <a href="http://stackoverflow.com/questions/137212/how-to-solve-performance-problem-with-java-securerandom">switch from the blocking /dev/random</a> to the less-secure-but-non-blocking /dev/urandom:</p>
<pre><code>-Djava.security.egd=file:/dev/./urandom</code></pre>
<p>I appended that onto the end of java.args in /opt/jrun4/bin/jvm.config and the server started up in 12 seconds!  I felt a little bit of hair on my head grow back at that moment.</p>
<h2>Solving for Production</h2>
<p>At this stage I&#8217;ve identified the culprit but I had uneasy feelings about using /dev/urandom in production where evil doers are constantly trying to do evil things to our server, application and users.   We don&#8217;t want an insecure random number generator.</p>
<p>Following the Ubuntu connection from Stack Overflow, this post on <a href="http://whatan00b.com/slow-apache-starts-on-ubuntu">slow Apache starts</a> described the same symptoms and the use of rngd (a random number generator daemon) to populate the entropy pool.   <a href="http://linux.die.net/man/8/rngd">Rngd</a> is included in rng-tools or rng-utils depending on your distro.  On RHEL 5.5, it was already installed under /sbin.</p>
<p>The trick is to feed rngd data from the kinda-insecure /dev/urandom and let it figure out what is secure enough to pass to /dev/random with a FIPS-140 test.  You can run rngd two ways.  If you want to populate /dev/random once, right now, run it in the foreground:</p>
<pre><code>/sbin/rngd -r /dev/urandom -o /dev/random -f -t 5</code></pre>
<p>Ctrl-C out of it after 15 seconds and check entropy_avail &#8211; you should find it&#8217;s up around 4000.  Very nice!  Now, how about running it as a daemon so you don&#8217;t have to ever worry if ColdFusion has enough to start quickly?   I added this to my /etc/rc3.d/S99local file so it will automatically start every time the server is started:</p>
<pre><code>
/sbin/rngd -r /dev/urandom -o /dev/random -t 5
 </code></pre>
<p>Fire that up, restart ColdFusion, crack a beer and ride off into the sunset.  Another ridiculous unexpected behavior solved by yours truly.</p>
<p>Interesting side note: Once upon a time, Intel included hardware RNGs in their chip sets that would be exposed as /dev/hw_random.  If you had one of those, you could use it as the parameter for -r.  Unfortunately that practice died out in the 800 series chips and are no longer available.  You can still buy external, cryptographically secure hardware RNGs that can be used for rngd but the above seems to be &#8220;good enough&#8221; according to the tubes.  </p>
<p>If you want to go nuts, you can use a <a href="https://bmearns.net/wwk/view//dev/random">radio tuned to static as an audio input</a> to provide the source data.  Unless your a crypto-nerd, <a href="http://www.groupsrv.com/linux/about157480.html">this thread about RNG sources</a> will make your eyes bleed.</p>
<h2>Resources</h2>
<p><a href="http://egd.sourceforge.net/">EGD</a> &#8211; entropy gathering daemon is a userspace substitute for /dev/random, written in perl.  It could be used with the java.security.egd parameter above in lieu of /dev/random.</p>
<p><a href="http://whatan00b.com/slow-apache-starts-on-ubuntu">http://whatan00b.com/slow-apache-starts-on-ubuntu</a> Llinked to from the StackOverflow thread on the Java SecureRandom slowness, explained entropy and how to monitor it.</p>
<p><a href="http://blog.sbf5.com/?p=50">http://blog.sbf5.com/?p=50</a>  Pointed me in the right direction for using rngd to generate entropy for /dev/random</p>
<p><a href="http://www.vglug.info/how-increase-entropy-pool-2-6-kernel-rhel-fedora-system-without-keyboard-mouse">Increasing entropy pool on RHEL/Fedora without keyboard or mouse</a>  Another source to monitoring entropy and using rngd that turned up in Google as I got more specific with my searches.</p>
<p><a href="http://en.wikipedia.org/wiki/Hardware_random_number_generator">Wikipedia on Hardware RNGs</a> An overview of ways to source random data</p>
<p>Did you know?  /proc/sys/kernel/random/uuid contains a <a href="http://lwn.net/Articles/259121/">fresh Version 4 UUID</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/01/11/cold-fusion-slow-start-messagebrokerservlet/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Getting very large files from flaky hosts using wget</title>
		<link>http://www.ghidinelli.com/2010/11/26/getting-very-large-files-from-flaky-hosts-using-wget</link>
		<comments>http://www.ghidinelli.com/2010/11/26/getting-very-large-files-from-flaky-hosts-using-wget#comments</comments>
		<pubDate>Fri, 26 Nov 2010 19:26:56 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Racing]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1186</guid>
		<description><![CDATA[Have a giant file you need to download from a crappy web server?  Wget can put together the pieces on your behalf.]]></description>
			<content:encoded><![CDATA[<p>Two years ago I raced the gruelling <a href="http://www.nasa25hour.com">25 Hours of Thunderhill</a> organized by NASA.  It&#8217;s the longest road race in North America, if not the world, and pits sixty-something teams and hundreds of crew members against each other for gargantuan trophies in one of five classes.  </p>
<p>I drove for Team Bimmerworld in an early 1990s BMW M3 and was in the car at night when the race was temporarily stopped due to thick valley fog.  The changing visibility from lap to lap was challenging but fun and all of the drama was captured on a ChaseCam.  Unfortunately the memory card disappeared with BMW E30 rally-star <a href="http://www.caswellmotorsport.com">Bill Caswell</a> and we never got more than halfway in exchanging the data.  The main problem?  Bill is a non-stop motorsport animal always on the go and the file was 13GB.   </p>
<p>At one point Bill managed to get the file uploaded to getdropbox.com but even installing their desktop client, I was unable to make it more than about 500MB at 5k/sec before timeouts or other network shenanigans would restart the process.  Frustrating!</p>
<p>That was twelve months ago.  This week I was cleaning out some old emails and came across the link to the file and, for fun, tried clicking it.  Hey, it&#8217;s still there!  And still 13GB.  </p>
<p>On a whim I logged in to my web server to see what I could do with the venerable command-line utility <a href="http://www.gnu.org/software/wget/">wget</a>.  Turns out wget has a few tricks up its sleeves and some 60 hours later I&#8217;ve managed to download 5GB of the video.   Here&#8217;s the magic in the command line:</p>
<pre><code>wget --continue --progress=dot:mega --tries=0 &lt;URL&gt;</code></pre>
<p>I was unaware of the continue option before which tells wget to try and restart any downloads where they left off.  The progress option indicates 3MB per line of dots rather than 384k; appropriate for a file of this size.  And finally, tries=0 means keep trying forever regardless of how many times the connection fails.  Here&#8217;s what a failure looks like:</p>
<pre><code>2010-11-26 10:25:48 (38.4 KB/s) - Connection closed at byte 5314183343. Retrying.

--2010-11-26 10:25:58--  (try:20)  http://dl.dropbox.com/u/PRIVATE-URL
Connecting to dl.dropbox.com|75.101.129.115|:80... connected.
HTTP request sent, awaiting response... 206 PARTIAL CONTENT
Length: 14425877949 (13G), 9111694606 (8.5G) remaining [video/quicktime]
Saving to: `2009 25 hours of thunderhill reel 10.mov'

         [ skipping 5188608K ]
5188608K ,,,,,,,, ,,,,,,,, ........ ........ ........ ........ 36% 61.7K 2d0h
5191680K ........ ........ ........ ........ ........ ........ 36% 38.1K 2d2h</code></pre>
<p>Success!  This is the 20th restart for 5GB averaging 500GB between connection failures.   Thanks to these few little tweaks it should keep trying until it finishes and then I&#8217;ll finally have my footage!  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2010/11/26/getting-very-large-files-from-flaky-hosts-using-wget/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Verifying HP RAID array status</title>
		<link>http://www.ghidinelli.com/2010/02/22/check-hp-raid-array-status</link>
		<comments>http://www.ghidinelli.com/2010/02/22/check-hp-raid-array-status#comments</comments>
		<pubDate>Mon, 22 Feb 2010 18:45:50 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1027</guid>
		<description><![CDATA[Make sure you get an appropriate alert when a drive goes dead in your HP/Compaq RAID array]]></description>
			<content:encoded><![CDATA[<p>Just a quicky &#8211; turns out our logwatch was not giving us enough of an alert when a drive failed in our raid array.  Obviously you want to replace a dead drive as quickly as possible to reduce the likelihood of a second or third drive failing and potentially taking your data with it.</p>
<p>For Linux, HP has a tool available called <a href="http://h20000.www2.hp.com/bizsupport/TechSupport/SoftwareDescription.jsp?lang=en&#038;cc=us&#038;swItem=MTX-66b08e49c28f4bd49f4641ed80&#038;jumpid=reg_R1002_USEN">hpacucli</a> (HP Array Configuration Utility for Linux) for interrogating HP/Compaq array controllers (SmartArray 5i, 6i, whatever) from the command line.  Before you can install the RPM (on CentOS/Redhat), you will need to first install a compatibility library: </p>
<pre><code>yum install compat-libstdc++-296
rpm -Uvh hpacucli-8.0-14.noarch.rpm </code></pre>
<p>Then I put this snippet into a new file <tt>/etc/cron.hourly/raidstatus</tt>:</p>
<pre><code>#!/bin/sh
/opt/compaq/hpacucli/bld/hpacucli ctrl all show config | egrep -i "(fail|error|offline|rebuild|ignoring|degraded|skipping|nok)"</code></pre>
<p>The command <tt>/opt/compaq/hpacucli/bld/hpacucli ctrl all show config</tt> normally generates something like this (from our development database server):</p>
<pre><code>Smart Array XXXXXXX in Slot 0      ()

   array A (Parallel SCSI, Unused Space: 0 MB)

      logicaldrive 1 (33.9 GB, RAID 1+0, OK)

      physicaldrive 2:0   (port 2:id 0 , Parallel SCSI, 36.4 GB, OK)
      physicaldrive 2:1   (port 2:id 1 , Parallel SCSI, 36.4 GB, OK)

   array B (Parallel SCSI, Unused Space: 0 MB)

      logicaldrive 2 (67.8 GB, RAID 1+0, OK)

      physicaldrive 2:2   (port 2:id 2 , Parallel SCSI, 36.4 GB, OK)
      physicaldrive 2:3   (port 2:id 3 , Parallel SCSI, 36.4 GB, OK)
      physicaldrive 2:4   (port 2:id 4 , Parallel SCSI, 36.4 GB, OK)
      physicaldrive 2:5   (port 2:id 5 , Parallel SCSI, 36.4 GB, OK)</code></pre>
<p>I believe you can reduce the grep to just &#8220;(fail|nok)&#8221; but I&#8217;m taking the conservative approach here.  Change the permissions to 0700 and if you have SELinux running make sure the context is set properly.</p>
<p>If your array and controller are in fine shape, then this command will output nothing.  If you have a dead drive, it will generate content which will cause cron to mail the root user about it.  Bingo &#8211; time to go to the colo!</p>
<p>I have seen other people use &#8220;ctrl all show status&#8221; which generates:</p>
<pre><code>Smart Array XXXXXXX in Slot 0
   Controller Status: OK
   Cache Status: OK
   Battery Status: OK</code></pre>
<p>I prefer to query the config which looks at individual physical drives in addition to the status of the array.  I have seen cases (just last week) where one dead drive in the array still lists the array status as OK (because, technically, it is OK, it&#8217;s just not optimal and may be pending major disaster!)</p>
<p><strong>Update 5/25/2011</strong> Had an error today, needed this code and corrected a few things.  I fixed a typo for a missing quote in the raidstatus script above and added a link to the actual utility.  For reference, the output from an error looks like this:</p>
<pre><code>physicaldrive 2:2   (port 2:id 2 , Parallel SCSI, ??? GB, Failed)
physicaldrive 2:5   (port 2:id 5 , Parallel SCSI, 72.8 GB, Rebuilding, active spare)</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2010/02/22/check-hp-raid-array-status/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TransferSync stable on ActiveMQ 5.2.0</title>
		<link>http://www.ghidinelli.com/2009/01/26/transfersync-stable-on-activemq-520</link>
		<comments>http://www.ghidinelli.com/2009/01/26/transfersync-stable-on-activemq-520#comments</comments>
		<pubDate>Mon, 26 Jan 2009 19:35:44 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Research/HOWTO]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[activemq]]></category>
		<category><![CDATA[transfer]]></category>
		<category><![CDATA[transfersync]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=535</guid>
		<description><![CDATA[In my post on synchronizing Transfer ORM with TransferSync, I used Apache ActiveMQ 5.1.0 which was not reliable for me.  After about a week of uptime, one of the hosts would invariably lose its connection to the queue and TransferSync would start throwing errors.  I thought I had solved it via a wireFormat [...]]]></description>
			<content:encoded><![CDATA[<p>In my post on <a href="https://www.ghidinelli.com/2008/10/16/synchronizing-transfer-orm-in-a-model-gluecoldspring-cluster-with-transfersync">synchronizing Transfer ORM with TransferSync</a>, I used Apache ActiveMQ 5.1.0 which was not reliable for me.  After about a week of uptime, one of the hosts would invariably lose its connection to the queue and TransferSync would start throwing errors.  I thought I had solved it via a wireFormat configuration option but it didn&#8217;t fix the problem.</p>
<p>Three weeks ago I grabbed the latest <a href="http://activemq.apache.org/activemq-520-release.html">ActiveMQ 5.2.0</a> and I&#8217;ve been running it locally in development and production.  I haven&#8217;t had a single queue failure since.  There were over 100 bugs fixed in this release so I would strongly recommend upgrading if you&#8217;re using ActiveMQ with <a href="http://transfersync.riaforge.org/">TransferSync</a> to keep your cluster of ColdFusion servers synchronized.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2009/01/26/transfersync-stable-on-activemq-520/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Access CFIDE with Apache</title>
		<link>http://www.ghidinelli.com/2008/11/05/access-cfide-with-apache</link>
		<comments>http://www.ghidinelli.com/2008/11/05/access-cfide-with-apache#comments</comments>
		<pubDate>Wed, 05 Nov 2008 17:25:44 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=281</guid>
		<description><![CDATA[I read a post by Jared Rypka-Hauer this morning on the Model-Glue list about his Apache-CF configuration that got me nodding in agreement.  He sets up his Apache like so:

I leave CFIDE and WEB-INF in the default location and create a symbolic link to it in the webroot of any vhost that needs access [...]]]></description>
			<content:encoded><![CDATA[<p>I read <a href="http://groups.google.com/group/model-glue/browse_thread/thread/bcb9f824103a7c33">a post</a> by Jared Rypka-Hauer this morning on the Model-Glue list about his Apache-CF configuration that got me nodding in agreement.  He sets up his Apache like so:</p>
<blockquote><p>
I leave CFIDE and WEB-INF in the default location and create a symbolic link to it in the webroot of any vhost that needs access to it. You need access to it for the scripts and CSS for any AJAX stuff, so it may be important to do this. I like having CFIDE in a consistent, central location and adding links to it where needed, and I like having a fully-default CF install so that things are always the same.
</p></blockquote>
<p>I agree with his closing sentiment; the longer I administer servers the more I have become a fan of default installs and default settings.  While getting it &#8220;just the way you like it&#8221; is great, it&#8217;s not a method that scales and it&#8217;s not easy to replicate unless you fully automate from the beginning.</p>
<p>Jared&#8217;s post made me want to share a quick tip I use in my Apache configuration files for the CFIDE directory.  I work on both Windows and Linux so I try to avoid symbolic links which are difficult to manage in Subversion and on multiple platforms.  Instead, I use a single-line Apache directive to accomplish the same thing in httpd.conf:</p>
<p><code>Alias /CFIDE /opt/jrun4/servers/cfusion/cfusion-ear/cfusion-war/CFIDE</code></p>
<p>Although the administrator has its own password, I like to further secure the ColdFusion administrator to prevent people from probing for vulnerabilities or <a href="http://www.adobe.com/devnet/security/security_zone/asb00-14.html">attempting a DoS</a>: </p>
<p><code>&lt;Location /CFIDE/administrator&gt;<br />
        Options +FollowSymLinks<br />
        Order deny,allow<br />
        Allow from all<br />
        AuthUserFile /opt/jrun4/servers/cfusion/cfusion-ear/cfusion-war/CFIDE/.htpasswd<br />
        AuthName "Administrators"<br />
        AuthType Basic<br />
        &lt;Limit GET POST&gt;<br />
                require valid-user<br />
        &lt;/Limit&gt;<br />
&lt;/Location&gt;</code></p>
<p>I have a few other Apache tips and tricks if anyone finds these interesting?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2008/11/05/access-cfide-with-apache/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
