Large-Scale Mail with Postfix, OpenLDAP and Courier

Setting up an SMTP mail server for multiple domains on a single machine with remote access via IMAP.
Creating the Directory Tree

Now that slapd is configured, it's time to start adding data to the LDAP directory. We use the command-line tools that come with OpenLDAP and create LDIF files to modify the directory.

The first step is to create a base tree structure with our root node, the hosting organization and an entry for the rootdn. Create a file called base.ldif with the following contents:

dn: dc=myhosting, dc=example
 objectClass: top
 dn: cn=Manager, dc=myhosting, dc=example
 objectClass: top
 objectClass: organizationalRole
 cn: Manager
 dn: o=hosting, dc=myhosting, dc=example
 objectClass: top
 objectClass: organization
 o: hosting

Now use ldapadd, binding as the root account, to add this LDIF:

ldapadd -x -D "cn=Manager,dc=myhosting,dc=example" \
-w secret -f base.ldif

Adding a Domain

Domains can now be added under the hosting tree. Each domain needs to have postmaster and abuse entries at minimum. To make a tree for domain1.example, create a file called domain1.example.ldif with the following contents:

dn: o=domain1.example, o=hosting, dc=myhosting,
 dc=example
objectClass: top
objectClass: organization
o: domain1.example
dn: cn=postmaster, o=domain1.example, o=hosting,
 dc=myhosting, dc=example
objectClass: top
objectClass: organizationalRole
objectClass: CourierMailAlias
cn: postmaster
mail:
maildrop: postmaster
dn: mail=abuse@domain1.example, o=domain1.example,
 o=hosting, dc=myhosting, dc=example
objectClass: top
objectClass: CourierMailAlias
mail:
maildrop: abuse

Notice that the maildrop attributes are local e-mail accounts and will forward to the postmaster and abuse accounts in /etc/aliases. There are no accounts in the postmaster role, so only the root account can create accounts at the moment. Add this domain with the following command:

ldapadd -x -D "cn=Manager,dc=myhosting,dc=example"
\
-w secret  -f domain1.example.ldif

Adding an Account

Now, let's add an account with an e-mail <user1@domain1.example>. Let's also grant this account postmaster privileges for domain1.example. Create a user1.domain1.example.ldif with the following contents:

dn: mail=user1@domain1.example, o=domain1.example,
 o=hosting, dc=myhosting, dc=example
objectClass: top
objectClass: CourierMailAccount
mail:
homeDirectory: /home/vmail/domains
uidNumber: 101
gidNumber: 101
mailbox: domain1.example/user1
dn: cn=postmaster, o=domain1.example, o=hosting,
dc=myhosting, dc=example
changetype: modify
add: roleOccupant
roleOccupant: mail=user1@domain1.example,
 o=domain1.example, o=hosting,
 dc=myhosting, dc=example

The first section adds a new entry for the account. The home directory and mailbox point to the physical mailbox on the filesystem. The uidNumber and gidNumber attributes are required but not used, so they are filled in with dummy values of 101. The second section modifies the postmaster entry by adding a roleOccupant attribute with the DN of user1@domain1.example. Let's create this account:

ldapadd -x -D "cn=Manager,dc=myhosting,dc=example"
\
-w secret -f user1.domain1.example.ldif
The account does not have a password yet, so even though it has been granted postmaster privileges, it cannot be authenticated. Use the ldappasswd command to set the initial password to user1:
ldappasswd -x -D "$DN" -w $PW -s user1 \
"mail=user1@domain1.example, o=domain1.example,
o=hosting, dc=myhosting, dc=example"
Other domains and accounts can be added with similar LDIF files. Creating LDIF files by hand can be cumbersome and error-prone. We discuss alternatives for administration later.

Postfix

We cover only the sections of Postfix that pertain to the mail hosting. To deal with other parts of Postfix setup, please visit the Postfix web page.

Download the Postfix source and untar it. You need to rebuild the Postfix Makefiles to be aware of LDAP and link against it. To do this, execute the following command:

make makefiles CCARGS="-I/usr/local/include
-DHAS_LDAP" AUXLIBS="-L/usr/local/lib -lldap
-L/usr/local/lib -llber"

At this point, follow the normal Postfix compiling and installing instructions as documented in its INSTALL and LDAP_README files.

Configuring Postfix

While configuring Postfix for this task, we are mostly concerned with /etc/postfix/main.cf. For most of the Postfix configuration, you will configure in a way that makes the most sense for your site, and you can follow the documentation contained in the Postfix source or on the Postfix web site. Here, we talk about the settings that are affected by this setup. If any of the configuration examples shown below aren't explicitly attributed to a specific file, assume they can be found in main.cf.

The transport table maps domains to message delivery transports (as specified in /etc/postfix/master.cf) and/or relay hosts. For our virtual domains, we want to map them to the virtual delivery agent that comes with Postfix. A transport table could look something like this:

domain1.example           virtual:
domain2.example           virtual:

After making your transport table in plain text, you need to make it into a binary DB file using postmap (see man postmap). At this point, tell Postfix that there is a transport table and where to find it. You also need to let Postfix know that we accept mail for those domains. This is done through the transport_maps and mydestination directives:

transport_maps = hash:/etc/postfix/transport
mydestination = $myhostname, localhost.$mydomain,
  $mydomain, $transport_maps
You can define multiple LDAP sources easily. LDAP source parameters are documented in README_FILES/LDAP_README in the Postfix source. The parameter names follow the pattern of <ldapsource>_parameter. The LDAP source name is defined by use. In main.cf, you'll need one LDAP source definition per each lookup.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

What about procmail??

Atrillanes's picture

Have I missed something in your article? Or you have just omitted the part where procmail gets into the picture?

dn of the user objects

Ahmed El Zein's picture

Hi,
Why is the dn of the users mail=user@domain,o=domain,etc? would it not make more sense to have a dn of cn=user,o=domain,etc (like you did for the postmaster)?

The only reason I can think of if to be able to search through the whole tree by email address. wouldn't it be faster to separate user and domain and just search under the o=domain? especially if you have a huge amount of users for each domain?

Re: Large-Scale Mail with Postfix, OpenLDAP and Courier

Anonymous's picture

I don't see a reply to the previous comment. I'm having a similar problem.

Given the format of the cn=postmaster,o=domain1.example..., I suspect that objectClass: organizationalRole needs to be present.

Another question, however, is why are the "mail:" attributes empty? They are required fields and the LDAP server balks at there being no entry there.

Re: Large-Scale Mail with Postfix, OpenLDAP and Courier

Anonymous's picture

Since OpenLDAP 2.2 (I don't know if earlier too) LDAP entities must have "structural" object class. Classes top, CourierMailAccount, CourierMailAlias are "auxiliary" clasess. You should add to each entity "structural" class: domain, organization, organizationalPerson, etc.
So eg.

dn: dc=myhosting, dc=example
objectClass: top

should be

dn: dc=myhosting, dc=example
objectClass: domain
dc: myhosting

You can also change those objectClasses to STRUCTURAL

Darian's picture

...by modifying authldap.schema and replacing "AUXILIARY" with "STRUCTURAL" on the CourierMailAccount, CourierMailAlias, and CourierDomainAlias.

Keep in mind, however, that you can only have one structural objectClass, just in case you plan on hanging e-mail information off of an inetOrgPerson or somesuch.

Re: Large-Scale Mail with Postfix, OpenLDAP and Courier

Anonymous's picture

Hi, I'm trying to follow your example, but I'm having a couple of problems here...

in the first ldif (base.ldif), I had to take out all the first spaces in the lines, and when I try to make an ldapadd I'm getting:

dapadd: update failed: dc=myhosting, dc=example
ldap_add: Object class violation (65)
additional info: no structural object class provided

any suggestions?

Re: Large-Scale Mail with Postfix, OpenLDAP and Courier

Anonymous's picture

This article looks abandoned ... but .. I am having the same problem and really don't know what to do here.

Re: Large-Scale Mail with Postfix, OpenLDAP and Courier

Anonymous's picture

Dear friend

Hi and thanks for the solution provided by you
but do you have any solution for multiple servers running under one domain. with the helpof ldap server database replication.

regds
amit jain
amitldap@hotmail.com

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState