Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update -q --fix-missing && \
curl \
dovecot-core \
dovecot-imapd \
dovecot-ldap \
dovecot-lmtpd \
dovecot-managesieved \
dovecot-pop3d \
Expand All @@ -32,9 +33,11 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update -q --fix-missing && \
opendmarc \
p7zip \
postfix \
postfix-ldap \
pyzor \
razor \
rsyslog \
sasl2-bin \
spamassassin \
unzip \
&& \
Expand All @@ -53,6 +56,9 @@ RUN chmod 644 /etc/clamav/freshclam.conf && freshclam
# Configures Dovecot
RUN sed -i -e 's/include_try \/usr\/share\/dovecot\/protocols\.d/include_try \/etc\/dovecot\/protocols\.d/g' /etc/dovecot/dovecot.conf
RUN sed -i -e 's/#mail_plugins = \$mail_plugins/mail_plugins = \$mail_plugins sieve/g' /etc/dovecot/conf.d/15-lda.conf
RUN sed -i -e 's/^.*lda_mailbox_autocreate.*/lda_mailbox_autocreate = yes/g' /etc/dovecot/conf.d/15-lda.conf
RUN sed -i -e 's/^.*lda_mailbox_autosubscribe.*/lda_mailbox_autosubscribe = yes/g' /etc/dovecot/conf.d/15-lda.conf
RUN sed -i -e 's/^.*postmaster_address.*/postmaster_address = '${POSTMASTER_ADDRESS:="[email protected]"}'/g' /etc/dovecot/conf.d/15-lda.conf
COPY target/dovecot/auth-passwdfile.inc /etc/dovecot/conf.d/
COPY target/dovecot/??-*.conf /etc/dovecot/conf.d/

Expand Down
29 changes: 28 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ all-fast: build generate-accounts run fixtures tests clean
no-build: generate-accounts run fixtures tests clean

build-no-cache:
cd test/docker-openldap/ && docker build -f Dockerfile -t ldap --no-cache .
docker build --no-cache -t $(NAME) .

build:
cd test/docker-openldap/ && docker build -f Dockerfile -t ldap .
docker build -t $(NAME) .

generate-accounts:
Expand Down Expand Up @@ -69,13 +71,35 @@ run:
-v "`pwd`/test":/tmp/docker-mailserver-test \
-e DISABLE_CLAMAV=1 \
-h mail.my-domain.com -t $(NAME)
sleep 20
docker run -d --name mail_manual_ssl \
-v "`pwd`/test/config":/tmp/docker-mailserver \
-v "`pwd`/test":/tmp/docker-mailserver-test \
-e SSL_TYPE=manual \
-e SSL_CERT_PATH=/tmp/docker-mailserver/letsencrypt/mail.my-domain.com/fullchain.pem \
-e SSL_KEY_PATH=/tmp/docker-mailserver/letsencrypt/mail.my-domain.com/privkey.pem \
-h mail.my-domain.com -t $(NAME)
sleep 20
docker run -d --name ldap_for_mail \
-e LDAP_DOMAIN="localhost.localdomain" \
-h mail.my-domain.com -t ldap
sleep 20
docker run -d --name mail_with_ldap \
-v "`pwd`/test/config":/tmp/docker-mailserver \
-v "`pwd`/test":/tmp/docker-mailserver-test \
-e ENABLE_LDAP=1 \
-e LDAP_SERVER_HOST=ldap \
-e LDAP_SEARCH_BASE=ou=people,dc=localhost,dc=localdomain \
-e LDAP_BIND_DN=cn=admin,dc=localhost,dc=localdomain \
-e ENABLE_SASLAUTHD=1 \
-e SASLAUTHD_MECHANISMS=ldap \
-e SASLAUTHD_LDAP_SERVER=ldap \
-e SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=localhost,dc=localdomain \
-e SASLAUTHD_LDAP_PASSWORD=admin \
-e SASLAUTHD_LDAP_SEARCH_BASE=ou=people,dc=localhost,dc=localdomain \
-e [email protected] \
--link ldap_for_mail:ldap \
-h mail.my-domain.com -t $(NAME)
# Wait for containers to fully start
sleep 20

Expand Down Expand Up @@ -115,7 +139,10 @@ clean:
fail-auth-mailer \
mail_disabled_amavis \
mail_disabled_clamav \
mail_manual_ssl
mail_manual_ssl \
ldap_for_mail \
mail_with_ldap

@if [ -f config/postfix-accounts.cf.bak ]; then\
rm -f config/postfix-accounts.cf ;\
mv config/postfix-accounts.cf.bak config/postfix-accounts.cf ;\
Expand Down
89 changes: 87 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Easy to deploy and upgrade.

Includes:

- postfix with smtp auth
- dovecot for sasl, imap (and optional pop3) with ssl support
- postfix with smtp or ldap auth
- dovecot for sasl, imap (and optional pop3) with ssl support, with ldap auth
- saslauthd with ldap auth
- amavis
- spamassasin supporting custom rules
- clamav with automatic updates
Expand Down Expand Up @@ -118,6 +119,40 @@ Otherwise, `iptables` won't be able to ban IPs.
- **empty** => `fetchmail` disabled
- 1 => `fetchmail` enabled

##### ENABLE_LDAP

- **empty** => LDAP authentification is disabled
- 1 => LDAP authentification is enabled
- NOTE:
- A second container for the ldap service is necessary (e.g. [docker-openldap](https://github.com/osixia/docker-openldap))
- For preparing the ldap server to use in combination with this continer [this](http://acidx.net/wordpress/2014/06/installing-a-mailserver-with-postfix-dovecot-sasl-ldap-roundcube/) article may be helpful

##### LDAP_SERVER_HOST

- **empty** => mail.domain.com
- => Specify the dns-name/ip-address where the ldap-server
- NOTE: If you going to use the mailserver in combination with docker-compose you can set the service name here

##### LDAP_SEARCH_BASE

- **empty** => ou=people,dc=domain,dc=com
- => e.g. LDAP_SEARCH_BASE=dc=mydomain,dc=local

##### LDAP_BIND_DN

- **empty** => cn=admin,dc=domain,dc=com
- => take a look at examples of SASL_LDAP_BIND_DN

##### LDAP_BIND_PW

- **empty** => admin
- => Specify the password to bind against ldap

##### POSTMASTER_ADDRESS

- **empty** => [email protected]
- => Specify the postmaster address

##### SA_TAG

- **2.0** => add spam info headers if at, or above that level
Expand All @@ -130,6 +165,56 @@ Otherwise, `iptables` won't be able to ban IPs.

- **6.31** => triggers spam evasive actions

##### ENABLE_SASLAUTHD

- **empty** => `saslauthd` is disabled
- 1 => `saslauthd` is enabled

##### SASLAUTHD_MECHANISMS

- empty => pam
- ldap => authenticate against ldap server
- shadow => authenticate against local user db
- mysql => authenticate against mysql db
- rimap => authenticate against imap server
- NOTE: can be a list of mechanisms like pam ldap shadow

##### SASLAUTHD_MECH_OPTIONS

- empty => None
- e.g. with SASLAUTHD_MECHANISMS rimap you need to specify the ip-address/servername of the imap server ==> xxx.xxx.xxx.xxx

##### SASLAUTHD_LDAP_SERVER

- empty => localhost

##### SASLAUTHD_LDAP_SSL

- empty or 0 => ldap:// will be used
- 1 => ldaps:// will be used

##### SASLAUTHD_LDAP_BIND_DN

- empty => anonymous bind
- specify an object with priviliges to search the directory tree
- e.g. active directory: SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=net
- e.g. openldap: SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net

##### SASLAUTHD_LDAP_PASSWORD

- empty => anonymous bind

##### SASLAUTHD_LDAP_SEARCH_BASE

- empty => Reverting to SASLAUTHD_MECHANISMS pam
- specify the search base

##### SASLAUTHD_LDAP_FILTER

- empty => default filter (&(uniqueIdentifier=%u)(mailEnabled=TRUE))
- e.g. for active directory: (&(sAMAccountName=%U)(objectClass=person))
- e.g. for openldap: (&(uid=%U)(objectClass=person))

##### SASL_PASSWD

- **empty** => No sasl_passwd will be created
Expand Down
10 changes: 10 additions & 0 deletions config/dovecot-ldap.conf.ext
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
base = ou=people,dc=domain,dc=com
default_pass_scheme = SSHA
dn = cn=admin,dc=domain,dc=com
dnpass = admin
hosts = mail.domain.com
ldap_version = 3
pass_attrs = uniqueIdentifier=user,userPassword=password
pass_filter = (&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))
user_attrs = mailHomeDirectory=home,mailUidNumber=uid,mailGidNumber=gid,mailStorageDirectory=mail
user_filter = (&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))
8 changes: 8 additions & 0 deletions config/postfix-ldap-aliases.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
bind = yes
bind_dn = cn=admin,dc=domain,dc=com
bind_pw = admin
query_filter = (&(mailAlias=%s)(mailEnabled=TRUE))
result_attribute = mail
search_base = ou=people,dc=domain,dc=com
server_host = mail.domain.com
version = 3
8 changes: 8 additions & 0 deletions config/postfix-ldap-groups.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
bind = yes
bind_dn = cn=admin,dc=domain,dc=com
bind_pw = admin
query_filter = (&(mailGroupMember=%s)(mailEnabled=TRUE))
result_attribute = mail
search_base = ou=people,dc=domain,dc=com
server_host = mail.domain.com
version = 3
8 changes: 8 additions & 0 deletions config/postfix-ldap-users.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
bind = yes
bind_dn = cn=admin,dc=domain,dc=com
bind_pw = admin
query_filter = (&(mail=%s)(mailEnabled=TRUE))
result_attribute = mail
search_base = ou=people,dc=domain,dc=com
server_host = mail.domain.com
version = 3
126 changes: 114 additions & 12 deletions target/start-mailserver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,38 @@ die () {

echo "export VIRUSMAILS_DELETE_DELAY=${VIRUSMAILS_DELETE_DELAY:="7"}" >> /root/.bashrc

#
# Configuring Dovecot
#
if [ "$SMTP_ONLY" != 1 ]; then
cp -a /usr/share/dovecot/protocols.d /etc/dovecot/
# Disable pop3 (it will be eventually enabled later in the script, if requested)
mv /etc/dovecot/protocols.d/pop3d.protocol /etc/dovecot/protocols.d/pop3d.protocol.disab
mv /etc/dovecot/protocols.d/managesieved.protocol /etc/dovecot/protocols.d/managesieved.protocol.disab
sed -i -e 's/#ssl = yes/ssl = yes/g' /etc/dovecot/conf.d/10-master.conf
sed -i -e 's/#port = 993/port = 993/g' /etc/dovecot/conf.d/10-master.conf
sed -i -e 's/#port = 995/port = 995/g' /etc/dovecot/conf.d/10-master.conf
sed -i -e 's/#ssl = yes/ssl = required/g' /etc/dovecot/conf.d/10-ssl.conf
fi

#
# Users
#
if [ -f /tmp/docker-mailserver/postfix-accounts.cf ]; then
if [ -f /tmp/docker-mailserver/postfix-accounts.cf -a "$ENABLE_LDAP" != 1 ]; then
echo "Checking file line endings"
sed -i 's/\r//g' /tmp/docker-mailserver/postfix-accounts.cf
echo "Regenerating postfix 'vmailbox' and 'virtual' for given users"
echo "# WARNING: this file is auto-generated. Modify config/postfix-accounts.cf to edit user list." > /etc/postfix/vmailbox

# Checking that /tmp/docker-mailserver/postfix-accounts.cf ends with a newline
sed -i -e '$a\' /tmp/docker-mailserver/postfix-accounts.cf
# Configuring Dovecot

echo -n > /etc/dovecot/userdb
chown dovecot:dovecot /etc/dovecot/userdb
chmod 640 /etc/dovecot/userdb
cp -a /usr/share/dovecot/protocols.d /etc/dovecot/
# Disable pop3 (it will be eventually enabled later in the script, if requested)
mv /etc/dovecot/protocols.d/pop3d.protocol /etc/dovecot/protocols.d/pop3d.protocol.disab
mv /etc/dovecot/protocols.d/managesieved.protocol /etc/dovecot/protocols.d/managesieved.protocol.disab
sed -i -e 's/#ssl = yes/ssl = yes/g' /etc/dovecot/conf.d/10-master.conf
sed -i -e 's/#port = 993/port = 993/g' /etc/dovecot/conf.d/10-master.conf
sed -i -e 's/#port = 995/port = 995/g' /etc/dovecot/conf.d/10-master.conf
sed -i -e 's/#ssl = yes/ssl = required/g' /etc/dovecot/conf.d/10-ssl.conf

sed -i -e '/\!include auth-ldap\.conf\.ext/s/^/#/' /etc/dovecot/conf.d/10-auth.conf
sed -i -e '/\!include auth-passwdfile\.inc/s/^#//' /etc/dovecot/conf.d/10-auth.conf

# Creating users
# 'pass' is encrypted
Expand Down Expand Up @@ -67,6 +76,93 @@ else
echo "==> Warning: 'config/docker-mailserver/postfix-accounts.cf' is not provided. No mail account created."
fi

#
# LDAP
#
if [ "$ENABLE_LDAP" = 1 ]; then
for i in 'users' 'groups' 'aliases'; do
fpath="/tmp/docker-mailserver/postfix-ldap-${i}.cf"
if [ -f $fpath ]; then
cp ${fpath} /etc/postfix/ldap-${i}.cf
sed -i -e 's|^server_host.*|server_host = '${LDAP_SERVER_HOST:="mail.domain.com"}'|g' \
-e 's|^search_base.*|search_base = '${LDAP_SEARCH_BASE:="ou=people,dc=domain,dc=com"}'|g' \
-e 's|^bind_dn.*|bind_dn = '${LDAP_BIND_DN:="cn=admin,dc=domain,dc=com"}'|g' \
-e 's|^bind_pw.*|bind_pw = '${LDAP_BIND_PW:="admin"}'|g' \
/etc/postfix/ldap-${i}.cf
else
echo "${fpath} not found"
echo "==> Warning: 'config/postfix-ldap-$i.cf' is not provided."
fi
done

echo "Loading dovecot LDAP authentification configuration"
cp /tmp/docker-mailserver/dovecot-ldap.conf.ext /etc/dovecot/dovecot-ldap.conf.ext

sed -i -e 's|^hosts.*|hosts = '${LDAP_SERVER_HOST:="mail.domain.com"}'|g' \
-e 's|^base.*|base = '${LDAP_SEARCH_BASE:="ou=people,dc=domain,dc=com"}'|g' \
-e 's|^dn\s*=.*|dn = '${LDAP_BIND_DN:="cn=admin,dc=domain,dc=com"}'|g' \
-e 's|^dnpass\s*=.*|dnpass = '${LDAP_BIND_PW:="admin"}'|g' \
/etc/dovecot/dovecot-ldap.conf.ext

echo "Enabling dovecot LDAP authentification"
sed -i -e '/\!include auth-ldap\.conf\.ext/s/^#//' /etc/dovecot/conf.d/10-auth.conf
sed -i -e '/\!include auth-passwdfile\.inc/s/^/#/' /etc/dovecot/conf.d/10-auth.conf

echo "Configuring LDAP"
[ -f /etc/postfix/ldap-users.cf ] && \
postconf -e "virtual_mailbox_maps = ldap:/etc/postfix/ldap-users.cf" || \
echo '==> Warning: /etc/postfix/ldap-user.cf not found'

[ -f /etc/postfix/ldap-aliases.cf -a -f /etc/postfix/ldap-groups.cf ] && \
postconf -e "virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf, ldap:/etc/postfix/ldap-groups.cf" || \
echo '==> Warning: /etc/postfix/ldap-aliases.cf or /etc/postfix/ldap-groups.cf not found'

[ ! -f /etc/postfix/sasl/smtpd.conf ] && cat > /etc/postfix/sasl/smtpd.conf << EOF
pwcheck_method: saslauthd
mech_list: plain login
EOF
fi

#
# SASLAUTHD
#
if [ "$ENABLE_SASLAUTHD" = 1 ]; then
echo "Configuring Cyrus SASL"
# checking env vars and setting defaults
[ -z $SASLAUTHD_MECHANISMS ] && SASLAUTHD_MECHANISMS=pam
[ -z $SASLAUTHD_LDAP_SEARCH_BASE ] && SASLAUTHD_MECHANISMS=pam
[ -z $SASLAUTHD_LDAP_SERVER ] && SASLAUTHD_LDAP_SERVER=localhost
[ -z $SASLAUTHD_LDAP_FILTER ] && SASLAUTHD_LDAP_FILTER='(&(uniqueIdentifier=%u)(mailEnabled=TRUE))'
([ $SASLAUTHD_LDAP_SSL == 0 ] || [ -z $SASLAUTHD_LDAP_SSL ]) && SASLAUTHD_LDAP_PROTO='ldap://' || SASLAUTHD_LDAP_PROTO='ldaps://'

if [ ! -f /etc/saslauthd.conf ]; then
echo "Creating /etc/saslauthd.conf"
cat > /etc/saslauthd.conf << EOF
ldap_servers: ${SASLAUTHD_LDAP_PROTO}${SASLAUTHD_LDAP_SERVER}

ldap_auth_method: bind
ldap_bind_dn: ${SASLAUTHD_LDAP_BIND_DN}
ldap_bind_pw: ${SASLAUTHD_LDAP_PASSWORD}

ldap_search_base: ${SASLAUTHD_LDAP_SEARCH_BASE}
ldap_filter: ${SASLAUTHD_LDAP_FILTER}

ldap_referrals: yes
log_level: 10
EOF
fi

sed -i -e "s|^START=.*|START=yes|g" \
-e "s|^MECHANISMS=.*|MECHANISMS="\"$SASLAUTHD_MECHANISMS\""|g" \
-e "s|^MECH_OPTIONS=.*|MECH_OPTIONS="\"$SASLAUTHD_MECH_OPTIONS\""|g" \
/etc/default/saslauthd
sed -i -e "/smtpd_sasl_path =.*/d" \
-e "/smtpd_sasl_type =.*/d" \
-e "/dovecot_destination_recipient_limit =.*/d" \
/etc/postfix/main.cf
gpasswd -a postfix sasl
fi

#
# Aliases
#
Expand Down Expand Up @@ -419,8 +515,14 @@ if [ "$ENABLE_FAIL2BAN" = 1 ]; then
/etc/init.d/fail2ban start
fi

echo "Listing users"
/usr/sbin/dovecot user '*'
if [ "$ENABLE_SASLAUTHD" = 1 ]; then
/etc/init.d/saslauthd start
fi

if [ "$SMTP_ONLY" != 1 ]; then
echo "Listing users"
/usr/sbin/dovecot user '*'
fi

echo "Starting..."
tail -f /var/log/mail/mail.log
Loading