OS X Server Mail Alias Debugging & Open Directory Setup

How to manage aliases with OS X Server Mail (postfix).

OS X Server Mail Alias Debugging & Open Directory Setup

Status: 2020 - my testing notes collected from Apple Community Support discussion

Status: 2023 - add Open Directory tips as this is critical and part of mail setup

Apple have retired OS X Server and integrated some of the functions back into base MacOS, while others such as its integrated Postfix mail implementation have been put out to pasture and Apple has published suggestions for alternate replacements.

The now retired mail server still runs on OS X High Sierra and has some nice pre-integration with Open Directory and anti-spamming filtering, so it is still usable for small self-hosted mail system. One area of mail systems administration that got a bit confusing was setting up mail alias, so here is info that I put together from my Apple Community support discussion

The OS X Server email is based on Postfix mail transfer agent (MTA), Dovecot pop / imap and SpamHaus anti-spam filter and so if you are inclined you can bring together these parts on any Linux server.

For its directory service OS X Server provided "OpenDirector" which was based on OpenLDAP. For my OS X mail setup I have all the users defined in OpenDirector, so I am including tips on this as well.

Postfix -  base OS X vs Server OS X

The base base OS X provides a Postfix (MTA) installation as part of base software. The configuration files for base OS X are installed at: /etc & /etc/postfix

This install has the following aliases & main files included:

  • "/etc/aliases"  - which is actually a soft link to "postfix/aliases"
  • "/etc/aliases.db" - which is the hash map created from "/etc/aliases" source file
  • "/etc/postfix/main.cf" - is the main postfix startup configuraton (which by default has all alias configuration items commented out

On installing OS X Server an additional and duplicate Postfix configuration file area is created at: /Library/Server/Mail/Config/postfix

  • This results in duplicate aliases files: "aliases" & "aliases.db"
  • Main startup configuration file: "main.cf"
  • And installs daemon startup plist: "/System/Library/LaunchDaemons/com.postfix.master.plist" which you can look at to see details startup command line and configuration files

Mail Configuration

As there are now multiple postfix configuration areas it (those from base & those from Server) it is easy to get the configuration wrong, for example if you do a "postconf config_directory" command it might tell you that postfix is using the config in "/etc/postfix", when in fact it is not...

To check which configuration file is being used do: "ps -ax | grep postfix" and you can see the configuation file flag indicated via "master -c" process:

$ ps -ax | grep postfix
  264 ??         0:00.80 master -c /Library/Server/Mail/Config/postfix
 5878 ??         0:00.06 /usr/bin/perl /Applications/Server.app/Contents/ServerRoot/usr/libexec/postfix/greylist.pl
 5889 ttys000    0:00.01 grep postfix

So by default with OS X Server mail (I know this is true for Server 3 & 4) the config used is the one in "/Library/Server/Mail/Config/postfix"

Aliases Configuration

Having identified the location of configuration files location to managed your aliases the key items to look for in "main.cf" are:

  • "alias_maps = hash:/" - this will tell you the location of the ".db" file
  • "alias_database = hash:/" - this will tell you the location of the "aliases" file used to generate the hash/db file above
  • "local_recipient_maps = proxy:unix:passwd.byname $alias_maps" - this command is very important
    ... it is what causes the mail server to trivially reject mail undefined/invalid users. This looks at the known login user ids (via proxy) and
    the $alias_maps - which are as per item 2 above...
  • "virtual_alias_maps = $virtual_maps hash:/ - if you are hosting multiple mail domains within a single server

This now gives you flexibility to:

  • Put traditional "aliases" & "aliases.db" at any location you would like and manage then in standard way
  • Have aliases which are by fully qualified domain names as "virtual_users"
  • Use Server Users administration interface via the "Advanced Options..." to create aliases that are held within "Open Directory"

NOTE 1: If have setup email accounts via "Open Directory" master and then replicate this to the mail host, then these user should be flagged as being able to login in order for them to be visible as local recipient (as per item 3. "local_recipient_maps" above).

Testing your configuration

Having created your aliases you will likely need to test then if some thing is not working. A critical configuration item in: "/Library/Server/Mail/Config/postfix/main.cf" to  avoid your mail accepting email for undefined address is:

local_recipient_maps = proxy:unix:passwd.byname $alias_maps

This forces postfix mail server to verify that the mail recipient is a known user and is essential to avoid mail to unknown user entering into mail system and then replying with a "cannot deliver message" back to the "from/reply-to" identity which could be a false one and hence your mail system becomes a target for spam relay via return to sender messages.

To test the behaviour you will get you can use the "postmap" command.

For example to test the aliases an alias in the /etc/aliases.db file you can use the following command:

# postmap -q <TEST_NAME> -c /Library/Server/Mail/Config/postfix hash:/<aliases>
--- here is example
# sudo postmap -q frog -c /Library/Server/Mail/Config/postfix hash:/etc/aliases

If the alias is found it will provide the destination identity... such as "hopper" in above example.

For recipients that are know local user identities you can test via:

# postmap -q <LOCAL_NAME> -c /Library/Server/Mail/Config/postfix proxy:unix:passwd.byname
--- here is example
sudo postmap -q hopper -c /Library/Server/Mail/Config/postfix proxy:unix:passwd.byname
hopper:********:521:20:Big Frog:/Users/hopper:/bin/bash

If the user is found you will get the shadow passwd line as response.  Postfix does not look at details of the response,  just if I gets something or nothing and if it gets something then it will accept mail to that receipient.

So now for the three ways you can add aliases

  1. Via the <aliases>.db file which must be in the location specified by $alias_maps = hash:/<location> directive in main.cf
  2. Via the "Advanced Options..." aliases list that available from "Server" application "Account/Users" function
  3. Via the "Email Addresses:" that is available from the "Edit User.." function from "Server" application "Account/Users" function

I have tested 1 & 2 and the behaviour is that:

  1. If you use  &  .db mechanism then the recipient is returned via hash:/ test
  2. If you use "Advance Options" aliases list then the recipient is returned via proxy:unix:passwd.byname

If you use option 3 then the result is that that mail address will be added in the /Library/Server/Mail/Config/postfix/virtual_users file and you can then test this by doing:

postmap -q NAME@DOMAIN.COM -c /Library/Server/Mail/Config/postfix #hash:/Library/Server/Mail/Config/postfix/virtual_users

The response should be the local id that this maps to...

Setting up standard file locations

To make using OS X postfix server a bit simpler and consistent with standard configuration.

Thus for me, I keep my  files as follows:

/etc/aliases -> postfix/aliases -- soft link to file in /etc/postfix/aliases
/etc/postfix/aliases -- the actual aliases file I use
/etc/aliases.db -- the generated hash file
/Library/Server/Mail/Config/postfix/aliases -> /etc/postfix/aliases -- again link to the master aliases file
/Library/Server/Mail/Config/postfix/aliases.db -> /etc/aliases.db -- again link to the hash file

and my alias directives in /Library/Server/Mail/Config/postfix/main.cf are:
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
virtual_alias_maps = $virtual_maps hash:/Library/Server/Mail/Config/postfix/virtual_users
local_recipient_maps = proxy:unix:passwd.byname $alias_maps
virtual_alias_domains = $virtual_alias_maps hash:/Library/Server/Mail/Config/postfix/virtual_domains

As you can see I have updated the /Server/Library/Mail/Config/postfix alias related files and config to point back to the standard /etc/aliases area...This is more paranoia rather than necessity.

Generating hash database

To update the aliases.db hash table...

Based on above configuration (symbolic links etc)

# cd /etc
--- generate hash file
# sudo postalias -c /Library/Server/Mail/Config/postfix aliases

--- or
# sudo newaliases -c /Library/Server/Mail/Config/postfix aliases
--- notes new aliases  is just link to postfix Sendmail compatibility interface
--- to reload mail server after updating alias db
# sudo postfix -c /Library/Server/Mail/Config/postfix reload

Open Directory - Configuration and Use

Open Direcotory has a number of components including:

  • Microsoft Acticve Directory - including support to act as Primary Domain Controller
  • Passwork and Authentication Services - including Kerberos & single sign-on support and
  • OpenLDAP Directory Server - the main LDAP implemenation.

The Apple OS X Server vision was sophisticated capabilities with ease of use. However sometimes things go wrong and you need to look past the simple adminstration ui.

I only use the LDAP and Authentication components which requires:

  • Open Directory LDP - main and replica server
  • Client Replicas - for each server that is using the LDAP (mail, jabber etc)

The main adminstration task I need to use is that sometimes the primary server loses its replicas and so I need to restablish the replication.

Stopping and Starting the Server

Assuming everything is working nicely then you can stop / start the Open Directory service from the OS X Server Admin GUI.

On OS X / MacOS launchd provides framework for running deamons and agents. To control the status of these you can use the "launchctl" tool (in termnal).  So to find status of Open Directory:

--- 1. find daemon
$ sudo launchctl list | grep  irectory
91	0	com.apple.opendirectoryd
--- 2. Get detail configuration
$ sudo launchctl list com.apple.opendirectoryd
	"EnableTransactions" = true;
	"LimitLoadToSessionType" = "System";
	"MachServices" = {
		"com.apple.system.opendirectoryd.libinfo" = mach-port-object;
		"com.apple.system.DirectoryService.libinfo_v1" = mach-port-object;
		"com.apple.system.opendirectoryd.api" = mach-port-object;
		"com.apple.private.opendirectoryd.rpc" = mach-port-object;
		"com.apple.system.opendirectoryd.membership" = mach-port-object;
		"com.apple.system.DirectoryService.membership_v1" = mach-port-object;
	"Label" = "com.apple.opendirectoryd";
	"TimeOut" = 30;
	"OnDemand" = false;
	"LastExitStatus" = 0;
	"PID" = 91;
	"Program" = "/usr/libexec/opendirectoryd";

And similiarly to see status of OpenLDAP:

--- 1. find daemon
$ sudo launchctl list | grep  slap
-	1	org.openldap.slapd
--- 2. Get detail configuration
$ sudo launchctl list org.openldap.slapd
	"LimitLoadToSessionType" = "System";
	"Label" = "org.openldap.slapd";
	"TimeOut" = 30;
	"OnDemand" = true;
	"LastExitStatus" = 256;
	"Program" = "/usr/libexec/slapd";
	"ProgramArguments" = (
		"ldap:/// ldapi://%2Fvar%2Frun%2Fldapi";

This shows how the OpenLDAP is started and the command line arguments: "/usr/libexec/slapd  -d 0 -h ldap:/// ldapi://var/run/run/ldapi"

Some useful commands for "fixing" Open Directory

  • Stop Open Directory LDAP: "sudo launchctl stop org.openldap.slapd"
  • Stop Open Directory: "sudo launchctl stop com.apple.opendirectoryd"
  • Disable Open Directory: "sudo launchctl disable system/com.apple.opendirectoryd"
  • Enable Open Directory: "sudo launchctl enable system/com.apple.opendirectoryd"

Another set of command line utilities are what is provided by "Server Admin" tool. This also provides a view on the status of Open Directory:

$ sudo serveradmin fullstatus dirserv
dirserv:ldapSearchBase = "dc=machine2,dc=sub,dc=domain,dc=com,dc=it"
dirserv:readWriteSettingsVersion = 1
dirserv:LDAPServerType = "replica"
dirserv:kdcHostedRealm = "MASTER.XX.DOMAIN.COM.AU"
dirserv:logPaths:opendirectorydLog = "/var/log/opendirectoryd.log"
dirserv:logPaths:ldapLog = "/var/log/slapd.log"
dirserv:logPaths:passwordServiceServerLog = "/Library/Logs/PasswordService/ApplePasswordServer.Server.log"
dirserv:logPaths:passwordServiceErrorLog = "/Library/Logs/PasswordService/ApplePasswordServer.Error.log"
dirserv:logPaths:kdcLog = "/var/log/krb5kdc/kdc.log"
dirserv:logPaths:slapconfigLog = "/Library/Logs/slapconfig.log"
dirserv:isRelayServer = no
dirserv:state = "RUNNING"

And you can enable & start Open Directory using: "sudo serveradmin start dirserv"

To start your diagnosis on openldap, first see what it thinks it is:

Location of the OpenLDAP Berkerley DB is: "/var/db/openldap/openldap-data/"

References & Links:

Apple Community Support - where I posted setup and testing information orginally

Open Directory Administration (Version 10.6 Snow Leopard) - Mac OS X Server documentation, provide here in case you can't find it)

Others have problems - pointers on the process to fix a specific Open Director issue

slap recovery - more tips on recovering OpenLDAP

Berkerly DB Recovery Tip - OpenLDAP uses berkerly db under the covers, so db_recover tool might help with recovery of corrupted DB