Categories

Categories

Archives

Postfix

w00t! I finally got the Postfix MTA running on my home network! I was using qmail on my old faithful Slackware 9.0 router, decided against using it again since it was a bit complex for my needs. Postfix is simple, very configurable, and lets me use a MySQL database for all of my virtual e-mail clients!

Unfortunately, like most Linux MTA’s, documentation and tutorials that somebody with no formal knowledge of e-mail servers are a bit hard to find. After reading nearly all of the Postfix docs and several random tutorials and howto’s, I finally got a setup that works perfectly for my needs. And I’ll be adding server-side spam checking in the future, too!

Basically, I installed the following on my Slackware 11.0 server, which is a dual-processor, dual-core Xeon 3.6GHz system with hyper-threading, 4GB RAM, 1TB+ of HD space, and lots of little goodies:

Below are very brief notes of how I installed it. I already installed MySQL 5, PHP5, and Apache2 a while back so they were already in working order. I didn’t want quotas (yes, I have plenty of space for my 3 users), and don’t care (as of yet) about SSL.

Preparations

Create a MySQL database for postfix give privileges in the database for a postfix user. I set my database up like this, but you’ll (and I’ll) probably want to add some additional fields, like IDs, and relationship fields, like Domain, to be shared between the tables (make queries from a management script, for example, much easier and logical).

Table structure for table alias

Field

Type

Null

Default

address

varchar(255)

Yes

goto

text

Yes

active

tinyint(1)

Yes

1

I set a few aliases like this:

address goto active
postmaster@11h.net joe123@11h.net 1
logs@11h.net joe123@11h.net 1
@myserversname.11h.net @11h.net 1

That last one will keep the username the same changing only the virtual domain it is redirected to. The first two simply redirect postmaster and logs to the e-mail joe123@11h.net.

Table structure for table domain

Field

Type

Null

Default

domain

varchar(255)

Yes

active

tinyint(1)

Yes

1

My 2 domains are merely “11h.net” and “myserversname.11h.net”. If you host any other domains, add them here.

Table structure for table mailbox

Field

Type

Null

Default

username

varchar(255)

Yes

password

varchar(255)

Yes

name

varchar(255)

Yes

maildir

varchar(255)

Yes

active

tinyint(1)

Yes

1

This one gets a little more complicated because of the password field. Here’s an example for “joe123”:

username: joe123@11h.net

password: $1$WmD/q3et$Hiz97VoENZ0q2Lm49V3ax.

name: Joe User

maildir: joe123@11h.net/

active: 1

First, the username is the full e-mail address.

Second, the password is in hashed form. For the most part, Courier-IMAP can recognize these types of passwords, depending on what they look like in the database (from man pages):

  • A traditional triple-DES crypted password, or a MD5+salt-hashed password, as used in Linux.
  • “{MD5}” followed by a base64-encoded MD5 hash of the password.
  • “{SHA}” followed by a base64-encoded SHA1 hash of the password.

In my case, since I was “upgrading” from qmail on one server to postfix on this server, I simply copied the users passwords on the old system from /etc/shadow. For new users, its easier to just use MySQL’s ENCRYPT function. The password in my example above is from /etc/shadow for an old user, it is the hash of “example”.

Third, maildir is the directory under /var/spool/postfix/virtual where the user’s e-mail is stored. This must end with a slash for it to be in “Maildir” format. I simply use the e-mail address, others may wish to separate them into domains. For example: “11h.net/joe123/”.

Finally, 1 in active indicates this e-mail can receive mail…

Table structure for table transport

Field

Type

Null

Default

domain

varchar(255)

Yes

transport

varchar(128)

Yes

I also created a user account and group “postfix” (for the postfix daemon’s to run as), a group (no associated user) named “postdrop”, and a user account and group “vmail” (the owner of the Maildirs in /var/spool/postfix/virtual/).

Courier-Auth

Did a usual install according to the instructions. The ./configure script auto-detected MySQL and whatever else it needed. It installed to the /usr/local prefix and stuck its configuration files in /usr/local/etc/authlib (don’t forget to rename the copied files so as to lose the .dist extension). Its daemon was put in /usr/local/sbin, but I start it via the scripts it put in /usr/local/libexec/courier-authlib.

In the authdaemonrc configuration file, I just set the authmodulelist to only include “authmysql”. I don’t want my local system users to have e-mail; only virtual addresses stored in the mysql table, so this works out for me.

In authmysqlrc, I basically set it up with these settings:

MYSQL_SERVER localhost
MYSQL_USERNAME postfix
MYSQL_PASSWORD password
MYSQL_DATABASE postfix
MYSQL_USER_TABLE mailbox
MYSQL_CRYPT_PWFIELD password
DEFAULT_DOMAIN 11h.net
MYSQL_UID_FIELD ‘1006’
MYSQL_GID_FIELD ‘107’
MYSQL_LOGIN_FIELD username
MYSQL_HOME_FIELD ‘/var/spool/postfix/virtual’
MYSQL_NAME_FIELD name
MYSQL_MAILDIR_FIELD maildir

# MYSQL_CLEAR_PWFIELD clear


Essentially, the way this configuration file works, for the fields, is it wants the name of the Database field. If the entry is “static” (i.e. don’t look it up in the database, but specify the value directly in the file) it is enclosed in single-quotes (”). So the authdaemon will obtain the Mailbox information from the “mailbox” table in the “postfix” SQL database. Within that table, the user’s hashed (encrypted) password in the “password” field, the user’s username/e-mail address in the “username” field, the user’s real name in the “name” field, and the user’s Maildir directory in the filesystem in the “maildir” field. The UID and GUI on my system are 1006 and 107, which are for the “vmail” system user account and group. This is who the maildir directory is owned by — it shouldn’t be readable by anybody except this user.

The default domain is specified so the user’s may log in as “joe123” instead of having to specify “joe123@11h.net”. I also left out the clear password field since I don’t consider it good practice to store plain-text user passwords inside a database (or anywhere for that matter). Note that this does, however, sacrifice the ability to use CRAM-MD5 Authentication.

Courier-IMAP

Did the usual install in accordance w/ the instructions… well almost, one of the tutorials I read said to compile it like this:

$ ./configure –prefix=/usr/local/courier –enable-unicode

So it stuck everything in its own directory. How nice. The daemons are started from /usr/local/courier/libexec, and the configurations in /usr/local/courier/etc. Don’t forget to rename the default config files as you had to do with the authdaemon.

In the etc dir, Peek thru “imapd” and make sure it all looks good. Options to pay attention are, as I did:

DEFDOMAIN=”@11h.net”
IMAP_CAPABILITY=”IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE”
IMAP_IDLE_TIMEOUT=5
IMAP_EMPTYTRASH=Trash:90
IMAP_MOVE_EXPUNGE_TO_TRASH=1
IMAPDSTART=YES

On the capabilities part, you’ll want to use the other one if you store a clear-text password and want CRAM-MD5 authentication. I didn’t care, so I left it as that. Also, configure pop3d if you want that, too.

Postfix

I’m sure I did a pretty basic installation, which picked up on MySQL and everything I needed. Configuring it was the most difficult for me since I had (well still have) no idea how this MTA even works.

Once installed, at least the way I set it up, the configuration files are in /etc/postfix, and mail spool stuff in /var/spool/postfix. I created a directory in there called “virtual” which is where all the e-mail goes.

First, I renamed all the config files to get rid of the “dist” or “.default” extensions. Then I edited “main.cf” to contain something like this:

queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
mail_owner = postfix
myhostname = mail.11h.net
mydomain = 11h.net
myorigin = $mydomain
local_recipient_maps = $virtual_mailbox_maps
unknown_local_recipient_reject_code = 550
mynetworks_style = host
mynetworks = 10.0.0.0/16, 127.0.0.0/8
relayhost = [my.isps.mail.server]
home_mailbox = Maildir/
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
xxgdb $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail
newaliases_path = /usr/bin/newaliases
mailq_path = /usr/bin/mailq
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/local/man
sample_directory = /etc/postfix
readme_directory = no
local_transport = virtual:11h.net
transport_maps = mysql:/etc/postfix/mysql_transport_maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_gid_maps = static:107
virtual_mailbox_base = /var/spool/postfix/virtual
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_limit = 1073741824
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_minimum_uid = 1006
virtual_transport = virtual
virtual_uid_maps = static:1006
message_size_limit = 268435456

Phew, the most important ones are at the bottom… note that I set my “local” transport to always assume a virtual transport with @11h.net as the defaut domain (so e-mails to “joe123” and “joe123@11h.net” both go to joe123@11h.net rather than attempt the linux system account “joe123”). I also set obsenly high message size limits. Make sure to set the virtual_gid_maps, virtual_uid_maps, and virtual_minimum_uid to the user/group ID of “vmail”, as they’re used to write to the Maildir directories to deliver mail.

The extra files I created are these:

mysql_relay_domains_maps.cf
user = postfix
password = password
hosts = localhost
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = ‘1’
mysql_transport_maps.cf
user=postfix
password=
password
dbname=postfix
hosts=localhost
table=transport
select_field=transport
where_field=domain
mysql_virtual_alias_maps.cf
user = postfix
password =
password
hosts = localhost
dbname = postfix
table = alias
select_field = goto
where_field = address
mysql_virtual_domains_maps.cf
user = postfix
password =
password
hosts = localhost
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and active = ‘1’
mysql_virtual_mailbox_maps.cf
user = postfix
password =
password
hosts = localhost
dbname = postfix
table = mailbox
select_field = maildir
where_field = username
additional_conditions = and active = ‘1’

Start and stop the daemon with “postfix” commands… i.e.:

# postfix start
# postfix reload
# postfix stop
# postfix help

And check /var/log/maillog for any problems!

RoundCube

This web-mail front end is very simple to use, has just enough features to make me happy, has a very nice ajaxy interface, and fully supports IMAP, which means I can keep my gigs of e-mail on my server and access them from my Windows IMAP client, a Linux IMAP client, or via RoundCube via the web interface! Very cool. I just created a VHOST in apache and dumped the latest SVN copy into it (its PHP). Its easy to configure and can use multiple IMAP servers, local or remote. Read the docs and play with their online demo.

Final Notes

Postfix will create the “Maildir” structure under /var/spool/postfix/virtual automatically when the user’s first e-mail is delivered. Until then, Courier-IMAP will not allow the user to login. Roundcube will also just hang and eventually time out with an access deined message. For simplicity, I just send a dummy e-mail to the user. Transferring existing users from qmail was a peice of cake — just tarred the user’s Maildir on the old server, copied it to the new server, and extracted it (w/o the Maildir part) to their virtual directory and changed the owner to vmail:vmail.

I know I left out some very important details, as this was supposed to be brief. Remember: read the man pages… and probably buy a book on it so you can figure out what all those new-fangled terms mean!

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

  

  

  

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.