Virtual mail server using Postfix, Courier and PostfixAdmin
| Please format this article according to the Style Guidelines and Wikification suggestions, then remove this notice {{Wikify}} from the article.
Reason(s): This article is a port from the old wiki, located here: http://www.gentoo-wiki.info/HOWTO_Setup_a_Virtual_Postfix/Courier_Mail_System_with_PostfixAdmin, please fix any errors and remove this |
Contents |
[edit] Introduction
I recently moved my original mail system, built using the Gentoo Virtual How-to, over to a PostfixAdmin run system. Additionally I took this time to add Postgrey and switch to encrypted passwords using Courier's new authlib, which I'll detail as well.
Virtual Mailhosting System with Postfix Guide
[edit] Notes From the Author
kashani (2007.04.17): I just ran through this how-to on my new vps server so it's pretty fresh. Should be updating this over the next week.
kashani (2008.06.25): A few updates, but I haven't really looked to hard at what is new in Postfixadmin 2.2
kashani (2008.08.21): Added syslog-ng stuff to split mail out, added mysql account creation stuff a couple of weeks ago.
[edit] Notes From Users
Put things you'd like me to fix or comments here
Bigun - Possibly some code on how to setup courier-imapd-ssl and courier-pop3d-ssl, certificates and all
[edit] Why PostfixAdmin
PostfixAdmin provides a nice front-end for a Postfix/Courier based virtual mail server. As super-admin you can create domain admins, create their domains, own the domains to the domain admin, and then you can go back to reading the Gentoo forums rather than creating users, changing passwords, or deleting accounts.
(...and managing your email system with PHPMyadmin sucks.)
[edit] Which Packages
This HowTo assumes you have the following prerequisites:
- dev-db/mysql-5.0*
- dev-lang/php-5.2*
- dev-libs/cyrus-sasl-2.1*
- mail-mta/postfix-2.5*
- net-mail/courier-imap-4.5*
- net-libs/courier-authlib-0.62*
- www-apps/postfixadmin-2.2*
- www-servers/apache-2.2*
[edit] Default Settings
The system we're going to build will have the settings below. You can change any of these to reflect your own system.
- All mail is in /var/vmail/
- All mail is owned by user postfix:postfix
- The database is postfix_db
- The database user is named postfix_user
- The database password is “postfix_pass” — you should change this to something different, use the app-admin/pwgen utility to generate a good password
[edit] Portage
These are the Use flags that should be set.
dev-db/mysql community perl ssl dev-lang/php apache2 bzip2 crypt ctype curl filter ftp gd gdbm imap json mysql mysqli nls pcre pic posix reflection session spl ssl unicode xml xsl zlib dev-libs/cyrus-sasl -berkdb authdaemond crypt gdbm mysql ssl urandom mail-mta/postfix mysql ssl sasl vda net-mail/courier-imap fam gdbm nls net-libs/courier-authlib crypt gdbm mysql www-apps/postfixadmin mysql vhosts www-servers/apache ssl
If any of them are in your USE variable in the /etc/make.conf file, you can safely remove it from the list. If more USE flags than the above are showing up that fine too. Most of the daemons above will have pam ipv6 or others that appear.
We're going to slave SASL off Courier-authlib instead of having it talk directly to the database. This allows us to use encrypted passwords and seems to work better as well. However there have been some weird authlib problems in recent updates so watch your upgrades.
Some webmail clients require php to be compiled with Unicode support, so just enable it to be sure, you may be needing it eventually.
[edit] Installing and configuring the packages
[edit] MySQL
There is a great guide here for installing MySQL, so I suggest you read it too, so you don't miss anything: MySQL Startup Guide
[edit] Installation
First install the package
Once that is done, setup the root user in mysql
Now you need install library pam_mysql.so. Do it typing:
The last thing that needs doing, is adding mysql to the default runlevel, so it starts when the server starts
That is really all that is needed to install mysql.
[edit] Configuration
Now we need to create the postfix database in mysql, and create the user to login with
create database postfix_db; GRANT ALL PRIVILEGES ON postfix_db.* TO postfix_user@localhost IDENTIFIED BY 'postfix_pass'; flush privileges;
By default MySQL binds only to 127.0.0.1, aka localhost, and will not be accessible from outside your server. In order to let it bind to the normal ethernet interface you need to comment out the bind-address line in /etc/mysql/my.cnf. You will also need to change your GRANT line to allow access from more than localhost.
[edit] Apache2
For a guide on how to install and configure apache, please read the Apache2 article.
Once Apache2 is installed, add it to the default runlevel like you did with mysql
[edit] PHP
Now that you have Apache installed, installing PHP is really just running this command
Once that is done, edit /etc/conf.d/apache2 and add -D PHP5 to the APACHE2_OPTS variable
APACHE2_OPTS="-D DEFAULT_VHOST -D INFO -D LANGUAGE -D SSL -D SSL_DEFAULT_VHOST -D PHP5"
[edit] Cyrus-SASL
To install Cyrus-SASL, simply emerge it
Thats it, there isn't really any configuration to be done for this package, so just add it to the default runlevel
SMTP Authentication settings:
pwcheck_method:authdaemond mech_list:PLAIN LOGIN authdaemond_path:/var/lib/courier/authdaemon/socket
[edit] Postfix
Postfix is the SMTP server, that handles all the incoming emails
[edit] Installation
First verify that you have all the proper USE flags enabled. A pretend should look like this.
mail-mta/postfix-2.5.6 USE="ipv6 mysql pam sasl ssl vda -cdb
-dovecot-sasl -hardened -ldap -mailwrapper -mbox -nis -postgres
(-selinux)"
Now install Postfix
Once Postfix is installed you'll need to add local aliases and run /usr/bin/newaliases so Postfix will start and be happy. Postfix does not deliver mail to root so you'll want to point the mail for root to some other user or mail account. Edit the /etc/mail/aliases file, where you uncomment and fill out the root and operator lines with your own login name:
# Basic system aliases -- these MUST be present. MAILER-DAEMON: postmaster postmaster: root # General redirections for pseudo accounts. adm: root bin: root daemon: root exim: root lp: root mail: root named: root nobody: root postfix: root # Well-known aliases -- these should be filled in! root: yourusername operator: yourusername # Standard RFC2142 aliases abuse: postmaster ftp: root hostmaster: root news: usenet noc: root security: root usenet: root uucp: root webmaster: root www: webmaster # trap decode to catch security attacks # decode: /dev/null
Now run the newaliases utility, to regenerate the aliases database file
Now add postfix to the default runlevel
And start it
[edit] Configuration
Now you need to change the /etc/postfix/main.cf and merge the changes below into it
# local settings. Remember any domain you want treated as virtual
# can not be listed in either relay_domains or mydestination.
myhostname = mail01.domain.com
mydomain = domain.com
myorigin = $myhostname
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost
mynetworks_style = subnet
mynetworks = 127.0.0.0/8
# attachment filtering, optional
#mime_header_checks = regexp:/etc/postfix/mime_header_checks.regexp
# Size settings, optional
#message_size_limit= 112400000
#mailbox_size_limit = 224800000
# SASL settings
broken_sasl_auth_clients = yes
smtpd_sasl_auth_enable = yes
smtpd_sasl_authenticated_header = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
# TLS stuff - Enable if you want to use SMTP over SSL
smtpd_use_tls = no
#smtpd_tls_key_file = /etc/postfix/newkey.pem
#smtpd_tls_cert_file = /etc/postfix/newcert.pem
#smtpd_tls_CAfile = /etc/postfix/cacert.pem
#smtpd_tls_loglevel = 3 #### change to 0 after everything works
#smtpd_tls_received_header = yes
#smtpd_tls_session_cache_timeout = 3600s
#tls_random_source = dev:/dev/urandom
# transport Stuff, optional
#transport_maps = hash:/etc/postfix/transport
#relay_domains = proxy:mysql:/etc/postfix/mysql_relay_domains_maps.cf
# virtual stuff. We're going to punt and make all virtual mail users use the same UID:GID of Postfix.
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_gid_maps = static:207
virtual_mailbox_base = /var/vmail/
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_limit = 112400000
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_minimum_uid = 207
virtual_transport = virtual
virtual_uid_maps = static:207
mailbox_transport = virtual
smtpd_recipient_restrictions =
#reject_non_fqdn_recipient
#reject_non_fqdn_sender
reject_unknown_recipient_domain
permit_mynetworks
permit_sasl_authenticated
#check_policy_service inet:127.0.0.1:2501 #needed for sqlgrey and optional
reject_unauth_destination
permit
# additional spam fighting checks, optional
#smtpd_helo_restrictions = reject_unknown_helo_hostname
#smtpd_sender_restrictions = reject_unknown_sender_domain
#smtpd_data_restrictions = reject_unauth_pipelining
Then create the following files in /etc/postfix
# you only need this if you plan to act as a backup mx for various domains. user = postfix_user password = postfix_pass hosts = localhost dbname = postfix_db query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '1' AND active = '1'
user = postfix_user password = postfix_pass hosts = localhost dbname = postfix_db query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
user = postfix_user password = postfix_pass hosts = localhost dbname = postfix_db query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
user = postfix_user password = postfix_pass hosts = localhost dbname = postfix_db query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
/^\s*Content-(Disposition|Type).*name\s*=\s*"?(.+\.(ad[ep]|asd|ba[st]|c[ho]m|cmd|cpl|crt|dbx|dll|exe |hlp|hta|in[fs]|isp|js|jse|lnk|md[etw]|ms[cipt]|nws|ocx|ops|pcd|pi|pif|prf|reg|scf|scr|sct|sh[bms]|uue |vb|vb[esx]|vxd|wab|ws[cfh]))"?\s*$/ REJECT Files attached to emails that contain or end in "$3" are prohibited on this server as they may contain viruses. The file named "$2" was rejected.
[edit] OS stuff
[edit] Directories
Now that you have Postfix installed it's time to create and chown properly our mail directory.
The directory name and location does not matter, but it's a good idea to have it in a large directory. For performance reason in a very busy server you may want to move it to another partition because the Postfix internal queues are also on /var/ and those are write heavy. Moving the main mail store to a partition on another physical disk can increase performance on a box that is struggling under I/O issues.
Owning the /var/vmail to Postfix allows Postfix to create new mail directories for new users when the first piece of mail comes in for that user. I recommend setting Postfixadmin to send a welcome message to new users to make sure their .maildir is created.
[edit] Syslog-NG configuration
Just make sure you are using >=syslog-ng-2* and you will be fine.
To be sure, check that your /etc/syslog-ng/syslog-ng.conf contains these lines
destination mail { file("/var/log/mail.log"); };
filter f_mail { facility(mail); };
filter f_messages { level(info..warn) # this line should already exist
and not facility(mail); }; # make sure this line is under the above line.
log { source(src); filter(f_mail); destination(mail); };
[edit] Courier-IMAP
Courier-IMAP is that package that contains the pop3 and imap server.
Those are the ones that are used when the user is reading the mails in their inboxes.
[edit] Installation
Again verify USE flags.
These are the packages that would be merged, in order: [ebuild N ] net-mail/courier-imap-4.4.1-r1 USE="fam gdbm ipv6 nls -berkdb -debug -gnutls (-selinux)" 0 kB Total: 1 package (1 new), Size of downloads: 0 kB
Then emerge it
Once done, add the services that you need to the default runlevel
- POP3
- IMAP
- POP3 over SSL
- IMAP over SSL
# mkpop3dcert
[edit] Configuration
For large virtual systems remember to increase per IP connections in /etc/courier-imap/imapd and any other services you plan to offer to the public. Even on a small system Thunderbird tends to cache several connections to the server. I run my personal mail servers to allow 40 connections from a single IP for IMAP. That seems to work.
This is done by changing the MAXPERIP varible to 40
MAXPERIP=40
[edit] Courier-AuthLib
Courier-AuthLib handles the authentication of the users, when they connect to imapd or pop3d to read their mail.
[edit] Installation
Again verify the use variables
These are the packages that would be merged, in order: [ebuild N ] net-libs/courier-authlib-0.61.1 USE="crypt gdbm mysql -berkdb -debug -ldap -pam -postgres -vpopmail" 0 kB Total: 1 package (1 new), Size of downloads: 0 kB
Then emerge it
And add it to the default runlevel
[edit] Configuration
First the /etc/courier/authlib/authmysqlrc file needs to be fitted to our needs
#DEFAULT_DOMAIN domain.tld MYSQL_CRYPT_PWFIELD password MYSQL_DATABASE postfix_db MYSQL_GID_FIELD '207' MYSQL_HOME_FIELD '/var/vmail' MYSQL_LOGIN_FIELD username MYSQL_MAILDIR_FIELD maildir MYSQL_NAME_FIELD name MYSQL_OPT 0 MYSQL_PASSWORD postfix_pass # Uncomment below if you want quota support. #MYSQL_QUOTA_FIELD quota MYSQL_SERVER localhost MYSQL_UID_FIELD '207' MYSQL_SOCKET /var/run/mysqld/mysqld.sock MYSQL_USERNAME postfix_user MYSQL_USER_TABLE mailbox # You can also turn off IMAP authentication when a user is # marked as inactive. Be aware that this will cause webmail auth, # smtp relay if slaved off courier-authlib, and POP3/IMAP logins to fail. #MYSQL_WHERE_CLAUSE active='1'
Then you need to edit /etc/courier/authlib/authdaemonrc and make sure authmysql is the first in the authmodulelist variable
authmodulelist="authmysql authpam"
You may need to loosen permissons on /var/lib/courier/authdaemon/socket I'd try it on your system first and if you see permission denied errors this is likely the problem.
[edit] PostfixAdmin
This section will show you how to set up PostfixAdmin. This is done first because it doesn't depend on anything else and sets up the databases that will be used by Postfix and Courier.
[edit] Virtual Host Setup
This section will install PostfixAdmin and configure the Apache virtual host. This section does not deal with configuring SSL, although it is highly recommended that you only access PostfixAdmin over SSL.
Using webapp-config, install PostfixAdmin using the following command, replacing the 2.2.1.1 with the version you're using:Pay attention to any messages that webapp-config displays and follow any instructions you're given.
PostfixAdmin will now be installed to /var/www/mailadmin.example.org/htdocs
Now you need to tell Apache about the virtual host. To do so, put the following into a new file, /etc/apache2/vhosts.d/mailadmin.example.org.conf (based on the Gentoo default virtual host). Remember to change "mailadmin.example.org" into your hostname in this file, it appears four times:
<VirtualHost *:80>
ServerName mailadmin.example.org
DocumentRoot "/var/www/mailadmin.example.org/htdocs"
<Directory "/var/www/mailadmin.example.org/htdocs">
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs/2.2/mod/core.html#options
# for more information.
Options Indexes FollowSymLinks
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
AllowOverride All
# Controls who can get stuff from this server.
Order allow,deny
Allow from all
</Directory>
<IfModule alias_module>
# Alias: Maps web paths into filesystem paths and is used to
# access content that does not live under the DocumentRoot.
# Example:
# Alias /webpath /full/filesystem/path
#
# If you include a trailing / on /webpath then the server will
# require it to be present in the URL. You will also likely
# need to provide a <Directory> section to allow access to
# the filesystem path.
# ScriptAlias: This controls which directories contain server scripts.
# ScriptAliases are essentially the same as Aliases, except that
# documents in the target directory are treated as applications and
# run by the server when requested rather than as documents sent to the
# client. The same rules about trailing "/" apply to ScriptAlias
# directives as to Alias.
ScriptAlias /cgi-bin/ "/var/www/mailadmin.example.org/cgi-bin/"
</IfModule>
<Directory "/var/www/mailadmin.example.org/cgi-bin">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
<IfModule mpm_peruser_module>
ServerEnvironment apache apache
</IfModule>
</VirtualHost>
# vim: ts=4 filetype=apache
[edit] Configuration
Open up the config.inc.php file in the postfixadmin directory. The following settings are listed in the order that they appear.
First comment out the configured setting by placing a # in front of it to tell PostfixAdmin that we've configured it. Until you do this, PostfixAdmin will not run:
Let PostfixAdmin know that we changed the config-file. Do NOT uncomment the line because login.php use the variable configured.
$CONF['configured'] = true;
Tell PostfixAdmin what web address it will be accessed with:
$CONF['postfix_admin_url'] = 'http://mailadmin.example.org/';
If your native language isn't English, you'll want to change the default_language setting. A list of language files in the languages/language.php file. For example, if you want PostfixAdmin in German:
$CONF['default_language'] = 'de';
Next set up the MySQL connection. This uses the MySQL database and user set up above. The password should be the same password you entered when creating the postfix_user MySQL user.
$CONF['database_type'] = 'mysqli';$CONF['database_host'] = 'localhost';$CONF['database_user'] = 'postfix_user';$CONF['database_password'] = 'postfix_pass';$CONF['database_name'] = 'postfix_db';$CONF['database_prefix'] = ;
You'll want to change the admin email address that PostfixAdmin uses. This is used as the From address when sending messages to new accounts.
$CONF['admin_email'] = 'postmaster@example.org';
This setup will use mailboxes stored in the format <domain>/<username>, so change the domain_path and domain_in_mailbox settings to match those below.
$CONF['domain_path'] = 'YES';$CONF['domain_in_mailbox'] = 'NO';
This setup will use quotas, so tell PostfixAdmin to turn them on.
$CONF['quota'] = 'YES';
PostfixAdmin displays a couple of customizable links. You'll probably want to change these to link to your website.
$CONF['user_footer_link'] = "http://example.org/";
$CONF['show_footer_text'] = 'YES';$CONF['footer_text'] = 'Example Webhosting';$CONF['footer_link'] = 'http://example.org/';
Finally, you can change the content of the email that is sent to new users.
$CONF['welcome_text'] = <<<EOMHi,
Welcome to your new account.EOM;
[edit] Setup
You can now complete the setup of PostfixAdmin, creating the database, by visiting the setup page. For example: http://mailadmin.example.org/setup.php
At this point you'll be asked to set up a global admin user. Follow the instructions to do so. Remember the details as you'll need them to log in later.
$CONF['emailcheck_resolve_domain']='NO';
You can now visit your PostfixAdmin install at the location you set it up. For example: http://mailadmin.example.org/
However, you should not set any domains or mailboxes up yet because Postfix and Dovecot have not been set up yet.
[edit] Sqlgrey
[edit] Why Greylist?
It's the simplest way to stop significant spam and it uses far less resources than just about any other method. I've been using sqlgrey on multiple servers and it seems to work well so that's what we'll use here.
[edit] Installation
First install the package
Now configure it with Portage system
Then run this command to set the setting in /etc/conf.d/postgrey
And finally add it to the default runlevel
[edit] Delay Time
I recommend a very small delay time as I've used above. Many webmail sites like Hotmail will attempt to delivery every thirty seconds for the first three minutes. The next retry will be fifteen minutes after the last retry. By using a very small delay you can still provide effective greylisting, but keep the total delay to a minimum.
[edit] Oddities
Here are a couple of weird issues that I ran into while installing Postfix Admin or using it.
[edit] Adding Multiple Emails to an Alias
Create an alias pointing to a single address. Now edit the alias again. You'll be able to add multiple email addresses, one per line, to the alias now.