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.