User-managed Postfix mail forwarding using inotify
Since 1996, I have run a friends-and-family Internet hosting service called miranda.org. One of my priorities has always been to make things as user-manageable as possible -- most of my users are very technical, and I want them to be able to change things as they see fit, within reasonable safety parameters.
For a long time miranda.org used the qmail mail transport agent, which, while it has its share of problems, has very nice facilities for delegating administration of email addresses under a domain, or even a subset of a domain's email address space, to regular users.
When I decided to move to Postfix in 2013, I wanted to preserve this ability for my users. With Postfix, virtual domains are handled using the virtual_alias_maps
directive:
virtual_alias_maps = hash:/etc/postfix/virtual
and that file just maps email addresses to recipients:
bret@example.com bam@example.com
brett@example.com bam@example.org
miranda.org hosts around 30 mail domains. Obviously I couldn't just allow those 30 domain owners to edit /etc/postfix/virtual
and then run postmap
directly -- they'd be able to edit each other's addresses and potentially break things for everyone.
I decided to write a script to assemble the file from components like /etc/mail/domains/example.com
. The script makes sure each user is only trying to manage her own domain, assembles /etc/postfix/virtual
, and runs postmap
. It also commits the changes to virtual
to my postfix
git repository, so all changes are tracked in the same way as I track the rest of my Postfix configuration.
At first I thought I'd run this from cron
, but I decided I didn't really like the idea of running it every minute or even every five or fifteen, when most of the time it would be changing no configuration. Why not just run it only when needed?
Enter inotify
, a Linux kernel subsystem for noticing filesystem changes. The incron
utility can be configured to watch a file or directory (even recursively) and run something in response to a change. I just did aptitude install incron
and added a /etc/incron.d/postfix-virtual-map
file with these contents:
/etc/mail/domains IN_CLOSE_WRITE,IN_CREATE,IN_DELETE,IN_MOVED /opt/miranda-util/sbin/postfix-virtual-map
Now, when any user modifies her domain's file under /etc/mail/domains
, my postfix-virtual-map
script runs automatically.
Here's the script, if you're interested.