Think Tank Workspaces

Using plan9/9front as a Mail Server

Mail is a pain to setup on any system that is traditionaly Linux or BSD Unix.

You can tripple that with plan9 sorry to say. A lot of time was spent on other systems such as sendmail and qmail, exim and postfix.

A lot of work is obfuscated so basically you enter in some basic paramaters such as alias, ip address and domain names and play around with relay settings and you are done.

Make no mistake those systems are a pain also. With plan9 everything is decoupled and you are kind of forced to work at a lower level.

FQA 7.7 Mail Server configuration and maintenance

This chapter will be your friend and you will learn it as well as you can. But it also helps to have some other examples not listed in the FQA. Chapter 7.9 TLS will also be extremely helpful when for key and certificate creation.

The first thing you will configure is smtpd.conf. Its pretty well documented and straight forward.

norelay		on	#allow relaying
verifysenderdom	on	#disable dns verification of sender domain
saveblockedmsg	off	#save blocked messages
ourdomains	*,,

I believe I tested with 'no relay off', removed ournets, and ourdomains only during test phase.

Next in configuration is rewrite. They mention to copy rewrite.gateway or to rewrite then edit the files ex: cp rewrite.gateway rewrite

\"(.+)\"		translate	"/bin/upas/aliasmail '\1'"
[^!@.]+			translate	"/bin/upas/aliasmail '&'"

\l!(.*)					alias		\1
\l\!(.*)	alias 	\1
(|!(.*)	alias	\2

local!"(.+)"		>>		/mail/box/\1/mbox
local!(.*)		>>		/mail/box/\1/mbox
@([^@!,]*):([^!@]*)@([^!]*)		alias	\2@\3@\1
@([^@!]*),@([^!@,]*):([^!@]*)@([^!]*)	alias	@\1:\3@\4@\2
([^@]+)@([^@]+)@(.+)	alias		\2!\1@\3
([^@]+)@([^@]+)		alias		\2!\1

([^!]*)!(.*) 		| 		"/mail/lib/qmail '\s' 'net!\1'" "'\2'"

The only thing I added to the rewrite above is as follows:

\l\!(.*)	alias 	\1
(|!(.*)	alias	\2

For some reason I needed both the main domain and the host I also needed to increment the value from \1 to \2

Next configuration is names.local

I didn't really change mine

postmaster glenda

Finaly you need to change remotemail.

echo "----------" >> /tmp/mail-hell.txt
echo $my_date >> /tmp/mail-hell.txt
fd=`{/bin/upas/aliasmail $sender}
echo "fd from sender: $fd" >> /tmp/mail-hell.txt
	case *.*
	case *

# ### debug
echo "sender: $sender" >> /tmp/mail-hell.txt
echo "addr: $addr" >> /tmp/mail-hell.txt
echo "fd: $fd" >> /tmp/mail-hell.txt
exec /bin/upas/smtp -d -h $fd $addr $sender $*

For some reason this was extremely difficult and I added a bunch of print statements.

fd=`{/bin/upas/aliasmail $sender}

This command broke everything becuase it defaulted to aliasmail -f $sender which returns nothing and the rest of the script does not work.

I'm not sure if I will need to add it back later or not. But this files writes data out to /tmp/mail-hell.txt and you can cat the information out when you need to.

Now you need to turn on some service.

#smtp serv net incalldir user
user=`{cat /dev/user}
#exec upas/smtpd -n $3
exec /bin/upas/smtpd -c /sys/lib/tls/smtp.pem -n $3

If !tcp587 does not exist copy !tcp25 tcp587 and edit the file like above

You can now send with smtp. But first you need to create certs to put in /sys/lib/tls. We will get to that in a bit.

For receiving mail you need turn on that service also. The original in is here followed by my change.

#exec tlssrv -c/sys/lib/ssl/cert.pem -limap4d -r`{cat $3/remote} /bin/upas/imap4d -p -r`{cat $3/remote}>[2]/sys/log/imap4d
exec tlssrv -c/sys/lib/tls/smtp.pem -limap4d -r`{cat $3/remote} /bin/upas/imap4d -p -r`{cat $3/remote}>[2]/sys/log/imap4d

Setting up TLS Certificates

ramfs -p
cd /tmp
auth/rsagen -t \
	'service=tls role=client owner=*' > smtp.key
chmod 600 key
cp smtp.key /sys/lib/tls/smtp.key

Notice I called it smtp.key probably not the best name. Make no mistake its just a key.

Next you need to create the cert that both imap and smtp will use. Like I mentioned before perhaps I didn't choose the best name. Also notice I added the domain name to 'CN'

auth/rsa2x509 'C=US' /sys/lib/tls/smtp.key | \
	auth/pemencode CERTIFICATE > /sys/lib/tls/smtp.pem

But you are still not ready. You need to copy the key to factotum and make sure its run on bootup.

mkdir /cfg/$sysname
touch /cfg/$sysname/cpustart
echo 'cat /sys/lib/tls/smtp/key >>/mnt/factotum/ctl' >>/cfg/$sysname/cpustart

Now when you reboot: 'fshalt -r'

The key should be loaded to factotum for everyone to use and your services for smtp and imap should be up and running.

Mail is still not working

Well chances are if you did everything correctly it still does not work.

When I first started this I created an EC2 instance on amazon and pushed a qemu image to it. rc-httpd worked fine out of the box. I was super excited until I started to mess with mail.

By default smtp/imap is turned of for ports 25, 587,993 etc...

You have to contact AWS to get it turned off and that is a difficult task to say the least Plus I found it to be a bit expensive. They also want you to use AWS SES and or AWS Workmail.

That can get expensive quickly. I'm sure there is a way around this but why fight it.

With Linode VPS you can get smtp turned on within the hour. Super fast and cheaper. My AWS instance was a t3.small at around $14+ a month. Linode is $5 per month.

The other thing to think about when in Qemu enviornment is you have to remember to port forward or hostfwd the services for email. I forgot to do that a few times. Just slipped my mind.

AWS has a firewall as well as other VPS providers like namecheap. You need to turn on those ports.

Linode uese qemu behind the scenes but the network is bridged so you don't have to worry so much about ports.


Even though I'm not managing DNS on plan9. You still need to deal with it in some fashion.

You can add the following to your DNS even if you don't manage it and it might prove helpful. pref=1

For the network settings. I really needed smtp= and mail= on the network. Its up to you to choose if you will be using the FQDN or the IP. Sometimes I think its safer to use the IP address. ip= ipmask=

And no does not exist. My DNS is managed by Gandi.

Below is Gandi DNS pointing to the linode ip address. You can do the same with Godaddy or some other DNS provider.

@ 10800 IN SOA 1646461443 10800 3600 604800 10800
@ 10800 IN A
@ 10800 IN MX 10
@ 10800 IN MX 10
@ 10800 IN MX 10
@ 10800 IN TXT "v=spf1 a mx ip4: -all"
_20948fec0056d2c1f86019ec5d2b200d 10800 IN CNAME
_dmarc 10800 IN TXT "v=DMARC1; p=none; fo=1;;"
_dmarc.maat 10800 IN TXT "v=DMARC1; p=none; fo=1;;"
blog 10800 IN CNAME
maat 10800 IN A
maat 10800 IN TXT "v=spf1 a mx ip4: -all"
mail 10800 IN A
mail 10800 IN TXT "v=spf1 a mx ip4: -all"
www 10800 IN A

/lib/ndb/local was kind of messy when dealing with auth/dom so I ended up having to add an additional subdomain to gandi for this particular host called 'maat'.

You will need to create an MX record in my case I created two of them. YOU will also need to create an A record for You will need to create TXT record for spf settings. Yes I had to read up on SPF and DKIM to figure out why it was needed and what in the world it is. Plan9 doesn't currently support DKIM. But its helpful to have spf configured and _dmarc even if its not using dkim the _dmarc reveals a lot.

For gmail to accept mail I needed a "_dmarc" for the root of the domain and the host "".

Finally I forgot about PTR record for reverse DNS. You don't set this on Gandi or Godaddy or whatever dns you are using. If you are doing all dns in plan9 then perhaps you won't have to worry about it much.

On linode you need to go to the Node -> Network -> Edit rDNS

Just change it to the domain. In my case it was for you it might be


Even with all of this setup the troubleshooting phase can prove difficult.

I suggest you split the screen as follows:

Draw 3 terminals to the right for smtp stuff and run the following lines. They don't have to be big terminal screens. Just enough to display a few lines of text.

tail -f /sys/log/smtp
tail -f /sys/log/
tail -f /sys/log/smtpd

Now draw 3 terminals to the left

tail -f /sys/log/imap4d
tail -f /sys/log/mail
tail -f /tmp/mail-hell.txt

You can start out sending mail with the following command. You will want to use a known address to send to that is not plan9. You can use gmail if you would like and note that it will be blocked.

echo hello | mail -s foobar

Yes it will be blocked but it reveals a lot of information.


maat Feb 28 19:21:53 delivery  at net! (
mailfrom failed: 553-5.1.7 The sender address <glenda@tcp!!smtp>
is not a
553 5.1.7 valid RFC-5321 address. k8-20020a170902694800b0014fc3733e43si9963578plt.551
- gsmtp
maat Feb 28 19:24:31 delivery  at net! (
mailfrom failed: 553-5.1.7 The sender address <glenda@tcp!!smtp>
is not a
553 5.1.7 valid RFC-5321 address. bh3-20020a056a02020300b00372dfb3acf7si11304950pgb.690
- gsmtp
maat Feb 28 19:38:01 delivery '/net.alt/dns' does not exist (tcp!!smtp) 
maat Feb 28 19:38:44 delivery '/net.alt/dns' does not exist ( 
maat Feb 28 19:40:59 delivery '/net.alt/dns' does not exist ( 

You know you are getting close when you get the following:

550-5.7.1 likely unsolicited mail. To reduce the amount of spam sent to Gmail,
550-5.7.1 this message has been blocked. Please visit
550 5.7.1  for more information. w18-20020a170902e89200b001518e753a1fsi924888plg.374
- gsmtp
maat Mar  1 10:48:15 delivery gunnells at net! ( rcptto failed: 550-5.7.1 [ 12] Our system has detected that
this message is
550-5.7.1 likely unsolicited mail. To reduce the amount of spam sent to Gmail,
550-5.7.1 this message has been blocked. Please visit
550 5.7.1  for more information. i14-20020a655b8e000000b00373cf6d0d9esi13398494pgr.59

Here is /sys/log/smtp

maat Mar  1 14:23:58 glenda sent 369 bytes to
maat Mar  1 14:24:24 glenda sent 284 bytes to
maat Mar  1 14:24:41 glenda sent 349 bytes to
maat Mar  1 14:24:43 glenda sent 351 bytes to

Here is /tmp/mail-hell.txt

cpu% tail /tmp/mail-hell.txt
"fd from sender: local!glenda"
"sender: glenda"
"addr: net!"
Tue Mar 1 15:09:24 PST 2022
"fd from sender: local!glenda"
"sender: glenda"
"addr: net!"

Also note I used You get about 3-5 tests that you can do.

I spent the extra money to use it for 30 day it only cost $11. It was worth it as a last resort.

echo hello | mail -s foobar

Eventually this mail will show up but it still gets caught by spam assassin.

You need to really run acme Mail client.

You should add upas/fs to $home/lib/profile and do not put -n like in the examples. You will be using the default mailbox in /mail/fs/mbox. Note it doesn't exist. Upas writes to it when you send a message.

You can tail -f /sys/log/runq and watch the messages as they are created in /mail/queue before they are sent. In /mail/queue several files are created with a letter and pid I think. C.1234 D.1234 and E.1324. It's really different parts of the message. If the mail leaves the files are deleted and only L.mbox remains. If it doesn't the files stay and stack up.

When you run acme with Mail you should create a real message with a real subject and a body larger than one word. Perhaps a sentence of multiple lines. You will get a higher score in Nothing more than 9/10 because we don't use DKIM.

I think thats about that. There are other configurations that you can find on the FQA online version at in section 7. The list server can be super helpful.

I have received other example configurations that have proved helpful but really you need to read the following man pages

Whatever is missing from FQA will be found in these man pages.

To post a comment you need to login first.