Mail Part 1 Setup Smtp Opensmtpd

This is mostly my personal mail server documentation a bit polished in three blog posts.

DNS setup

Set a MX record to a subdomain like mail.domain.tdl and then the mail.domain.tdl points to your IP. Don't forget to increase the TTL of this records if everything works. Why? I set my TTL to 259200 sec, which are 3 days

Make sure your reverse DNS match the hostname of your mail server!

And you should probably set the Sender Policy Framework

doamin.tdl.                 IN   TXT    "v=spf1 mx mx:domain.tdl -all"

Create users

Now we need a user, replace $USERNAME with the account name. If your email address should be hi@domain.tdl your account name is hi.

pw user add $USERNAME -m -s /sbin/nologin -c "mail user ($USERNAME)" # create user account
passwd $USERNAME                                                     # change password

mkdir /home/$USERNAME/mbox                                           # create mail directory
chown -R $USERNAME:$USERNAME /home/$USERNAME/mbox                    # own the directory to the right user

If you need to create a few accounts maybe use this script, where you can just run this script with the user name as parameter.

Install OpenSMTPD

Before we can install OpenSMTPD we need to stop and remove sendmail. So first we stop it with:

service sendmail stop

Then we can edit /etc/rc.conf and add these lines, to make sure sendmail is not started automaticly after a reboot.

sendmail_enable="NONE"

Now we can install OpenSMTPD which is really really easy, it's just:

pkg install opensmtpd

and add to /etc/rc.conf

smtpd_enable="YES"

and your done. Well almost we need to create the SSL certificates and configure the OpenSMTPD.

Create your SSL certs

As the first step we symlink the certificate root to the global certificate root location. If it's not alreay done.

ln -s /usr/local/etc/ssl/cert.pem /etc/ssl/cert.pem

At this point we can create our certificates.

openssl genrsa -out /usr/local/openssl/private/mail.domain.tdl.key 4096
openssl req -new -x509 -key /usr/local/openssl/private/mail.domain.tdl.key -out /usr/local/openssl/certs/mail.domain.tdl.crt -days 1440

Country Name (2 letter code) [AU]: NL
State or Province Name (full name) [Some-State]:Amsterdam         
Locality Name (eg, city) []:Amsterdam
Organization Name (eg, company) [Internet Widgits Pty Ltd]:l33tsource Ltd
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:mail.domain.tdl
Email Address []:admin@domain.tdl

By default these key and certificate should only be accessible to the root user. So we fix that with chmod.

chmod 500 /usr/local/openssl/private/mail.domain.tdl.key
chmod 500 /usr/local/openssl/certs/mail.domain.tdl.crt

OpenSMTPD configuration

With the SSL certificate in place we can edit the smtpd config (/usr/local/etc/mail/smtpd.conf).

pki mail.domain.tdl key "/usr/local/openssl/private/mail.domain.tdl.key"
pki mail.domain.tdl certificate "/usr/local/openssl/certs/mail.domain.tdl.crt"

listen on lo1 port 25 hostname mail.domain.tdl tls pki mail.domain.tdl
listen on lo1 port 587 hostname mail.domain.tdl tls-require pki mail.domain.tdl auth mask-source

table aliases file:/etc/mail/aliases

accept from any for domain "domain.tdl" alias <aliases> deliver to maildir "~/mbox"
accept from local for any relay

This is it. Really simple and short. What this does is listen on port 25 and 587 on the lo1 interface (this should obviously match your interface) and accept encrypted connections. The key and certificate location are configured with the pki keyword. And the messages are delivered to the home directory of the user in a folder called mbox.

Now we can start the smtpd service and test it with telnet.

telnet servername 25
	EHLO mail.domain.tdl 
	MAIL FROM:<FROM@domain.tdl> 
	RCPT TO:<TO@domain.tdl> 
	DATA 
	Subject: Testmessage 
	(blank line) 
	This is a test.
	(blank line) 
	. 
	QUIT 

If it's says something like 250 2.0.0: 5x549x2a Message accepted for delivery, congratulation your SMTP works.

This is the first part of a three part series:

Gpg Enigmail And Error Messages

I got a GPG encrypted mail, which should be a good thing since encryption and these things. But every time I use GPG something does not work. And every time the error messages are useless.

So the moral of this blog post is: If you are a developer write meaningful error messages.

A short overview what my setup is, I have a Fedora 22 with gpg2 and my default mail client is Thunderbird. And to use Thunderbird with GPG I use the Enigmail plugin which if it's working an okayish way to read and write encrypted mails.

What was my problem? Well if you read the error messages I guess something like you haven't imported your private key yet.

gpg: decryption failed: No secret key

Error - no matching private/secret key found to decrypt message

So I checked that with gpg -K and I see my key, I even extracted the encrypted part from the mail and decrypted it on the command line without a problem. Thanks to the Internet I was able to find other people with the same problem. And one of this posts gave me the right idea. By default there is no pinentry-program installed. After I installed one with sudo dnf install pinentry-qt4 and restarted my Thunderbird it can magically encrypt the message.

Jekyll Build From Github

You might or might not remember how I publish this blog with Github. But I wrote a post about this. Since I migrated my hosting to a VPS I changed a few things. The important bits that changed are, the way things get logged. Now I use tee which has the side effect that the output is on my logfiles and get printed to stdout which you can see then on you php update page (this helps to debug the build process). The other thing that changed is that on FreeBSD jekyll is installed in /usr/local/bin, which is not in the default path. This resulted in a blog which get no updates, because the jekyll binary is missing. That's why I added /usr/local/bin to the path, to fix this.

$ cat update.php
<?php
	$output = shell_exec('./update.sh');
	echo "<pre>$output</pre>"; 
?>
$ cat update.sh
#!/bin/sh
export PATH=$PATH:/usr/local/bin

#the logfile
datestr=$(date +%Y%m%d_%H%M%S)
LOGFILE=/usr/local/www/update_log/log_$datestr

#cd to your git repo
cd /usr/local/www/blog_git_src

#update ALL TEH SOURCE
echo git | tee -a $LOGFILE
git version | tee -a $LOGFILE
git pull origin master | tee -a $LOGFILE

#build page
echo jekyll | tee -a $LOGFILE
jekyll build -d /usr/local/www/blog | tee -a $LOGFILE

Jekyll Nginx Rewrite Rules

I use permalink: pretty which create for each post a folder with a index.html. This creates nice urls like this /2015/04/22/htaccess-proxy. But last time I cheked my error logs I saw a few peoples who tried urls like this: /2015/04/22/htaccess-proxy.html. So I thought why not redirect this urls. Of course I'm not the first person with this problem, I found two blog post on which I based my solution.

My solution:

server {
        listen       80;
        server_name  l33tsource.com www.l33tsource.com;

        rewrite ^/index.html$ / redirect;
        rewrite ^(/.+)/index.html$ $1 redirect;
    
        if ($request_uri ~* ".html") {
            rewrite (?i)^(.*)/(.*)\.html $1/$2 redirect;
        }

        location / {
            rewrite ^/(.*) /$1 break;
            proxy_pass http://blog;
        }
}

If you have any problems or find broken urls, just write me.

###Update

For some weird reason all these redirection foo doesn't work when the blog upstream not on port 80 is.

Htaccess Proxy

Lets say you have a web application bound to localhost. For example your ruby or python web project. The next logic step is to install nginx and setup a reverse proxy. If that's not an option and you need to use Apache and can not edit the Apache settings. There is a solution which I used for some time:

This assumes that your application run at port 886688.

RewriteEngine On
RewriteRule ^(.*) http://localhost:886688/$1 [P]

Probably not the best and cleanest solution but works for me!