Skip to content
Open
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
13 changes: 2 additions & 11 deletions .github/linters/.dive-ci.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
rules:
# If the efficiency is measured below X%, mark as failed.
# Expressed as a ratio between 0-1.
lowestEfficiency: 0.95

# If the amount of wasted space is at least X or larger than X, mark as failed.
# Expressed in B, KB, MB, and GB.
highestWastedBytes: 20MB

# If the amount of wasted space makes up for X% or more of the image, mark as failed.
# Note: the base image layer is NOT included in the total image size.
# Expressed as a ratio between 0-1; fails if the threshold is met or crossed.
highestUserWastedPercent: 0.20
highestUserWastedPercent: disabled
lowestEfficiency: disabled
42 changes: 29 additions & 13 deletions target/mda/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM dovecot/dovecot:2.4.1-dev@sha256:99f45812578122e62663503f55bd32919e96c7b048349539a8511c3e71c00e3e
FROM alpine:3.23@sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62 AS base

LABEL maintainer="https://github.com/jeboehm/docker-mailserver"
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
Expand All @@ -15,15 +15,18 @@ ENV MYSQL_HOST=db \
POSTMASTER=postmaster@example.com \
RECIPIENT_DELIMITER=-

USER root
RUN apt-get update && \
apt-get install --no-install-recommends -y curl && \
rm -rf \
/etc/dovecot/conf.d/auth.conf \
/etc/dovecot/conf.d/mail.conf \
/etc/dovecot/conf.d/ssl.conf \
/srv/mail \
/var/lib/apt/lists/*
RUN --mount=type=cache,target=/var/cache/apk \
apk add \
curl \
dovecot \
dovecot-fts-flatcurve \
dovecot-lmtpd \
dovecot-mysql \
dovecot-pigeonhole-plugin \
dovecot-pop3d && \
adduser -DH vmail && \
mkdir -p /srv/vmail && \
chown -R vmail:vmail /srv/vmail

COPY --chown=root:root rootfs/ /

Expand All @@ -35,9 +38,22 @@ RUN mv /etc/dovecot/conf.d/10-ssl.conf /tmp/10-ssl.conf && \
USER vmail
WORKDIR /

# 2003: LMTP, 2004: AUTH
EXPOSE 2003 2004

# LMTP
EXPOSE 2003
# AUTH
EXPOSE 2004
# IMAP
EXPOSE 31143
EXPOSE 31993
# POP3
EXPOSE 31110
EXPOSE 31995
# MANAGESIEVE
EXPOSE 4190
# DOVEADM
EXPOSE 8080

VOLUME ["/srv/vmail"]
HEALTHCHECK CMD /usr/local/bin/healthcheck.sh

ENTRYPOINT ["/entrypoint.sh"]
Expand Down
2 changes: 1 addition & 1 deletion target/mda/rootfs/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ if ! [ -r /etc/dovecot/tls/tls.crt ] || ! [ -r /etc/dovecot/tls/tls.key ]; then
exit 1
fi

exec /usr/bin/tini -- /dovecot/sbin/dovecot -F
exec dovecot -F
24 changes: 23 additions & 1 deletion target/mda/rootfs/etc/dovecot/conf.d/10-auth.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,26 @@ import_environment {
auth_mechanisms = plain login
auth_cache_size = 5M

!include auth-sql.conf.ext
sql_driver = mysql

mysql default {
host = $ENV:MYSQL_HOST
port = $ENV:MYSQL_PORT
user = $ENV:MYSQL_USER
password = $ENV:MYSQL_PASSWORD
dbname = $ENV:MYSQL_DATABASE
option_file = /etc/my.cnf
option_group = client
}

passdb sql {
default_password_scheme = SHA256-CRYPT
query = SELECT mail_users.name AS user, mail_domains.name AS domain, password FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id \
WHERE mail_users.name = '%{user|username}' AND mail_domains.name = '%{user|domain}' AND enabled = 1 AND NOT (send_only = 1 AND "%{protocol}" in ('imap', 'pop3'));
}

userdb sql {
query = SELECT concat(quota, 'M') AS quota_storage_size FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id \
WHERE mail_users.name = '%{user|username}' AND mail_domains.name = '%{user|domain}';
iterate_query = SELECT mail_users.name AS username, mail_domains.name AS domain FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id;
}
7 changes: 7 additions & 0 deletions target/mda/rootfs/etc/dovecot/conf.d/10-common.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ postmaster_address = $ENV:POSTMASTER
hostname = $ENV:MAILNAME
submission_host = $ENV:MTA_SMTP_ADDRESS
doveadm_api_key = $ENV:DOVEADM_API_KEY

mail_uid = vmail
mail_gid = vmail

default_internal_user = vmail
default_login_user = vmail
default_internal_group = vmail
12 changes: 12 additions & 0 deletions target/mda/rootfs/etc/dovecot/conf.d/10-logging.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mail_plugins {
mail_log = yes
notify = yes
}

log_path = /dev/stdout
mail_log_events = delete undelete expunge save copy mailbox_create mailbox_delete mailbox_rename flag_change

event_exporter log {
format = json
time_format = rfc3339
}
13 changes: 7 additions & 6 deletions target/mda/rootfs/etc/dovecot/conf.d/10-mail.conf
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
mail_driver = maildir
mail_home = /srv/vmail/%{user|domain}/%{user|username}
mail_path = /srv/vmail/%{user|domain}/%{user|username}/Maildir
mail_attachment_detection_options =
mailbox_list_layout = maildir++
mailbox_list_index = yes
mailbox_list_utf8 = yes
maildir_copy_with_hardlinks = yes

namespace inbox {
inbox = yes
}

protocol !indexer-worker {
# mail_vsize_bg_after_count = 100
mail_attribute {
dict file {
path = %{home}/dovecot-attributes
}
}
27 changes: 27 additions & 0 deletions target/mda/rootfs/etc/dovecot/conf.d/10-master.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import_environment {
haproxy_trusted_networks = $ENV:TRUSTED_PROXIES

service lmtp {
chroot =

inet_listener lmtp {
port = 2003
}
Expand All @@ -18,6 +20,10 @@ service auth {
}

service imap-login {
process_min_avail = 1
client_limit = 100
chroot =

inet_listener imap {
port = 31143
haproxy = $ENV:MDA_UPSTREAM_PROXY
Expand All @@ -30,6 +36,10 @@ service imap-login {
}

service pop3-login {
process_min_avail = 1
client_limit = 100
chroot =

inet_listener pop3 {
port = 31110
haproxy = $ENV:MDA_UPSTREAM_PROXY
Expand All @@ -40,3 +50,20 @@ service pop3-login {
haproxy = $ENV:MDA_UPSTREAM_PROXY
}
}

service managesieve-login {
process_min_avail = 1
client_limit = 100
chroot =

inet_listener sieve {
port = 4190
}
}

service doveadm {
inet_listener http {
port = 8080
ssl = yes
}
}
15 changes: 0 additions & 15 deletions target/mda/rootfs/etc/dovecot/conf.d/10-no-chroot.conf

This file was deleted.

3 changes: 3 additions & 0 deletions target/mda/rootfs/etc/dovecot/conf.d/15-mailboxes.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace inbox {
inbox = yes
separator = /

mailbox Drafts {
auto = subscribe
special_use = \Drafts
Expand Down
21 changes: 21 additions & 0 deletions target/mda/rootfs/etc/dovecot/conf.d/20-fts.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
mail_plugins {
fts = yes
fts_flatcurve = yes
}

fts_autoindex = yes
fts_autoindex_max_recent_msgs = 999
fts_search_add_missing = yes

language_filters = normalizer-icu snowball stopwords
language_tokenizers = generic email-address
language_tokenizer_generic_algorithm = simple

language en {
default = yes
filters = lowercase snowball english-possessive stopwords
}

fts flatcurve {
substring_search = yes
}
4 changes: 4 additions & 0 deletions target/mda/rootfs/etc/dovecot/conf.d/20-imap.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
imap_hibernate_timeout = 5s

protocol imap {
mail_plugins {
imap_sieve = yes
imap_filter_sieve = yes
imap_quota = yes
}
}
9 changes: 0 additions & 9 deletions target/mda/rootfs/etc/dovecot/conf.d/20-managesieve.conf

This file was deleted.

78 changes: 78 additions & 0 deletions target/mda/rootfs/etc/dovecot/conf.d/90-metrics.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# https://github.com/dovecot/docker/blob/main/2.4.1/dovecot.conf
@metric_defaults = backend

# Log auth failures
metric auth_failures {
filter = event=auth_request_finished AND NOT success=yes
exporter = log
}

metric imap_command {
filter = event=imap_command_finished

group_by cmd_name {
method discrete {
}
}

group_by tagged_reply_state {
method discrete {
}
}
}

metric smtp_command {
filter = event=smtp_server_command_finished and protocol=submission

group_by cmd_name {
method discrete {
}
}

group_by status_code {
method discrete {
}
}

group_by duration {
method exponential {
base = 10
min_magnitude = 1
max_magnitude = 5
}
}
}

metric lmtp_command {
filter = event=smtp_server_command_finished and protocol=lmtp

group_by cmd_name {
method discrete {
}
}

group_by status_code {
method discrete {
}
}

group_by duration {
method exponential {
base = 10
min_magnitude = 1
max_magnitude = 5
}
}
}

# Add duration metrics for deliveries
metric mail_deliveries {
filter = event=mail_delivery_finished
group_by duration {
method exponential {
base = 10
min_magnitude = 1
max_magnitude = 5
}
}
}
6 changes: 0 additions & 6 deletions target/mda/rootfs/etc/dovecot/conf.d/90-quota.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ mail_plugins {
quota = yes
}

protocol imap {
mail_plugins {
imap_quota = yes
}
}

quota "User quota" {
warning warn-95 {
quota_storage_percentage = 95
Expand Down
6 changes: 3 additions & 3 deletions target/mda/rootfs/etc/dovecot/conf.d/90-sieve.conf
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,20 @@ service rspamc-learnspam {
mailbox Junk {
sieve_script report-spam {
type = before
cause = copy
cause = copy append
path = /etc/dovecot/sieve/global/learn-spam.sieve
}
}

imapsieve_from Junk {
sieve_script report-ham {
type = before
cause = copy
cause = copy append
path = /etc/dovecot/sieve/global/learn-ham.sieve
}
}

sieve_script before {
sieve_script_type = before
type = before
path = /etc/dovecot/sieve/global/spam-to-folder.sieve
}
Loading