<?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>Brandon&#039;s Blog &#187; howto</title>
	<atom:link href="http://www.brandonturner.net/blog/tag/howto/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.brandonturner.net/blog</link>
	<description>Random thoughts on web applications, software development and Linux</description>
	<lastBuildDate>Thu, 08 Apr 2010 01:47:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>DKIM and DomainKeys for qmail</title>
		<link>http://www.brandonturner.net/blog/2009/03/dkim-and-domainkeys-for-qmail/</link>
		<comments>http://www.brandonturner.net/blog/2009/03/dkim-and-domainkeys-for-qmail/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 05:13:21 +0000</pubDate>
		<dc:creator>Brandon</dc:creator>
				<category><![CDATA[Server Admin]]></category>
		<category><![CDATA[DKIM]]></category>
		<category><![CDATA[DomainKeys]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[qmail]]></category>

		<guid isPermaLink="false">http://www.brandonturner.net/blog/?p=134</guid>
		<description><![CDATA[This patch adds support for signing and verifying DKIM and DomainKeys signatures to qmail.]]></description>
			<content:encoded><![CDATA[<p><a href="http://domainkeys.sourceforge.net/">DomainKeys</a> and its successor <a href="http://www.dkim.org/">DomainKeys Identified Mail (DKIM)</a> are technologies that allow organizations to take responsibility for a message.  This is done by cryptographically signing an email as it leaves an organization in route to its destination.  The signature can be verified using the DNS system to establish trust.  In theory the technologies help cut down on spam by proving a message originated from the domain it says it does.</p>
<p>Support for DomainKeys in qmail has existed for a while thanks to a <a href="http://www.qmail.org/qmail-1.03-dk-0.53.patch">patch</a> by Russel Nelson.  Kyle Wheeler created a set of <a href="http://www.memoryhole.net/qmail/#dkim">wrapper scripts</a> that can be used to provide support for DKIM and DomainKeys.  Mihai Secasiu has some <a href="http://patchlog.com/security/qmail-and-dkim/">wrapper scripts</a> similar to Kyle&#8217;s that provide support for DKIM via the libdkim library instead of Perl&#8217;s <a href="http://search.cpan.org/~jaslong/Mail-DKIM-0.31/">Mail::DKIM</a> module.</p>
<p>The current methods take different approaches to implement DKIM and DomainKeys.  The DomainKeys patch creates a single program, <code>qmail-dk</code> that is called before <code>qmail-queue</code>.  This program signs or verifies all <em>incoming</em> messages (that may later become outbound) based on the existence of the <code>DKSIGN</code> and <code>DKVERIFY</code> variables.  The DKIM wrapper scripts wrap <code>qmail-remote</code> to sign messages and wrap <code>qmail-queue</code> (or <code>qmail-dk</code>) to verify incoming messages.  This can be easier understood by looking at the <a href="http://www.nrg4u.com/">qmail big picture</a>.</p>
<p>I tend to agree with separate programs for signing outbound messages and verifying inbound messages as this allows signing <em>all</em> outbound messages, even those (such as NDRs) that never pass through <code>qmail-queue</code>.  I also prefer patching qmail as it tends to be a little easier and requires less configuration after qmail is installed.</p>
<p>In this post I will show you how to patch qmail to support DKIM as well as DomainKeys.  My <a href="http://www.bltweb.net/qmail/qmail-1.03-jms1.7.08-dkim-r1.patch">qmail DKIM/DomainKeys patch</a> uses neither Russel Nelson&#8217;s DomainKeys patch nor Kyle Wheeler&#8217;s DKIM/DomainKey wrappers, but borrows ideas from both.  My patch uses the <a href="http://sourceforge.net/projects/domainkeys/">libdomainkeys</a> and <a href="http://sourceforge.net/projects/libdkim/">libdkim</a> libraries to do the actual signing and verifying.  Rather than creating two new programs, I patch <code>qmail-smtpd</code> (for verifying) and <code>qmail-remote</code> (for signing) directly.</p>
<p>I&#8217;ll do my best to provide step by step instructions for patching and installing for you non-Gentoo users, but in my next post I&#8217;ll share my ebuild which does it all for you.</p>
<p><a name="libdomainkeys"></a><br />
<h4>1. Install libdomainkeys</h4>
<p>The <code>libdomainkeys</code> library is used to sign and verify DomainKeys signatures.</p>
<div class="prompt">
$ <span class="cmd">wget <a href="http://downloads.sourceforge.net/domainkeys/libdomainkeys-0.69.tar.gz">http://downloads.sourceforge.net/domainkeys/libdomainkeys-0.69.tar.gz</a></span><br />
$ <span class="cmd">tar -xzf libdomainkeys-0.69.tar.gz</span><br />
$ <span class="cmd">cd libdomainkeys-0.69</span><br />
$ <span class="cmd">make</span><br />
<span style="color: red;">(If you get errors during <code>make</code>, edit the Makefile and add <code>-lresolv</code> to the end of the <code>LIBS</code> line)</span><br />
$ <span class="cmd">sudo install -m 644 libdomainkeys.a /usr/local/lib</span><br />
$ <span class="cmd">sudo install -m 644 domainkeys.h dktrace.h /usr/local/include</span><br />
$ <span class="cmd">sudo install -m 755 dknewkey /usr/local/bin</span><br />
$ <span class="cmd">cd ..</span>
</div>
<p><a name="libdkim"></a><br />
<h4>2. Install libdkim</h4>
<p>The <code>libdkim</code> library is used to sign and verify DKIM signatures.  You&#8217;ll need g++ to compile this on your system.  The library claims to be portable, but I needed to patch it to get it to compile on my Gentoo box.  I&#8217;ve also included a (slightly modified) patch from <a href="http://patchlog.com/security/qmail-and-dkim/">Mihai Secasiu</a> that makes working with libdkimtest much easier.</p>
<div class="prompt">
$ <span class="cmd">wget <a href="http://downloads.sourceforge.net/libdkim/libdkim-1.0.19.zip">http://downloads.sourceforge.net/libdkim/libdkim-1.0.19.zip</a></span><br />
$ <span class="cmd">wget <a href="http://www.bltweb.net/qmail/libdkim-1.0.19-linux.patch">http://www.bltweb.net/qmail/libdkim-1.0.19-linux.patch</a></span><br />
$ <span class="cmd">wget <a href="http://www.bltweb.net/qmail/libdkim-1.0.19-extra-options.patch">http://www.bltweb.net/qmail/libdkim-1.0.19-extra-options.patch</a></span><br />
$ <span class="cmd">unzip libdkim-1.0.19.zip</span><br />
$ <span class="cmd">cd libdkim/src</span><br />
$ <span class="cmd">patch -p2 < ../../libdkim-1.0.19-linux.patch</span><br />
$ <span class="cmd">patch -p2 < ../../libdkim-1.0.19-extra-options.patch</span><br />
$ <span class="cmd">make</span><br />
$ <span class="cmd">sudo make install</span><br />
$ <span class="cmd">cd ../..</span>
</div>
<p><a name="install_qmail"></a><br />
<h4>3. Patch and install qmail</h4>
<p>I&#8217;m currently using <a href="http://qmail.jms1.net/patches/combined.shtml">John Simpson&#8217;s qmail Combined Patch Set</a> for my qmail installation.  The instructions below highlight how to apply my DKIM/DomainKeys patch on top of John&#8217;s combined patch.  I&#8217;d highly recommend checking out John&#8217;s combined patch as it is about as close as you can get to an actively maintained qmail.</p>
<p>I&#8217;m <strong>not</strong> attempting to describe or document John&#8217;s patch in anyway in this post, as John runs an excellent site about qmail (<a href="http://qmail.jms1.net/">qmail.jms1.net</a>) that contains far more information than is contained here.  Do not attempt to proceed without reading through John&#8217;s documentation as well as the rest of this post.</p>
<div class="prompt">
$ <span class="cmd">wget <a href="http://cr.yp.to/software/qmail-1.03.tar.gz">http://cr.yp.to/software/qmail-1.03.tar.gz</a></span><br />
$ <span class="cmd">wget <a href="http://qmail.jms1.net/patches/qmail-1.03-jms1.7.08.patch">http://qmail.jms1.net/patches/qmail-1.03-jms1.7.08.patch</a></span><br />
$ <span class="cmd">wget <a href="http://www.bltweb.net/qmail/qmail-1.03-jms1.7.08-dkim-r1.patch">http://www.bltweb.net/qmail/qmail-1.03-jms1.7.08-dkim-r1.patch</a></span><br />
$ <span class="cmd">tar -xzf qmail-1.03.tar.gz</span><br />
$ <span class="cmd">mv qmail-1.03 qmail-1.03-jms1.7.08</span><br />
$ <span class="cmd">cd qmail-1.03-jms1.7.08</span><br />
$ <span class="cmd">patch < ../qmail-1.03-jms1.7.08.patch</span><br />
$ <span class="cmd">patch -p1 < ../qmail-1.03-jms1.7.08-dkim-r1.patch</span><br />
$ <span class="cmd">sed -ie 	&#39;1s/$/ -DDKIM/&#39; conf-cc</span><br />
$ <span class="cmd">make</span><br />
$ <span class="cmd">make man</span><br />
$ <span class="cmd">sudo make setup check</span><br />
$ <span class="cmd">cd ..</span>
</div>
<p><a name="sign"></a><br />
<h4>4. Configure DKIM/DomainKeys signing</h4>
<p>Signing is done by <code>qmail-remote</code> and is controlled by the <code>dksign</code> control file.  Signatures are created using a private key on your system, and verified by a public key stored in the DNS for the email domain.</p>
<h5>Generate keys</h5>
<p>Before you can sign an email, you must create at least one public/private key pair.  You should create key pairs for every domain you wish to sign.  To create keys for <code>example.com</code>:</p>
<div class="prompt">
# <span class="cmd">mkdir -p /etc/domainkeys/example.com</span><br />
# <span class="cmd">cd /etc/domainkeys/example.com</span><br />
# <span class="cmd">dknewkey default 1024 > default.pub</span><br />
# <span class="cmd">chown -R root:root /etc/domainkeys</span><br />
# <span class="cmd">chmod 640 /etc/domainkeys/example.com/default</span><br />
# <span class="cmd">chown root:qmail /etc/domainkeys/example.com/default</span>
</div>
<p>It is very important that the default file be readable only by <code>root</code> and the group which <code>qmailr</code> (the <code>qmail-remote</code> user) belongs to.  This is the private key used for signing messages and, if compromised, would allow others to sign messages as your domain.</p>
<p>Now add a <code>TXT</code> entry to the DNS for <code>default._domainkey.example.com</code> containing the quoted part in the <code>/etc/domainkeys/example.com/default.pub</code>.  NOTE: You normally want to include the quotes!</p>
<h5>Configure control files</h5>
<p>Create a file <code>/var/qmail/control/dksign</code> containing one line:</p>
<div class="file">
/etc/domainkeys/%/default
</div>
<p>The <code>%</code> will be replaced with the domain name in the <code>From:</code> header (or the <code>Sender:</code> header if it exists).  If no file exists for the given domain, parent domains will be tried.  For example if the message is from <code>foo@bar.example.com</code>, <code>/etc/domainkeys/bar.example.com/default</code> will be tested first.  If the file does not exist, <code>/etc/domainkeys/example.com/default</code> will be tested.  If no key can be found, the message will not be signed.  If a key exists, but cannot be read or contains invalid data, the message will not be sent and will remain in the queue until the problem is fixed.</p>
<p>If you do not create the <code>/var/qmail/control/dksign</code> file, no messages will be signed.</p>
<h5>Test outbound signing</h5>
<p>Now that DKIM/DomainKeys signing is configured, you can test it by sending an email to <code>sa-test (at) sendmail dot net</code>.  This reflector will reply (within seconds) to the envelope sender with a status of the DomainKeys and DKIM signatures.</p>
<p>If you experience problems, consult the <code>qmail-remote</code> man page or post a comment below and I&#8217;ll try to help.</p>
<p><a name="verify"></a><br />
<h4>5. Configure DKIM/DomainKeys verification</h4>
<p>Verification is performed by <code>qmail-smtpd</code> and is controlled by the <code>DKVERIFY</code> environment variable.  Messages are only verified if <code>DKVERIFY</code> is set and RELAYCLIENT is <strong>not</strong> set.  You may control which IP addresses are verified using the tcpserver access file (sometimes stored in <code>/etc/tcprules.d/tcp.qmail-smtp</code>).</p>
<p>When verifying a message, the contents of <code>DKVERIFY</code> are checked against the status of the DomainKeys and DKIM results.  Each test result is represented by a letter.  <code>DKVERIFY</code> should contain a series of letters for DomainKeys results, a comma, and then a series of letters for the DKIM results.  If the letter is uppercase, the message will be rejected (hard error).  If the letter is lowercase, the message will be deferred (soft error).  The <code>DKVERIFY</code> variable can be set but empty, in which case messages will be verified and an <code>Authentication-Results:</code> header will be added but <em>all</em> messages will be accepted regardless of status.</p>
<p>The letters for DomainKeys results are:</p>
<table>
<tr>
<th>Code</th>
<th>Status</th>
<th>Description</th>
</tr>
<tr>
<td>A</td>
<td>OK</td>
<td>The message contained a signature which correctly matched the contents of the message.</td>
</tr>
<tr>
<td>B</td>
<td>BADSIG</td>
<td>The message contained a signature which DID NOT correctly match the contents of the message. The signature may be forged, or the content may have been changed after the original server applied the signature.</td>
</tr>
<tr>
<td>C</td>
<td>NOSIG</td>
<td>The message did not contain a <code>DomainKey-Signature</code> header, or contained one which was missing a required field, or had a signature header without a &#8220;From:&#8221; header.</td>
</tr>
<tr>
<td>D</td>
<td>NOKEY</td>
<td>The public key needed to verify the signature does not exist (i.e. the authoritative DNS server for the domain says that the TXT record which should contain the key does not exist.)</td>
</tr>
<tr>
<td>E</td>
<td>BADKEY</td>
<td>The public key which was found in DNS is not usable.</td>
</tr>
<tr>
<td>F</td>
<td>CANTVRFY</td>
<td>The public key needed to verify the signature cannot be found, because the DNS server which should have the key is not responding, or returned a temporary error condition. The domainkeys specification says that the server SHOULD treat this as a soft error, telling the client to try their delivery again at some point in the future.</td>
</tr>
<tr>
<td>G</td>
<td>SYNTAX</td>
<td>The message is not in the proper format. This could be an improperly formatted email address, a duplicate &#8220;From:&#8221; header in the message, or any number of things which &#8220;confuse&#8221; the program.</td>
</tr>
<tr>
<td>H</td>
<td>NORESOURCE</td>
<td>Out of memory. The domainkeys specification says that the server SHOULD treat this as a soft error, telling the client to try their delivery again at some point in the future.</td>
</tr>
<tr>
<td>I</td>
<td>ARGS</td>
<td>Arguments are not usable</td>
</tr>
<tr>
<td>J</td>
<td>REVOKED</td>
<td>The key which was used to generate the signature has been revoked.</td>
</tr>
<tr>
<td>K</td>
<td>INTERNAL</td>
<td>There was an internal error in the libdomainkeys library</td>
</tr>
</table>
<p>The letters for the DKIM results are:</p>
<table>
<tr>
<th>Code</th>
<th>Status</th>
<th>Description</th>
</tr>
<tr>
<td>A</td>
<td>OK</td>
<td>The message contained a signature which correctly matched the contents of the message.</td>
</tr>
<tr>
<td>B</td>
<td>FAIL</td>
<td>The message failed verification</td>
</tr>
<tr>
<td>C</td>
<td>BAD_SYNTAX</td>
<td>The <code>DKIM-Signature</code> header could not be parsed or had bad tags/values</td>
</tr>
<tr>
<td>D</td>
<td>SIG BAD</td>
<td>RSA verify failed</td>
</tr>
<tr>
<td>E</td>
<td>SIG BAD (testing)</td>
<td>RSA verify failed but testing</td>
</tr>
<tr>
<td>F</td>
<td>SIG EXPIRED</td>
<td>Signature is expired (x= is old)</td>
</tr>
<tr>
<td>G</td>
<td>SELECTOR INVALID</td>
<td>Selector doesn&#8217;t parse or contains invalid values</td>
</tr>
<tr>
<td>H</td>
<td>SELECTOR MISMATCH</td>
<td>Selector granularity doesn&#8217;t match</td>
</tr>
<tr>
<td>I</td>
<td>SELECTOR REVOKED</td>
<td>The selector was revoked (p= is empty)</td>
</tr>
<tr>
<td>J</td>
<td>DOMAIN TOO LONG</td>
<td>The domain name is too long to request</td>
</tr>
<tr>
<td>K</td>
<td>DNS TEMP FAIL</td>
<td>Temporary DNS error requesting public key</td>
</tr>
<tr>
<td>L</td>
<td>DNS PERM FAIL</td>
<td>Permanent DNS error requestion public key</td>
</tr>
<tr>
<td>M</td>
<td>PUBLIC KEY INVALID</td>
<td>Public key isn&#8217;t valid or can&#8217;t be parsed</td>
</tr>
<tr>
<td>N</td>
<td>NO SIG</td>
<td>The message contains no DKIM signatures</td>
</tr>
<tr>
<td>O</td>
<td>NO VALID SIG</td>
<td>The message contains no valid signatures</td>
</tr>
<tr>
<td>P</td>
<td>BAD BODY HASH</td>
<td>The message body doesn&#8217;t verify</td>
</tr>
<tr>
<td>Q</td>
<td>ALGORITHM MISMATCH</td>
<td>The selector (h=) doesn&#8217;t match signature (a=)</td>
</tr>
<tr>
<td>R</td>
<td>STAT INCOMPAT</td>
<td>Incompatible v=</td>
</tr>
</table>
<p>I recommend a <code>DKVERIFY</code> value of <code><strong>DEGIJKfh,CGHIJMQRkl</strong></code>.  This will only reject improperly formatted messages.  Messages that don&#8217;t verify will still be allowed.  I would advise against rejecting messages that don&#8217;t verify as there are still some problems with DomainKeys and DKIM (such as mailing lists).  Rather than rejecting bad signatures, incorporate the <code>Authentication-Results</code> header into your broader spam prevention strategy.</p>
<h5>The <code>Authentication-Results</code> header</h5>
<p>All messages received by <code>qmail-smtpd</code> when <code>DKVERIFY</code> is set will add an <code>Authentication-Results</code> header to the incoming message.  This header conforms to the <a href="http://tools.ietf.org/html/draft-kucherawy-sender-auth-header-20">IETF internet draft</a>.  Here&#8217;s an example from one of my emails:</p>
<pre>Authentication-Results: bltweb.net; domainkeys=pass (ok); dkim=pass (ok)</pre>
<p><a name="examples"></a><br />
<h4>6. Examples</h4>
<p>Here are some examples to help you configure your box.  Anything that normally should be private is made up.</p>
<h5>Keys</h5>
<p>For my bltweb.net domain name, here&#8217;s what my keys look like (these are not the actual keys installed on my system, those are private):</p>
<div class="prompt">
$ <span class="cmd">ls -l /etc/domainkeys/bltweb.net</span><br />
total 8.0K<br />
-rw-r&#45;&#45;&#45;&#45;&#45; 1 root qmail 887 Mar  4 18:49 default<br />
-rw-r&#45;&#45;r&#45;&#45; 1 root root&nbsp; 254 Mar  4 18:49 default.pub<br />
<br />
$ <span class="cmd">cat /etc/domainkeys/bltweb.net/default.pub</span><br />
default._domainkey	IN	TXT	&#8220;k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbFnVeFZdlud6/xvLoMt2/g9qrQzZjg6mopp4IYgPwNxRfQTsvYJo4dxP/aIt5UcL1YWtEnOm6/VL+wzj33WvVGL8GWdJDcUWGpCOysWuKasH/sXCaxoZSFMNM02K5pOgzaIVinWZNLIv+yaDSnBC3zb35HoQOnU4KLySECWPRuQIDAQAB&#8221;<br />
<br />
$ <span class="cmd">sudo cat /etc/domainkeys/bltweb.net/default</span><br />
&#8212;&#8211;BEGIN RSA PRIVATE KEY&#8212;&#8211;<br />
MIICXAIBAAKBgQDbFnVeFZdlud6/xvLoMt2/g9qrQzZjg6mopp4IYgPwNxRfQTsv<br />
YJo4dxP/aIt5UcL1YWtEnOm6/VL+wzj33WvVGL8GWdJDcUWGpCOysWuKasH/sXCa<br />
xoZSFMNM02K5pOgzaIVinWZNLIv+yaDSnBC3zb35HoQOnU4KLySECWPRuQIDAQAB<br />
AoGAXuZniI2JuwK8Pg4LghEmhKK0waKnmIubnfYuVis+0XrKVEiJPoh1xSevfd7n<br />
K3IDJQ9By8K8a8b3gGtH7fX3ktWWFNz++DpewvWzFksC++7rhZoarBC1puWxVNYI<br />
M4xdqEtKXHIzaj3nRHM76RBD5htqa2hZkIDqfK7vDVZUkEECQQD0C5pmMGaBjO1K<br />
bC0hs8dMogxsrnwooIiHg1FO0WhOXGxKYuQGxXjR/fNz8gUyeicCPB3/piKaucGT<br />
OY1X0b9FAkEA5dHhTQTnkMD0pLow6yXTehy8NWzmIl9/EeIQu9HoXVpIGePy4Mrr<br />
ydJzaisQ+RJ8dO5C+1PeR89IRYdeGS/l5QJBAKHRG8SMbTuTdTe2uMozCYA/pttd<br />
asgJgd3Q7dXENlRXJhrArY/r2ivrJkUIAfgxVLI/qGh+AU30w2zaaWUEl70CQEe7<br />
wv8vULg2AiaIl0xOejvbTEPAwfRoqlkCnwaA9m5tB6RNKjpQHFjaf3vcBWg5BO/a<br />
jr2z5+WyJXTOU+i4sqECQC/lZY/0/cgEyyD0UL+oqYrVmlIm5Sc9Pnsu1fIRsfgC<br />
SnHS8/eTTUxNERGIYso4+wVFHR82oR8hucVYa8iY7CM=<br />
&#8212;&#8211;END RSA PRIVATE KEY&#8212;&#8211;
</div>
<h5>Signing Configuration</h5>
<p>To sign emails for all domains for which I have a key in <code>/etc/domainkeys</code>, I set the <code>control/dksign</code> configuration file:</p>
<div class="prompt">
$ <span class="cmd">ls -l /var/qmail/control/dksign</span><br />
-rw-r&#45;&#45;r&#45;&#45; 1 root root 31 Mar 17 14:02 /var/qmail/control/dksign<br />
<br />
$ <span class="cmd">cat /var/qmail/control/dksign</span><br />
/etc/domainkeys/%/default
</div>
<h5>Verify Configuration</h5>
<p>Here&#8217;s an example of my <code>/etc/tcprules.d/tcp.qmail-smtp</code> file.  Make sure you regenerate the cdb file after editing your <code>tcp.qmail-smtp</code> file!</p>
<div class="file">
# Connections from localhost are allowed to relay<br />
127.0.0.1:allow,RELAYCLIENT=&quot;&quot;,RBLSMTPD=&quot;&quot;<br />
<br />
# Everyone else can&#8217;t relay unless they auth<br />
# All signed mail is allowed, even if it&#8217;s bad, but still prepend the<br />
# Authentication-Results header<br />
:allow,DKVERIFY=&quot;&quot;,AUTH_UNSET_DKVERIFY=&quot;&quot;<br />
<br />
# Or if I want to use the recommend DKIM settings, comment out the line<br />
# above and use<br />
# :allow,DKVERIFY=&quot;DEGIJKfh,CGHIJMQRkl&quot;,AUTH_UNSET_DKVERIFY=&quot;&quot;
</div>
<p><a name="finished"></a><br />
<h4>7. Finished</h4>
<p>That&#8217;s it.  You should now have a qmail installation capable of signing and verifying messages.  More information is contained in the <code>qmail-smtpd</code> and <code>qmail-remote</code> man pages.</p>
<p>If you have any comments or find any bugs, please feel free to post a comment below.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brandonturner.net/blog/2009/03/dkim-and-domainkeys-for-qmail/feed/</wfw:commentRss>
		<slash:comments>63</slash:comments>
		</item>
		<item>
		<title>Installing Gentoo 2008.0 amd64 on a Linode VPS</title>
		<link>http://www.brandonturner.net/blog/2009/02/install-gentoo-amd64-linode/</link>
		<comments>http://www.brandonturner.net/blog/2009/02/install-gentoo-amd64-linode/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 05:21:17 +0000</pubDate>
		<dc:creator>Brandon</dc:creator>
				<category><![CDATA[Gentoo]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[Linode]]></category>
		<category><![CDATA[vps]]></category>

		<guid isPermaLink="false">http://www.brandonturner.net/blog/?p=14</guid>
		<description><![CDATA[Linode VPS doesn't provide a Gentoo 2008.0 amd64 image out of the box.  Here I describe the steps needed to install a fresh Gentoo 2008.0 image on Linode.]]></description>
			<content:encoded><![CDATA[<p>Today I signed up for a <a title="Linode.com" href="http://www.linode.com">Linode VPS</a>.  Linode appeared to have great reviews and very reasonable prices.  I had originally looked at <a href="http://www.vr.org">Host Virtual</a>, primarily because they are planning to offer native ipv6 (something I&#8217;ve been wanting to play with) later this month.  I ended up with Linode because they have a Dallas datacenter which makes my connections from Austin pretty fast.</p>
<p>One advantage that Host Virtual provided was a more recent Gentoo image.  Linode only offers a Gentoo 2007.0 install, which it doesn&#8217;t even list as a <em>current distribution</em>.  No worries, in this post I describe the steps I took to install a fresh <strong>Gentoo 2008.0 amd64</strong> image on my new Linode!</p>
<div class="note">
<strong>Update:</strong>  On April 4 2009, Linode released a <a href="http://blog.linode.com/2009/04/04/gentoo-20080-x86_64-and-slackware-122/">Gentoo 2008.0 x86_64</a> image, which somewhat obsoletes this post.  I haven&#8217;t tried it, but if your looking to try 64-bit Gentoo on a Linode, try that image instead of these instructions.
</div>
<p>Before we get started, some of the things I wanted on my system:</p>
<ul>
<li>x86_64 kernel running natively compiled 64-bit applications</li>
<li>ReiserFS filesystem instead of ext3</li>
<li>Basic LAMP server and no more</li>
</ul>
<div class="note">
<strong>Note:</strong> Currently, Linode does not provide a 64-bit recovery option, so we&#8217;ll have to install a small 64-bit environment to use when setting up our new Gentoo environment.  This can be done with only 300MB of disk space so it is best to leave it installed in case your Gentoo environment gets screwed up.
</div>
<h4>1. Create recovery configuration profile</h4>
<ol>
<li>From the Linode Manager Dashboard, click <em>Deploy a Linux Distribution</em></li>
<li>Select an Unbuntu 8.10 64-bit (or similar 64-bit OS) with a 300MB disk drive.  If you want swap space, you should configure that here.</li>
<li>Click <em>Create Profile</em></li>
<li>Change the name of the profile to &#8220;Recovery Ubuntu 64bit&#8221;</li>
</ol>
<h4>2. Create the Gentoo disk image</h4>
<ol>
<li>From the Linode Manager Dashboard, click <em>Create a new Disk Image</em></li>
<li>Give your disk a label (you can change this later) and size (most likely all the remaining disk space on your Linode)</li>
<li>Pick <em>Unformatted / raw</em> for the filesystem, we&#8217;ll format using ReiserFS later</li>
<li>Click <em>Create Disk</em></li>
<li>Edit your Recovery Unbuntu 64bit profile: set /dev/xvdc to the disk image you just created.</li>
<li>Click <em>Save Profile</em></li>
</ol>
<h4>3. Boot the recovery profile</h4>
<ol>
<li>From the Linode Manager Dashboard, boot your recovery profile</li>
<li>Log in with your favorite ssh client: root@<em>&lt;linode vps IP&gt;</em> and the root password you set up in section 1</li>
<li>Install some tools required in later steps:
<div class="prompt">
root@li # <span class="cmd">apt-get update</span><br />
root@li # <span class="cmd">apt-get install reiserfsprogs wget</span>
</div>
</li>
</ol>
<h4>4. Set up Gentoo</h4>
<p style="margin-top: 0;">This section roughly follows the <a href="http://www.gentoo.org/doc/en/gentoo-x86-quickinstall.xml">Gentoo Quick Install Guide</a>.</p>
<ol>
<li>Create the ReiserFS filesystem:
<div class="prompt">
root@li # <span class="cmd">mkreiserfs /dev/xvdc</span>
</div>
<li>Mount the filesystem:
<div class="prompt">
root@li # <span class="cmd">mkdir -p /mnt/gentoo</span><br />
root@li # <span class="cmd">mount /dev/xvdc /mnt/gentoo</span><br />
root@li # <span class="cmd">cd /mnt/gentoo</span>
</div>
</li>
<li>Set up the stage:
<div class="prompt">
root@li # <span class="cmd">wget http://gentoo.osuosl.org/releases/amd64/2008.0/stages/stage3-amd64-2008.0.tar.bz2</span><br />
root@li # <span class="cmd">tar xjpf stage3*</span><br />
root@li # <span class="cmd">rm stage3*</span>
</div>
</li>
<li>Install latest portage snapshot:
<div class="prompt">
root@li # <span class="cmd">cd /mnt/gentoo/usr</span><br />
root@li # <span class="cmd">wget http://gentoo.osuosl.org/snapshots/portage-latest.tar.bz2</span><br />
root@li # <span class="cmd">tar xjf portage-lat*</span><br />
root@li # <span class="cmd">rm portage-lat*</span>
</div>
</li>
<li>Chroot into the new Gentoo environment:
<div class="prompt">
root@li # <span class="cmd">cd /</span><br />
root@li # <span class="cmd">mount -t proc proc /mnt/gentoo/proc</span><br />
root@li # <span class="cmd">mount -o bind /dev /mnt/gentoo/dev</span><br />
root@li # <span class="cmd">cp -L /etc/resolv.conf /mnt/gentoo/etc/</span><br />
root@li # <span class="cmd">chroot /mnt/gentoo /bin/bash</span><br />
li50-172 / # <span class="cmd">env-update &#038;&#038; source /etc/profile</span>
</div>
</li>
<li>Set your timezone:
<div class="prompt">
li50-172 / # <span class="cmd">ls /usr/share/zoneinfo</span><br />
<span style="color: red">(Using US/Central as an example)</span><br />
li50-172 / # <span class="cmd">cp /usr/share/zoneinfo/US/Central /etc/localtime</span><br />
li50-172 / # <span class="cmd">nano -w /etc/conf.d/clock</span><br />
<span style="color: red">(Change value of TIMEZONE variable, e.g. TIMEZONE=&#8221;US/Central&#8221;)</span><br />
li50-172 / # <span class="cmd">date</span><br />
Mon Feb 9 14:41:50 CST 2009
</div>
</li>
<li>Set host and domain name
<div class="prompt">
li50-172 / # <span class="cmd">cd /etc</span><br />
li50-172 etc # <span class="cmd">echo &#8220;127.0.0.1 mybox.at.myplace mybox localhost&#8221; &gt; hosts</span><br />
li50-172 etc # <span class="cmd">sed -i -e &#8216;s/HOSTNAME.*/HOSTNAME=&#8221;mybox&#8221;/&#8217; conf.d/hostname</span><br />
li50-172 etc # <span class="cmd">hostname mybox</span><br />
li50-172 etc # <span class="cmd">hostname -f</span><br />
mybox.at.myplace
</div>
</li>
<li>Configure fstab mount points
<div class="prompt">
li50-172 etc # <span class="cmd">nano -w fstab</span>
</div>
<p style="margin-bottom:0">Edit the fstab file similar to:</p>
<div class="file">
<pre>
/dev/xvda     /       reiserfs     noatime,notail  0 1
/dev/xvdb     none    swap         sw              0 0
</pre>
</div>
</li>
<li>Edit <code>/etc/inittab</code>.<br />
To ensure the lish console works if you ever need it, edit the <code>terminals</code> section of <code>/etc/inittab</code> to look like:</p>
<div class="file">
<pre>
# TERMINALS
c1:12345:respawn:/sbin/agetty 38400 <b>hvc0</b> linux
#c2:2345:respawn:/sbin/agetty 38400 tty2 linux
#c3:2345:respawn:/sbin/agetty 38400 tty3 linux
#c4:2345:respawn:/sbin/agetty 38400 tty4 linux
#c5:2345:respawn:/sbin/agetty 38400 tty5 linux
#c6:2345:respawn:/sbin/agetty 38400 tty6 linux
</pre>
</div>
</li>
<li>Configure networking and SSH:
<div class="prompt">
li50-172 etc # <span class="cmd">rc-update add net.eth0 default</span><br />
 <span style="color: green">*</span> net.eth0 added to runlevel default<br />
li50-172 etc # <span class="cmd">rc-update add sshd default</span><br />
 <span style="color: green">*</span> sshd added to runlevel default<br />
li50-172 etc # <span class="cmd">passwd</span><br />
New UNIX password: <span style="color: red">type_the_password</span><br />
Retype new UNIX password: <span style="color: red">type_the_password_again</span><br />
passwd: password updated successfully
</div>
</li>
<li>Install system tools:
<div class="prompt">
li50-172 etc # <span class="cmd">emerge logrotate syslog-ng vixie-cron reiserfsprogs dhcpcd</span><br />
li50-172 etc # <span class="cmd">rc-update add syslog-ng default</span><br />
 <span style="color: green">*</span> syslog-ng added to runlevel default<br />
li50-172 etc # <span class="cmd">rc-update add vixie-cron default</span><br />
 <span style="color: green">*</span> vixie-cron added to runlevel default
</div>
</li>
<li>Prepare to reboot:
<div class="prompt">
li50-172 etc # <span class="cmd">exit</span><br />
root@li # <span class="cmd">umount /mnt/gentoo/proc /mnt/gentoo/dev/ /mnt/gentoo</span><br />
root@li # <span class="cmd">exit</span>
</div>
</li>
</ol>
<h4>5. Set up Gentoo profile</h4>
<ol>
<li>From the Linode Manager, shutdown the recovery Linode.</li>
<li>Create a new profile by clicking <em>Create a new Configuration Profile</em></li>
<li>Set the following options:
<ul>
<li>Label: Gentoo 2008.0 amd64</li>
<li>Kernel: a 64-bit kernel, e.g. 2.6.27.4-x86_64-linode3</li>
<li>Drive: /dev/xvda:  <em>The disk image you set up in section 2 (<strong>not</strong> the small Ubuntu recovery disk)</em></li>
<li>Drive: /dev/xvdb: Swap Image</li>
</ul>
</li>
</ol>
<h4>6. Boot Gentoo and finish installation</h4>
<ol>
<li>From the Linode Manager, click the <em>Boot</em> button for your new Gentoo profile</li>
<li>Log in via ssh: root@<em>&lt;Linode VPS IP&gt;</em><br />
(You may have to delete the old ssh key out of your known_hosts file on your local machine)</li>
<li>Add a non-root user, install sudo and disable root logins via SSH:
<div class="prompt">
mybox ~ # <span class="cmd">useradd -m -G wheel <em>username</em></span><br />
mybox ~ # <span class="cmd">passwd <em>username</em></span><br />
New UNIX password: <span style="color: red">type_the_password</span><br />
Retype new UNIX password: <span style="color: red">type_the_password_again</span><br />
passwd: password updated successfully<br />
mybox ~ # <span class="cmd">nano -w /etc/ssh/sshd_config</span><br />
<span style="color: red;">(Add a line: <code>PermitRootLogin: no</code>)</span><br />
mybox ~ # <span class="cmd">emerge sudo</span><br />
mybox ~ # <span class="cmd">visudo</span><br />
<span style="color: red;">(Uncomment the line: &#8220;<code>%wheel   ALL=(ALL) ALL</code>&#8220;, around line 24)</span><br />
mybox ~ # <span class="cmd">/etc/init.d/sshd restart</span>
</div>
</li>
<li>Install a simple conservative firewall:
<div class="prompt">
mybox ~ # <span class="cmd">emerge iptables</span><br />
mybox ~ # <span class="cmd">iptables -A INPUT -p tcp -m tcp &#8211;dport 22 -j ACCEPT</span><br />
mybox ~ # <span class="cmd">iptables -A INPUT -p icmp -m icmp &#8211;icmp-type 8 -j ACCEPT</span><br />
mybox ~ # <span class="cmd">iptables -A INPUT -i lo -j ACCEPT</span><br />
mybox ~ # <span class="cmd">iptables -A INPUT -m state &#8211;state RELATED,ESTABLISHED -j ACCEPT</span><br />
mybox ~ # <span class="cmd">iptables -P FORWARD DROP</span><br />
mybox ~ # <span class="cmd">iptables -P INPUT DROP</span><br />
mybox ~ # <span class="cmd">/etc/init.d/iptables save</span><br />
mybox ~ # <span class="cmd">/etc/init.d/iptables start</span><br />
mybox ~ # <span class="cmd">rc-update add iptables default</span><br />
 <span style="color: green">*</span> iptables added to runlevel default
</div>
</li>
<li>Select a Gentoo mirror and update make.conf:
<div class="prompt">
mybox ~ # <span class="cmd">emerge mirrorselect</span><br />
mybox ~ # <span class="cmd">mirrorselect -i -o >> /etc/make.conf</span><br />
mybox ~ # <span class="cmd">mirrorselect -i -r -o >> /etc/make.conf</span><br />
mybox ~ # <span class="cmd">nano -w /etc/make.conf</span>
</div>
<p style="margin-bottom: 0;">Edit the file to include the parts in bold:</p>
<div class="file">
<pre>
# Typical Linode has 4 processors, make use of them when compiling
<strong>MAKEOPTS="-j5"</strong>

<strong>CHOST="x86_64-pc-linux-gnu"</strong>
<strong>CFLAGS="-march=nocona -O2 -pipe"</strong>
<strong>CXXFLAGS="${CFLAGS}"</strong>
</pre>
</div>
<p style="margin-bottom: 0;">At this point you should also run <code>emerge -vpe world</code> and decide what USE variables you want to include in your make.conf file.</p>
</li>
<li>Define locales:
<div class="prompt">
mybox ~ # <span class="cmd">nano -w /etc/locale.gen</span><br />
<span style="color: red;">(Uncomment the first two en_US lines)</span><br />
mybox ~ # <span class="cmd">locale-gen</span>
</div>
</li>
<li>Update portage and installed packages:
<div class="prompt">
mybox ~ # <span class="cmd">emerge portage</span><br />
mybox ~ # <span class="cmd">emerge -vpuD &#8211;newuse world</span><br />
mybox ~ # <span class="cmd">emerge -vUD &#8211;newuse world</span><br />
<span style="color: red;">(Go grab some lunch, this is going to take a while.)</span><br />
mybox ~ # <span class="cmd">emerge &#8211;oneshot libtool</span><br />
mybox ~ # <span class="cmd">emerge gentoolkit</span><br />
mybox ~ # <span class="cmd">revdep-rebuild</span>
</div>
</li>
</ol>
<h4>7. Reboot and enjoy</h4>
<p>At this point I like to reboot the server to ensure that everything comes back up the way I expect it.  This isn&#8217;t necessary however.</p>
<p>After reboot my server was using just under a GB of data (990264 bytes) and about 60MB of RAM.  The server is now ready to install apache, mysql, etc.  I&#8217;ll be looking at optimizing my memory usage in a later post.</p>
<p class="note green" style="font-size: 90%;"><strong>Note:</strong> If you found this helpful and are interesting in signing up for Linode, feel free to use my referral code below.  I&#8217;m only putting this out there if you&#8217;d like to use it &#8211; you can easily sign up for a Linode VPS without it!<br />
<a href="http://www.linode.com/?r=edff465df97bb1e29468836d3700c79a2d24a17e">http://www.linode.com/?r=edff465df97bb1e29468836d3700c79a2d24a17e</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.brandonturner.net/blog/2009/02/install-gentoo-amd64-linode/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
