
New version based on Debian 7.2 and with the latest Modoboa… watch this space. If you wan’t to help out testing the new guide, leave a comment below.
First off, this guide like 90% complete. If you follow it, please report back if something is wrong etc.
When I first started writing, I ran through the steps a couple of times installing everything from scratch, but after a while, I got tired of re installing just to try stuff out, so some things may gone wrong along the way.
These are mostly my own notes setting up modoboa. When completed, you’ll have postfix, dovecot and modoboa running with nginx.
I won’t go into detail how to configure the various modoboa extensions, this is covered in modoboas documentation.
I’m using a minimal install of Debian Squeeze for this. So, some packages may already be installed if you don’t us the same dist. The steps described here also should work on Ubuntu, but I haven’t verified that.
Replace <fqdn> with your fully qualified domain name. For example: mail.domain.com. <domain> with your domain. For example: example.com.
This guide assumes you’ll run mailserver, mysql and modoboa on the same host. If you plan to grow, it might be a good idea to separate these.
Content
- Install packages
- amavisd-new setup
- Configure clamav
- Make /tmp a bit more secure
- Make /tmp a bit more secure
- Create users
- Install modoboa with pip
- Create databases and user
- Create amavis tables
- Configure postfix
- configure nginx
- Change MAILDIR_ROOT
- Create a SECRET_KEY
- Change NOTIFICATIONS_SENDER
- Configure dovecot
- Troubleshooting
- Deploy modoboa
Install packages
I’d start with installing netselect-apt to find your fastest mirror. This is optional (works only in Debian).
apt-get install netselect-apt cd /etc/apt/ netselect-apt apt-get update
then we’ll install the needed packages. We won’t use the Debian packaged version of amavisd-new but the latest from source. That’s why we install all the perl modules and archive packages
apt-get install sudo gcc libxslt-dev python-pip postfix-mysql nginx \ python-dev python-rrdtool python-mysqldb mysql-server dovecot-imapd \ dovecot-pop3d pwgen spamassassin vim ca-certificates dkim-filter \ libarchive-zip-perl libconvert-tnef-perl libconvert-uulib-perl \ libmime-tools-perl libcrypt-openssl-rsa-perl libnet-cidr-perl \ libevent-1.4-2 libnet-server-perl pax libnfsidmap2 libmail-dkim-perl \ libberkeleydb-perl librpcsecgss3 libio-multiplex-perl libgssglue1 portmap \ libunix-syslog-perl libcrypt-openssl-bignum-perl ncompress nomarch \ arc arj zoo tnef cabextract clamav clamav-daemon bzip2 unrar-free xdms \ p7zip p7zip-full unzip orange ripole lzop rpm2cpio lrzip
If you’re using Ubuntu, replace package dkim-filter with opendkim. I won’t go into detail how to enable dkim in this guide anyway.
amavisd-new setup
These instructions pretty much come from the INSTALL file from amavisd-new.
Create user group amavis:amavis and set to home dir /var/amavis
useradd amavis -d /var/amavis mkdir -p /var/amavis/tmp /var/amavis/var /var/amavis/db /var/amavis/home chown -R amavis:amavis /var/amavis chmod -R 750 /var/amavis
Download and unpack amavisd-new.
cd /usr/local/src wget http://www.amavis.org/amavisd-new-2.8.0.tar.gz -O - | tar zxf - cd amavisd-new-2.8.0
install amavis
cp amavisd /usr/local/sbin/ chown root /usr/local/sbin/amavisd chmod 755 /usr/local/sbin/amavisd
copy configfile
cp amavisd.conf /etc/ chown root:amavis /etc/amavisd.conf chmod 640 /etc/amavisd.conf
create a directory to be used by amavisd-new as a quarantine area
mkdir /var/virusmails chown amavis:amavis /var/virusmails chmod 750 /var/virusmails
edit /etc/amavisd.conf and change, enable or uncomment, the following settings:
$daemon_user = 'amavis'; $daemon_group = 'amavis'; $mydomain = 'example.com'; $MYHOME = '/var/amavis'; $TEMPBASE = "$MYHOME/tmp"; $db_home = "$MYHOME/db"; $helpers_home = "$MYHOME/home"; $pid_file = "/var/run/amavis/amavisd.pid"; $lock_file = "/var/run/amavis/amavisd.lock"; $unix_socketname = "/var/run/amavis/amavisd.sock"; $myhostname = '<fdqn>';
since we’re doing the ”uncluttered” setup, for some extra security, also change ownerships:
chown root /var/amavis chown -R amavis:amavis /var/amavis/home chmod 750 /var/amavis /var/amavis/home
Create init script for amavisd
Create a new file, /etc/init.d/amavisd, containing:
#!/bin/sh
# /etc/init.d/amavisd
### BEGIN INIT INFO
# Provides: amavis
# Required-Start: $local_fs $remote_fs $network $syslog $time
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start amavis at boot time
# Description: Enable amavis service
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
PIDFILE=/var/run/amavis/amavisd.pid
SOCKET=/var/run/amavis/amavisd.sock
case "$1" in
start)
if [ -f "$PIDFILE" ]; then
echo "Already running"
else
echo "Starting amavisd"
/usr/local/sbin/amavisd -u amavis
fi
;;
stop)
if [ -f "$PIDFILE" ]; then
echo "Stopping amavisd"
kill `cat $PIDFILE`
else
echo "Not running"
fi
;;
restart)
echo "Restarting amavisd"
$0 stop
sleep 1
$0 start
;;
reload)
echo "Reloading amavisd"
kill -HUP `cat /var/amavis/amavisd.pid`
;;
*)
echo "Usage: /etc/init.d/amavisd {start|stop}"
exit 1
;;
esac
exit 0
also create the directory /var/run/amavis.
mkdir /var/run/amavis chown amavis:amavis /var/run/amavis chmod 700 /var/run/amavis
and finally set executable bit and enable the service:
chmod +x /etc/init.d/amavisd update-rc.d amavisd defaults
and start the service:
service amavisd start
Configure clamav
Add the clamav user to the amavis group
make sure the following lines are enabled in /etc/amavisd.conf (note the change from .sock to .ctl).
['ClamAV-clamd',
\&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.ctl"],
qr/\bOK$/m, qr/\bFOUND$/m,
qr/^.*?: (?!Infected Archive)(.*) FOUND$/m ],
and make sure
AllowSupplementaryGroups true
is set in /etc/clamav/clamd.conf. This is the default setting (at least in Debian squeeze).
gpasswd -a clamav
and finally start clamd-daemon
service clamav-daemon start
Make /tmp a bit more secure
Add the following line to /etc/fstab. As per recommendation in amavisd-new install instructions.
tmpfs /tmp tmpfs noexec,nosuid,nodev 0 0
After that, create a new file /etc/apt/apt.conf.d/50extracttemplates. Apt uses /tmp per default running installation scripts and if we add noexec to /tmp, this will make sure this doesn’t happen.
APT
{
ExtractTemplates
{
TempDir "/var/tmp";
};
};
Create users
groupadd -g 5000 vmail useradd -g vmail -u 5000 vmail -d /var/vmail -m chown -R vmail:vmail /var/vmail chmod u+w /var/vmail
Install modoboa with pip
pip install modoboa
This will download, compile and install modoboa and what’s needed to run the whole shebang.
Create databases and user
mysql -u root -p
create database modoboa; create database amavis; grant all privileges on modoboa.* to 'modoboa'@'localhost' identified by 'somepassword'; grant all privileges on amavis.* to 'amavis'@'localhost' identified by 'someotherpassword'; flush privileges;
Create amavis tables
I’ve removed (some) comments to save pixels. Please refer to the amavis documentation for the whole thing. It’s pure SQL so you can cut and paste. If you get errors. Take one query at the time.
use amavis;
CREATE TABLE users (
id int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, -- unique id
priority integer NOT NULL DEFAULT '7', -- sort field, 0 is low prior.
policy_id integer unsigned NOT NULL DEFAULT '1', -- JOINs with policy.id
email varbinary(255) NOT NULL UNIQUE,
fullname varchar(255) DEFAULT NULL -- not used by amavisd-new
-- local char(1) -- Y/N (optional field, see note further down)
);
CREATE TABLE mailaddr (
id int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
priority integer NOT NULL DEFAULT '7', -- 0 is low priority
email varbinary(255) NOT NULL UNIQUE
);
CREATE TABLE wblist (
rid integer unsigned NOT NULL, -- recipient: users.id
sid integer unsigned NOT NULL, -- sender: mailaddr.id
wb varchar(10) NOT NULL, -- W or Y / B or N / space=neutral / score
PRIMARY KEY (rid,sid)
);
CREATE TABLE policy (
id int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
-- 'id' this is the _only_ required field
policy_name varchar(32), -- not used by amavisd-new, a comment
virus_lover char(1) default NULL, -- Y/N
spam_lover char(1) default NULL, -- Y/N
unchecked_lover char(1) default NULL, -- Y/N
banned_files_lover char(1) default NULL, -- Y/N
bad_header_lover char(1) default NULL, -- Y/N
bypass_virus_checks char(1) default NULL, -- Y/N
bypass_spam_checks char(1) default NULL, -- Y/N
bypass_banned_checks char(1) default NULL, -- Y/N
bypass_header_checks char(1) default NULL, -- Y/N
spam_modifies_subj char(1) default NULL, -- Y/N
virus_quarantine_to varchar(64) default NULL,
spam_quarantine_to varchar(64) default NULL,
banned_quarantine_to varchar(64) default NULL,
unchecked_quarantine_to varchar(64) default NULL,
bad_header_quarantine_to varchar(64) default NULL,
clean_quarantine_to varchar(64) default NULL,
archive_quarantine_to varchar(64) default NULL,
spam_tag_level float default NULL, -- higher score inserts spam info headers
spam_tag2_level float default NULL, -- inserts 'declared spam' header fields
spam_tag3_level float default NULL, -- inserts 'blatant spam' header fields
spam_kill_level float default NULL, -- higher score triggers evasive actions
-- e.g. reject/drop, quarantine, ...
-- (subject to final_spam_destiny setting)
spam_dsn_cutoff_level float default NULL,
spam_quarantine_cutoff_level float default NULL,
addr_extension_virus varchar(64) default NULL,
addr_extension_spam varchar(64) default NULL,
addr_extension_banned varchar(64) default NULL,
addr_extension_bad_header varchar(64) default NULL,
warnvirusrecip char(1) default NULL, -- Y/N
warnbannedrecip char(1) default NULL, -- Y/N
warnbadhrecip char(1) default NULL, -- Y/N
newvirus_admin varchar(64) default NULL,
virus_admin varchar(64) default NULL,
banned_admin varchar(64) default NULL,
bad_header_admin varchar(64) default NULL,
spam_admin varchar(64) default NULL,
spam_subject_tag varchar(64) default NULL,
spam_subject_tag2 varchar(64) default NULL,
spam_subject_tag3 varchar(64) default NULL,
message_size_limit integer default NULL, -- max size in bytes, 0 disable
banned_rulenames varchar(64) default NULL, -- comma-separated list of ...
-- names mapped through %banned_rules to actual banned_filename tables
disclaimer_options varchar(64) default NULL,
forward_method varchar(64) default NULL,
sa_userconf varchar(64) default NULL,
sa_username varchar(64) default NULL
);
CREATE TABLE maddr (
partition_tag integer DEFAULT 0, -- see $partition_tag
id bigint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
email varbinary(255) NOT NULL, -- full mail address
domain varchar(255) NOT NULL, -- only domain part of the email address
-- with subdomain fields in reverse
CONSTRAINT part_email UNIQUE (partition_tag,email)
) ENGINE=InnoDB;
CREATE TABLE msgs (
partition_tag integer DEFAULT 0, -- see $partition_tag
mail_id varbinary(16) NOT NULL, -- long-term unique mail id, dflt 12 ch
secret_id varbinary(16) DEFAULT '', -- authorizes release of mail_id, 12 ch
am_id varchar(20) NOT NULL, -- id used in the log
time_num integer unsigned NOT NULL, -- rx_time: seconds since Unix epoch
time_iso char(16) NOT NULL, -- rx_time: ISO8601 UTC ascii time
sid bigint unsigned NOT NULL, -- sender: maddr.id
policy varchar(255) DEFAULT '', -- policy bank path (like macro %p)
client_addr varchar(255) DEFAULT '', -- SMTP client IP address (IPv4 or v6)
size integer unsigned NOT NULL, -- message size in bytes
originating char(1) DEFAULT ' ' NOT NULL, -- sender from inside or auth'd
content char(1), -- content type: V/B/U/S/Y/M/H/O/T/C
-- virus/banned/unchecked/spam(kill)/spammy(tag2)/
-- /bad-mime/bad-header/oversized/mta-err/clean
-- is NULL on partially processed mail
-- (prior to 2.7.0 the CC_SPAMMY was logged as 's', now 'Y' is used;
-- to avoid a need for case-insenstivity in queries)
quar_type char(1), -- quarantined as: ' '/F/Z/B/Q/M/L
-- none/file/zipfile/bsmtp/sql/
-- /mailbox(smtp)/mailbox(lmtp)
quar_loc varbinary(255) DEFAULT '', -- quarantine location (e.g. file)
dsn_sent char(1), -- was DSN sent? Y/N/q (q=quenched)
spam_level float, -- SA spam level (no boosts)
message_id varchar(255) DEFAULT '', -- mail Message-ID header field
from_addr varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '',
-- mail From header field, UTF8
subject varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '',
-- mail Subject header field, UTF8
host varchar(255) NOT NULL, -- hostname where amavisd is running
PRIMARY KEY (partition_tag,mail_id)
-- FOREIGN KEY (sid) REFERENCES maddr(id) ON DELETE RESTRICT
) ENGINE=InnoDB;
CREATE INDEX msgs_idx_sid ON msgs (sid);
CREATE INDEX msgs_idx_mess_id ON msgs (message_id); -- useful with pen pals
CREATE INDEX msgs_idx_time_num ON msgs (time_num);
-- alternatively when purging based on time_iso (instead of msgs_idx_time_num):
-- CREATE INDEX msgs_idx_time_iso ON msgs (time_iso);
CREATE TABLE msgrcpt (
partition_tag integer DEFAULT 0, -- see $partition_tag
mail_id varbinary(16) NOT NULL, -- (must allow duplicates)
rseqnum integer DEFAULT 0 NOT NULL, -- recip's enumeration within msg
rid bigint unsigned NOT NULL, -- recipient: maddr.id (dupl. allowed)
is_local char(1) DEFAULT ' ' NOT NULL, -- recip is: Y=local, N=foreign
content char(1) DEFAULT ' ' NOT NULL, -- content type V/B/U/S/Y/M/H/O/T/C
ds char(1) NOT NULL, -- delivery status: P/R/B/D/T
-- pass/reject/bounce/discard/tempfail
rs char(1) NOT NULL, -- release status: initialized to ' '
bl char(1) DEFAULT ' ', -- sender blacklisted by this recip
wl char(1) DEFAULT ' ', -- sender whitelisted by this recip
bspam_level float, -- per-recipient (total) spam level
smtp_resp varchar(255) DEFAULT '', -- SMTP response given to MTA
PRIMARY KEY (partition_tag,mail_id,rseqnum)
-- FOREIGN KEY (rid) REFERENCES maddr(id) ON DELETE RESTRICT,
-- FOREIGN KEY (mail_id) REFERENCES msgs(mail_id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE INDEX msgrcpt_idx_mail_id ON msgrcpt (mail_id);
CREATE INDEX msgrcpt_idx_rid ON msgrcpt (rid);
CREATE TABLE quarantine (
partition_tag integer DEFAULT 0, -- see $partition_tag
mail_id varbinary(16) NOT NULL, -- long-term unique mail id
chunk_ind integer unsigned NOT NULL, -- chunk number, starting with 1
mail_text blob NOT NULL, -- store mail as chunks of octets
PRIMARY KEY (partition_tag,mail_id,chunk_ind)
-- FOREIGN KEY (mail_id) REFERENCES msgs(mail_id) ON DELETE CASCADE
) ENGINE=InnoDB;
Deploy modoboa
mkdir /var/www && cd /var/www modoboa-admin.py deploy --syncdb --collectstatic --with-amavis mailadmin cd mailadmin python manage.py collectstatic python manage.py syncdb --migrate --noinput python manage.py loaddata initial_users.json
Configure postfix
Use the modoboa-admin.py script to create these files automatically.
modoboa-admin.py postfix_maps --dbtype mysql /etc/postfix/maps
Answer the questions with the values you used earlier. The database is the modoboa database.
Fix permissions. Since these files contain your database passwords and it’s only postfix that need to read them.
chown root:postfix /etc/postfix/maps/sql-* chmod 640 /etc/postfix/maps/sql-*
configure postfix
postconf -e mailbox_transport=virtual postconf -e maildrop_destination_recipient_limit=1 postconf -e virtual_minimum_uid=5000 postconf -e virtual_gid_maps=static:5000 postconf -e virtual_uid_maps=static:5000 postconf -e virtual_mailbox_base=/var/vmail postconf -e relay_domains= postconf -e virtual_mailbox_domains=mysql:/etc/postfix/maps/sql-domains.cf postconf -e virtual_alias_domains=mysql:/etc/postfix/maps/sql-domain-aliases.cf postconf -e virtual_mailbox_maps=mysql:/etc/postfix/maps/sql-mailboxes.cf postconf -e virtual_alias_maps=mysql:/etc/postfix/maps/sql-aliases.cf,mysql:/etc/postfix/maps/sql-domain-aliases-mailboxes.cf,mysql:/etc/postfix/maps/sql-email2email.cf,mysql:/etc/postfix/maps/sql-catchall-aliases.cf postconf -e virtual_transport=dovecot postconf -e dovecot_destination_recipient_limit=1
add definition to /etc/postfix/master.cf
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
and then restart postfix
service postfix restart
configure nginx
Now we’ll install Green Unicorn and configure nginx. I know, there is a package included with Debian, don’t use that, use easy_install as described here to get the latest version instead.
Green Unicorn
easy_install -U gunicorn
create a gunicorn config file /var/www/mailadmin/gunicorn.conf.py
backlog = 2048 bind = "unix:/var/run/gunicorn/modoboa.sock" pidfile = "/var/run/gunicorn/modoboa.pid" daemon = True debug = False workers = 2 logfile = "/var/log/gunicorn/modoboa.log" loglevel = "info"
Now, gunicorn won’t run without /var/run/gunicorn, let’s create it.
mkdir /var/run/gunicorn
then create a init script, /etc/init.d/modoboa:
#!/bin/sh
# /etc/init.d/modoboa
### BEGIN INIT INFO
# Provides: modoboa
# Required-Start: $local_fs $remote_fs $network $syslog $time
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start modoboa at boot time
# Description: Enable modoboa service
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MODOBOA_ROOT=/var/www/mailadmin
LOGFILE=/var/log/modoboa.log
PIDFILE=/var/run/gunicorn/modoboa.pid
SOCKET=/var/run/gunicorn/modoboa.sock
case "$1" in
start)
if [ -f "$PIDFILE" ]; then
echo "Already running"
else
echo "Starting modoboa"
cd $MODOBOA_ROOT
gunicorn_django --error-log $LOGFILE -c gunicorn.conf.py
fi
;;
stop)
if [ -f "$PIDFILE" ]; then
echo "Stopping modoboa"
kill -QUIT `cat /var/run/gunicorn/modoboa.pid`
else
echo "Not running"
fi
;;
restart)
echo "Restarting modoboa"
$0 stop
sleep 1
$0 start
;;
reload)
echo "Reloading modoboa"
kill -HUP `cat /var/run/gunicorn/modoboa.pid`
;;
*)
echo "Usage: /etc/init.d/modoboa {start|stop}"
exit 1
;;
esac
exit 0
set executable bit and enable the service:
chmod +x /etc/init.d/modoboa update-rc.d modoboa defaults
and finally start it
service modoboa start
nginx
now create a config file for nginx
vi /etc/nginx/sites-available/modoboa
change as it suits you:
upstream modoboa {
server unix:/var/run/gunicorn/modoboa.sock fail_timeout=0;
}
server {
listen 443;
server_name <fqdn>;
root /var/www/mailadmin/mailadmin/;
ssl on;
ssl_certificate /etc/ssl/<fqdn>.pem;
ssl_certificate_key /etc/ssl/<fqdn>.key;
# if you're serve other stuff; it might be good to use separate logfile
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /sitestatic/ {
autoindex on;
}
location /media/ {
autoindex on;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Protocol ssl;
proxy_pass http://modoboa;
}
}
change path to your cert and key accordingly. you can read here how to enable ssl and generate a self signed cert/key pair. You can use the same cert/key for dovecot below if you have the same fdqn on web- and mailserver.
Now enable the site and restart nginx. Make sure the certificates excist, otherwise nginx won’t start.
ln -s /etc/nginx/sites-available/modoboa /etc/nginx/sites-enabled/modoboa service nginx restart
You shold now be able to login using the default username: admin and password: password at https://<fqdn>. First thing you do is to change the password! First time you save modoboa settings, some tables are creted. Do that and then run the following snippets.
Change MAILDIR_ROOT
Change default maildir root from .maildir/ to just /. I think it’s prettier, and I already used this on a server I migrated from. This is optional.
echo "update modoboa.lib_parameter set value = '/' where name = 'admin.MAILDIR_ROOT';" | mysql -u root -p
Create a SECRET_KEY
echo "update modoboa.lib_parameter set value = '`pwgen -N 1 -s 32`' where name = 'auth.SECRET_KEY';" | mysql -u root -p
Change NOTIFICATIONS_SENDER
echo "update modoboa.lib_parameter set value = 'admin@domain.com' where name = 'amavis.NOTIFICATIONS_SENDER';" | mysql -u root -p
Configure dovecot
I won’t go into detail here. I’ll just paste an example config file. NOT COMPLETE YET!
# if you, like me, have mail stored on nfs use these settings so index files doesn't get corrupted (according to dovecot manual)
mmap_disable = yes
dotlock_use_excl = no
mail_nfs_storage = yes
mail_nfs_index = yes
login_processes_count=16
login_max_processes_count=256
mail_max_userip_connections=20
protocols = imap imaps pop3 pop3s managesieve
disable_plaintext_auth=no
log_timestamp = "%Y-%m-%d %H:%M:%S"
# certificates
ssl_ca_file = /etc/ssl/certs/ca-certificates.crt
ssl_cert_file = /etc/ssl/mail.crt
ssl_key_file = /etc/ssl/mail.key
# needed for fail2ban to work
auth_verbose=yes
log_path = /var/log/dovecot.log
info_log_path = /var/log/dovecot-info.log
mail_location = maildir:/var/vmail/%d/%n
namespace private {
separator=.
inbox = yes
}
mail_privileged_group = mail
protocol pop3 {
pop3_uidl_format = %08Xu%08Xv
}
protocol imap {
mail_plugins = quota imap_quota
}
plugin {
sieve_global_path = /var/vmail/globalsieverc
sieve_dir=/var/vmail/%d/%n/sieve
sieve=/var/vmail/%d/%n/.dovecot.sieve
quota = maildir:User quota
quota_rule = *:storage=100M
quota_rule2 = Trash:storage=50M
}
protocol managesieve {
login_executable = /usr/lib/dovecot/managesieve-login
mail_executable = /usr/lib/dovecot/managesieve
managesieve_max_line_length = 65536
managesieve_logout_format = bytes=%i/%o
#managesieve_implementation_string = Cyrus timsieved v2.2.13
}
protocol lda {
postmaster_address = admin@dalnix.se
auth_socket_path = /var/run/dovecot/auth-master
mail_plugins = sieve
log_path = /var/log/dovecot-deliver-errors.log
info_log_path = /var/log/dovecot-deliver.log
}
auth default {
mechanisms = plain login
passdb sql {
args = /etc/dovecot/dovecot-sql.conf
}
userdb sql {
args = /etc/dovecot/dovecot-sql.conf
}
user = root
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0600
user = vmail
}
client {
path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
}
}
}
now create /etc/dovecot/dovecot-sql.conf.
driver = mysql
connect = host=localhost dbname=modoboa user=modoboa password=somepassword
default_pass_scheme = CRYPT
password_query = SELECT email AS user, password FROM auth_user WHERE email='%u' and is_active=1
user_query = SELECT concat('/', dom.name, '/', mb.path) AS home, uid, gid, concat('*:storage=', mb.quota, 'M') AS quota_rule FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.address='%n' AND dom.name='%d'
and then restart dovecot
service dovecot restart
Troubleshooting
Relay access denied
If you get lines like these in your /etc/mail.log.
Mar 15 18:59:19 mail postfix/smtpd[4012]: NOQUEUE: reject: RCPT from mail-qe0-f48.google.com[209.85.128.48]: 454 4.7.1 <joe@example.com>: Relay access denied; from=<mrbad@gmail.com> to=<joe@example.com> proto=ESMTP helo=<mail-qe0-f48.google.com>
Make sure the domain/account is actually enabled in modoboa. I had some trouble figuring this out after doing an import of alot of domains and all apparantly got imported without beeing enabled (my bad).

Hi,
Am unable to launch the gunucorn server. Any help will be much appreciated.
Bellow is the /var/log/modoboa.log output.
http://pastebin.com/NJ0M1VyG
ValueError: Unable to configure handler ’modoboa’: Cannot resolve ’modoboa.lib.logutils.SQLHandler’: cannot import name connection
Hi, I’m sorry but I can’t help you. I’m not really a pyhon guru. Plus this guide is quite old and probably won’t work for Modoboa 1.0.
You’ll get better help asking in the #modoboa irc channel on Freenode etc.
Hi
You should mention that you need to specify ALLOWED_HOSTS in settings.py for the django app to get it up and running with nginx.
Regards
Paul
I would like to help you out testing Debian 7.2 setup.
Hi, I never got around to finishing mine. But I can recommend you check out this guide instead.