Author: Matthew J. Salerno
For Gentoo Linux: http://www.gentoo.org - but generic enough for most.
This has been in the planning for quite some time, but I just recently got the time and equipment to get it started. Here are my notes so far. I do not cover every step along this process, most of these programs come with well written README or INSTALL files that should not be overlooked. I am very new to postfix, so if anyone spots somthing that should be changed, please post it.
This is without a doubt the easiest virtual mail server I have ever setup.
postfix→MailScanner→postfix→DBMail
Minimum recommended use flags: sasl mysql pam apache2 innodb ssl postfix crypt
If you updated any of your use flags, try the following command to see what might need to be rebuild with the new libraries # emerge -N world –deep -pv
Here are the packages I am currently using:
You have the option to use either just use SASL or SASL with pam_mysql. Completely your option.
If you choose just to use sasl, then you will need to emerge dev-libs/cyrus-sasl >= 2.1.20-r2
Which is currently masked. I just used:
ACCEPT_KEYWORDS=”~x86” emerge -v cyrus-sasl
If you don't want to emerge a masked package and you want to go the other route, then you will need
I used the MailScanner ebuild from http://bugs.gentoo.org/show_bug.cgi?id=36060 I know that there is a dbmail ebuild, but I built it from source - http://www.dbmail.org/
I configured postfix to run in the chroot'd env by executing:
/usr/share/doc/postfix-2.1.5-r2/examples/chroot-setup/LINUX2
I also had to change the following line in the master.cf
smtp inet n - - - - smtpd
All I did was replace the second “n” with a ”-”. This tells postfix to run in a chroot.
I got postfix working before I made any of the following changes. Mail in and out with no problems. The postfix website http://www.postfix.org/documentation.html has lots of great documentation. If you are new to postfix, like me, I strongly recommend going through the docs.
Next, I setup MailScanner. Make sure postfix is in your use flags! I put it in my portage_overlay, and emerg'd it. Currently, it setups up 2 init scripts, MailScanner and MailScanner-mta. Due to my configuration, I don't start the MailScanner-mta service and I comment out MailScanner-mta in the /etc/init.d/MailScanner:
depend() { need net # MailScanner-mta after postfix use logger dns }
In the /etc/MailScanner/MailScanner.conf, I only changed some basic settings. (setting the Queue paths is required!): There are many more options to set, but I just wanted to get things working first. Many of those options are just set so that I know that MailScanner is working. Read through the file, it is well commented.
Incoming Queue Dir = /var/spool/postfix/hold Outgoing Queue Dir = /var/spool/postfix/incoming Always Include SpamAssassin Report = yes Sign Clean Messages = yes Use SpamAssassin = yes
/etc/mail/spamassassin/local.cf:
rewrite_header Subject *****SPAM***** bayes_sql_override_username "global" bayes_store_module Mail::SpamAssassin::BayesStore::SQL bayes_sql_dsn DBI:mysql:spamassassin:localhost bayes_sql_username bayesdb bayes_sql_password mypassword use_bayes 1 use_bayes_rules 1 bayes_auto_learn 1 required_hits 5.5 report_safe 2 use_terse_report 1 dns_available yes skip_rbl_checks 1 use_razor2 1 use_pyzor 1 use_dcc 1 ok_languages all ok_locales all
For spamassassin, I imported my old bayes_db into my SQL database and could check connectivity by just executing:
sa-learn –dump magic -D
At this point, you should be able to start postfix and mailscanner.
/etc/init.d/postfix start
/etc/init.d/MailScanner start
Send an e-mail to an external account
# echo Test | mutt me@foo.yahoo.com
When you receive the e-mail, check the headers for MailScanner entries.
In order to get SASL w/ TLS working with the chroot'd Postfix, I added the following lines to my /etc/fstab:
/var/lib/sasl2 /var/spool/postfix/var/lib/sasl2 bind bind 0 0
/var/run/mysqld /var/spool/postfix/var/run/mysqld bind bind 0 0
Of course I created the /var/spool/postfix/var/lib/sasl2 and the /var/spool/postfix/var/run/mysqld directories first
I also generated my own certs using:
cd /etc/ssl/misc/ perl CA.pl -newca perl CA.pl -newreq perl CA.pl -sign
And then copying them to /etc/postfix/ssl/
These lines will allow postfix to access the mysql and sasl sockets from the chroot.
For my master.cf, I added the below line under the line for smtp:
dbmail-lmtp unix - - n - - lmtp
This is to tell postfix to hand the mail over to dbmail.
Current main.cf
queue_directory = /var/spool/postfix command_directory = /usr/sbin daemon_directory = /usr/lib/postfix mail_owner = postfix sendmail_path = /usr/sbin/sendmail newaliases_path = /usr/bin/newaliases mailq_path = /usr/bin/mailq setgid_group = postdrop html_directory = no manpage_directory = /usr/share/man sample_directory = /etc/postfix readme_directory = /usr/share/doc/postfix-2.1.5-r2/readme debug_peer_level = 2 debug_peer_list = 127.0.0.1 debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin xxgdb $daemon_directory/$process_name $process_id & sleep 5 # SASL smtpd_sasl_auth_enable = yes smtpd_sasl_security_options = noanonymous smtpd_sasl_local_domain = broken_sasl_auth_clients = yes # TLS smtpd_tls_auth_only = yes smtp_use_tls = yes smtpd_use_tls = yes smtp_tls_note_starttls_offer = yes smtpd_tls_key_file = /etc/postfix/ssl/ozone.key smtpd_tls_cert_file = /etc/postfix/ssl/ozone.crt smtpd_tls_CAfile = /etc/postfix/ssl/ozone.pem smtpd_tls_loglevel = 1 smtpd_tls_received_header = yes smtpd_tls_session_cache_timeout = 3600s tls_random_source = dev:/dev/urandom mynetworks_style = subnet mynetworks = 127.0.0.0/8 alias_database = hash:/etc/mail/aliases alias_maps = hash:/etc/mail/aliases # Server header_checks = regexp:/etc/postfix/header_checks myhostname = foo.bar mydomain = foo.bar myorigin = $mydomain mydestination = localhost, foo.bar unknown_local_recipient_reject_code = 550 virtual_transport = dbmail-lmtp:localhost:24 virtual_mailbox_domains = mysql:/etc/postfix/virtual-domains.cf virtual_mailbox_maps = mysql:/etc/postfix/virtual_aliases.cf mysql:/etc/postfix/valiasdom.cf smtpd_recipient_restrictions = reject_invalid_hostname, reject_non_fqdn_recipient, reject_non_fqdn_sender, reject_unauth_pipelining, reject_unknown_recipient_domain, reject_unknown_sender_domain, permit_mx_backup, permit_mynetworks, permit_sasl_authenticated, check_relay_domains, permit
/etc/postfix/header_checks:
/^Received:/ HOLD
/etc/postfix/virtual-domains.cf:
user = dbmail password = password dbname = dbmail table = dbmail_vdomains select_field = domain where_field = domain
/etc/postfix/virtual_aliases.cf:
user = dbmail password = password hosts = localhost dbname = dbmail table = dbmail_aliases select_field = alias where_field = alias
/etc/postfix/valiasdom.cf:
user = dbmail password = password dbname = dbmail table = dbmail_vdomains select_field = concat( '@', pridomain ) where_field = concat( '@', domain ) additional_conditions = and pridomain is not NULL
Table structure for table 'dbmail_vdomains'
Field | Type | Null | Key | Default | Extra |
id | int(7) | PRI | NULL | auto_increment | |
domain | varchar(40) | UNI | |||
comment | varchar(40) | YES | NULL | ||
pridomain | varchar(40) | YES | NULL |
id domain comment pridomain 1 foo.com Primary domain NULL 2 bar.com Another domain foo.com
SQL to create table 'dbmail_vdomains':
DROP TABLE IF EXISTS `dbmail_vdomains`; CREATE TABLE IF NOT EXISTS `dbmail_vdomains` ( `id` int(7) NOT NULL auto_increment, `domain` varchar(40) NOT NULL default '', `comment` varchar(40) default NULL, `pridomain` varchar(40) default NULL, PRIMARY KEY (`id`), UNIQUE KEY `domain` (`domain`), ) TYPE=InnoDB AUTO_INCREMENT=1 ;
Then you can populate the table with:
For Primary domain:
INSERT INTO `dbmail_vdomains` (`domain`, `comment`, `pridomain`) VALUES(“pridom.com”, “Primary Domain”, NULL);
For Secondary domain:
INSERT INTO `dbmail_vdomains` (`domain`, `comment`, `pridomain`) VALUES(“secdom.com”, “Primary Domain”, “pridom.com);
Download the DBMail source and unpack it. Read through the README and INSTALL and the INSTALL.postfix for better instructions. You will need to copy the given dbmail.conf to /etc/ and make some changes. The only changes I made were for the database connection.
/etc/dbmail.conf:
[DBMAIL] host=localhost sqlport=3306 sqlsocket=/var/run/mysqld/mysqld.sock user=dbmail pass=mypassword db=dbmail POSTMASTER=postmaster@foo.com TRACE_LEVEL=1 [SMTP] SENDMAIL=/usr/sbin/sendmail AUTO_NOTIFY=no AUTO_REPLY=no TRACE_LEVEL=1 [LMTP] EFFECTIVE_USER=nobody EFFECTIVE_GROUP=nogroup BINDIP=127.0.0.1 PORT=24 NCHILDREN=20 MAXCHILDREN=15 MINSPARECHILDREN=2 MAXSPARECHILDREN=4 MAXCONNECTS=10000 TIMEOUT=300 RESOLVE_IP=yes TRACE_LEVEL=1 MAX_ERRORS=500 [POP] EFFECTIVE_USER=nobody EFFECTIVE_GROUP=nogroup BINDIP=* PORT=110 NCHILDREN=30 MAXCHILDREN=200 MINSPARECHILDREN=2 MAXSPARECHILDREN=4 MAXCONNECTS=10000 TIMEOUT=300 RESOLVE_IP=yes POP_BEFORE_SMTP=no TRACE_LEVEL=1 [IMAP] EFFECTIVE_USER=nobody EFFECTIVE_GROUP=nogroup BINDIP=* PORT=143 NCHILDREN=5 MAXCHILDREN=100 MINSPARECHILDREN=2 MAXSPARECHILDREN=4 MAXCONNECTS=10000 TIMEOUT=4000 RESOLVE_IP=yes IMAP_BEFORE_SMTP=no TRACE_LEVEL=1
I got the init scripts from the ebuild
/etc/conf.d/saslauthd:
SASLAUTHD_OPTS="" SASLAUTHD_OPTS="${SASLAUTH_MECH} -a pam -r"
<Just SASL> If you plan on using just SASL: This will allow you to authenticate your through your SMTP server using: crypt, plaintext, md5 /etc/sasl2/smtpd.conf:
pwcheck_method: auxprop auxprop_plugin: sql allowanonymouslogin: no allowplaintext: yes mech_list: PLAIN LOGIN srp_mda: md5 srvtab: /dev/null opiekeys: /dev/null password_format: crypt sql_user: dbmail sql_passwd: mypassword sql_hostnames: localhost sql_database: dbmail sql_select: SELECT passwd FROM dbmail_users WHERE userid = '%u@%r' log_level: 10 sql_verbose: yes
</Just SASL>
<SASL with pam_mysql> If you plan on using SASL with pam_mysql: /etc/pam.d/smtp: This will allow you to authenticate your through your SMTP server using: crypt, plaintext, md5 Watch out for the line wrap. When you create the smtp file, there should only be 2 lines.
auth sufficient pam_mysql.so user=dbmail passwd=password host=127.0.0.1 db=dbmail table=dbmail_users usercolumn=userid passwdcolumn=passwd crypt=1 account required pam_mysql.so user=dbmail passwd=password host=127.0.0.1 db=dbmail table=sbmail_users usercolumn=userid passwdcolumn=passwd crypt=1
/etc/sasl2/smtpd.conf:
pwcheck_method:saslauthd mech_list: plain login
</SASL with pam_mysql>
/etc/init.d/dbmail-lmtpd:
#!/sbin/runscript # # chkconfig: - 91 35 # description: Starts and stops the dbmail-lmtpd daemon # PROGRAM=dbmail-lmtpd BIN_DIR=/usr/local/sbin PID_DIR=/var/run PID=pid # Where is the dbmail.conf file located? CONFIG=/etc/dbmail.conf # opts="${opts} reload" depend() { need net # This won't cause a hard failure if neither is installed, however. use mysql after mysql mta } initService() { # Avoid using root's TMPDIR unset TMPDIR # Check that config file exists. [ -f $CONFIG ] || exit 0 RETVAL=0 } start() { initService ebegin "Starting DBMail LMTP daemon ($PROGRAM)" start-stop-daemon --start --quiet \ --pidfile $PID_DIR/$PROGRAM.$PID \ --exec $BIN_DIR/$PROGRAM \ --name $PROGRAM \ -- -f $CONFIG -p $PID_DIR/$PROGRAM.$PID 2>&1 eend $? } stop() { initService ebegin "Stopping DBMail LMTP daemon ($PROGRAM)" start-stop-daemon --stop --quiet --retry 5 \ --pidfile $PID_DIR/$PROGRAM.$PID eend $? }
/etc/init.d/dbmail-pop3d:
#!/sbin/runscript # # chkconfig: - 91 35 # description: Starts and stops the dbmail-pop3d daemon # PROGRAM=dbmail-pop3d BIN_DIR=/usr/local/sbin PID_DIR=/var/run PID=pid # Where is the dbmail.conf file located? CONFIG=/etc/dbmail.conf # opts="${opts} reload" depend() { need net # This won't cause a hard failure if neither is installed, however. use mysql use pgsql after mta } initService() { # Avoid using root's TMPDIR unset TMPDIR # Check that config file exists. [ -f $CONFIG ] || exit 0 RETVAL=0 } start() { initService ebegin "Starting DBMail POP3 daemon ($PROGRAM)" start-stop-daemon --start --quiet \ --pidfile $PID_DIR/$PROGRAM.$PID \ --exec $BIN_DIR/$PROGRAM \ --name $PROGRAM \ -- -f $CONFIG -p $PID_DIR/$PROGRAM.$PID 2>&1 eend $? } stop() { initService ebegin "Stopping DBMail POP3 daemon ($PROGRAM)" start-stop-daemon --stop --quiet --retry 5 \ --pidfile $PID_DIR/$PROGRAM.$PID eend $? }
/etc/init.d/dbmail-imapd:
#!/sbin/runscript # # chkconfig: - 91 35 # description: Starts and stops the dbmail-imapd daemon # PROGRAM=dbmail-imapd BIN_DIR=/usr/local/sbin PID_DIR=/var/run PID=pid # Where is the dbmail.conf file located? CONFIG=/etc/dbmail.conf # opts="${opts} reload" depend() { need net # This won't cause a hard failure if neither is installed, however. use mysql use pgsql after mta } initService() { # Avoid using root's TMPDIR unset TMPDIR # Check that config file exists. [ -f $CONFIG ] || exit 0 RETVAL=0 } start() { initService ebegin "Starting DBMail IMAP daemon ($PROGRAM)" start-stop-daemon --start --quiet \ --pidfile $PID_DIR/$PROGRAM.$PID \ --exec $BIN_DIR/$PROGRAM \ --name $PROGRAM \ -- -f $CONFIG -p $PID_DIR/$PROGRAM.$PID 2>&1 eend $? } stop() { initService ebegin "Stopping DBMail IMAP daemon ($PROGRAM)" start-stop-daemon --stop --quiet --retry 5 \ --pidfile $PID_DIR/$PROGRAM.$PID eend $? }
Currently with this setup, my mail server is working great. Now all I have to do is setup mysql to listen on an external ip address, setup another server with almost the same settings, setup sql replication and I should have some pretty reliable and redundant mail servers. Of course the switchover won't be automatic, yet…
Good luck
Readers note, perhaps this would be better served by an email to the author; but im a bit lazy tonight – kerpal2343 at domain yahoo.com – The primary and seconday domain portion I feel is a bitt off from a default setup, as its not in the database and I am a DBMA web user (more so, im setting up the system to be so for a client). I could not tell from this article how this affects the system, im left to assume that this allows one to have a postmaster@organization.com mapped to an organization.net address or silly.com address by default.. let me know if I am fool with this thought. If not.. umm please add a description up there – End –