AFS, Postfix, Dovecot and Maildirs
UPDATE: Most of this is still valid, but read this first to see what I've learned about needing PAGs.
Okay, here's the deal. Maildir works by using link()/unlink() to move mail around from the new/cur/tmp dirs. This is a problem because AFS doesn't allow link() across dirs Doing so would break ACLs. However, you can safely use rename() with Maildirs on AFS because it's atomic, which is the whole reason Maildir uses link()/unlink() in the first place.
Originally I didn't have any problems with link()/unlink() because I didn't let the Postfix local delivery agent (local) deliver my mail - it passed it off to procmail, which already happens to use rename() when dealing with Maildir (which is technically incorrect behavior).
Here's how you can get it to work:
Okay, here's the deal. Maildir works by using link()/unlink() to move mail around from the new/cur/tmp dirs. This is a problem because AFS doesn't allow link() across dirs Doing so would break ACLs. However, you can safely use rename() with Maildirs on AFS because it's atomic, which is the whole reason Maildir uses link()/unlink() in the first place.
Originally I didn't have any problems with link()/unlink() because I didn't let the Postfix local delivery agent (local) deliver my mail - it passed it off to procmail, which already happens to use rename() when dealing with Maildir (which is technically incorrect behavior).
Here's how you can get it to work:
- Create a user principle in Kerberos for postfix and one for dovecot. Export as keytabs. Store them on the mail server somewhere. You could probably use a single principle for this, but I like the idea of having two so users can remove privs from dovecot if they don't check their mail via IMAP.
- Make a few changes in dovecot.conf. First, keep indexes out of AFS and disable link() copies:
mail_location = maildir:/afs/cell/home/%u/Maildir:INDEX=/var/lib/dovecot-index/%u
maildir_copy_with_hardlinks = no
Next, disable mmap and enable dotlocks. I would think you shouldn't need these but this is what I ended up with that worked. Test yourself and see:
mmap_disable = yes
dotlock_use_excl = yes
lock_method = dotlock
I ended up using the following args for passdb pam {}to ensure pam_afs_session gets hit:
args = session=yes setcred=yes dovecot - k5start dovecot in the foreground (k5start backgrounds the whole thing):
k5start -U -f /etc/dovecot/dovecot.keytab \
-t -b -K 10 -- /usr/sbin/dovecot -F - Get the Postfix source (as I use debian, I just grabed the source package from APT and built it that way). Edit src/local/maildir.c and change the sane_link() calls to rename(), and comment out the call to unlink(). Install Postfix. WARNING: You shouldn't modify this if your Postfix also delivers to non-AFS Maildirs, as rename() on most non-AFS filesystems is NOT atomic. If you need to do that, checking to see if you're in /afs and then using the right syscall should be trivial.
- Rename /usr/lib/postfix/local (or wherever it is on your system). I mv'd it to local.wrapped
- Make a new file called local, give it the same permissions/owernship as local.wrapped, and then wrap local.wrapped as such:
#!/bin/sh
k5start -U -f /etc/postfix/postfix.keytab \
-K 10 -t -- /usr/lib/postfix/local.wrapped \
"$@" - Set ACLs on Maildirs for postfix/dovecot:
find /afs/path/to/Maildir -type d -exec \
fs setacl {} postfix rlidwk dovecot rlidwk \;

1 Comments:
Thanks a lot.
I use afs for mailstorage and I have done a lot of unneccesery work to emulate what k5start does.
Why did I not find this posting earlier?
Post a Comment
<< Home