1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2025-09-16 09:26:45 +02:00

Postfix: Split TLSPol companion app into separate container (#6688)

* postfix: split postfix-tlspol service into new container

* postfix-tls-pol: added debug mode

* pf-tlspol: removed obsoleted standalone conf from Dockerfiles

* pf-tlspol: use git instead of wget
This commit is contained in:
DerLinkman
2025-08-28 10:18:18 +02:00
committed by GitHub
parent 169aafec50
commit 1cb38bacdb
12 changed files with 257 additions and 44 deletions

View File

@@ -0,0 +1,49 @@
FROM golang:1.25-bookworm AS builder
WORKDIR /src
ENV CGO_ENABLED=0 \
GO111MODULE=on \
VERSION=1.8.14
RUN git clone --branch v${VERSION} https://github.com/Zuplu/postfix-tlspol && \
cd /src/postfix-tlspol && \
scripts/build.sh build-only
FROM debian:bookworm-slim
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
ARG DEBIAN_FRONTEND=noninteractive
ENV LC_ALL=C
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
dirmngr \
dnsutils \
iputils-ping \
sudo \
supervisor \
redis-tools \
syslog-ng \
syslog-ng-core \
syslog-ng-mod-redis \
tzdata \
&& rm -rf /var/lib/apt/lists/* \
&& touch /etc/default/locale
COPY supervisord.conf /etc/supervisor/supervisord.conf
COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf
COPY syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng-redis_slave.conf
COPY postfix-tlspol.sh /opt/postfix-tlspol.sh
COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh
COPY docker-entrypoint.sh /docker-entrypoint.sh
COPY --from=builder /src/postfix-tlspol/build/postfix-tlspol /usr/local/bin/postfix-tlspol
RUN chmod +x /opt/postfix-tlspol.sh \
/usr/local/sbin/stop-supervisor.sh \
/docker-entrypoint.sh
RUN rm -rf /tmp/* /var/tmp/*
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]

View File

@@ -0,0 +1,7 @@
#!/bin/bash
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
cp /etc/syslog-ng/syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng.conf
fi
exec "$@"

View File

@@ -0,0 +1,52 @@
#!/bin/bash
LOGLVL=info
if [ ${DEV_MODE} != "n" ]; then
echo -e "\e[31mEnabling debug mode\e[0m"
set -x
LOGLVL=debug
fi
[[ ! -d /etc/postfix-tlspol ]] && mkdir -p /etc/postfix-tlspol
[[ ! -d /var/lib/postfix-tlspol ]] && mkdir -p /var/lib/postfix-tlspol
until dig +short mailcow.email > /dev/null; do
echo "Waiting for DNS..."
sleep 1
done
# Do not attempt to write to slave
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
export REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
else
export REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
fi
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
echo "Waiting for Redis..."
sleep 2
done
echo "Waiting for Postfix..."
until ping postfix -c1 > /dev/null; do
sleep 1
done
echo "Postfix OK"
cat <<EOF > /etc/postfix-tlspol/config.yaml
server:
address: 0.0.0.0:8642
log-level: ${LOGLVL}
prefetch: true
cache-file: /var/lib/postfix-tlspol/cache.db
dns:
# must support DNSSEC
address: 127.0.0.11:53
EOF
/usr/local/bin/postfix-tlspol -config /etc/postfix-tlspol/config.yaml

View File

@@ -0,0 +1,8 @@
#!/bin/bash
printf "READY\n";
while read line; do
echo "Processing Event: $line" >&2;
kill -3 $(cat "/var/run/supervisord.pid")
done < /dev/stdin

View File

@@ -0,0 +1,25 @@
[supervisord]
pidfile=/var/run/supervisord.pid
nodaemon=true
user=root
[program:syslog-ng]
command=/usr/sbin/syslog-ng --foreground --no-caps
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autostart=true
[program:postfix-tlspol]
startsecs=10
autorestart=true
command=/opt/postfix-tlspol.sh
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[eventlistener:processes]
command=/usr/local/sbin/stop-supervisor.sh
events=PROCESS_STATE_STOPPED, PROCESS_STATE_EXITED, PROCESS_STATE_FATAL

View File

@@ -0,0 +1,45 @@
@version: 3.38
@include "scl.conf"
options {
chain_hostnames(off);
flush_lines(0);
use_dns(no);
dns_cache(no);
use_fqdn(no);
owner("root"); group("adm"); perm(0640);
stats_freq(0);
bad_hostname("^gconfd$");
};
source s_src {
unix-stream("/dev/log");
internal();
};
destination d_stdout { pipe("/dev/stdout"); };
destination d_redis_ui_log {
redis(
host("`REDIS_SLAVEOF_IP`")
persist-name("redis1")
port(`REDIS_SLAVEOF_PORT`)
auth("`REDISPASS`")
command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
);
};
filter f_mail { facility(mail); };
# start
# overriding warnings are still displayed when the entrypoint runs its initial check
# warnings logged by postfix-mailcow to syslog are hidden to reduce repeating msgs
# Some other warnings are ignored
filter f_ignore {
not match("overriding earlier entry" value("MESSAGE"));
not match("TLS SNI from checks.mailcow.email" value("MESSAGE"));
not match("no SASL support" value("MESSAGE"));
not facility (local0, local1, local2, local3, local4, local5, local6, local7);
};
# end
log {
source(s_src);
filter(f_ignore);
destination(d_stdout);
filter(f_mail);
destination(d_redis_ui_log);
};

View File

@@ -0,0 +1,45 @@
@version: 3.38
@include "scl.conf"
options {
chain_hostnames(off);
flush_lines(0);
use_dns(no);
dns_cache(no);
use_fqdn(no);
owner("root"); group("adm"); perm(0640);
stats_freq(0);
bad_hostname("^gconfd$");
};
source s_src {
unix-stream("/dev/log");
internal();
};
destination d_stdout { pipe("/dev/stdout"); };
destination d_redis_ui_log {
redis(
host("redis-mailcow")
persist-name("redis1")
port(6379)
auth("`REDISPASS`")
command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
);
};
filter f_mail { facility(mail); };
# start
# overriding warnings are still displayed when the entrypoint runs its initial check
# warnings logged by postfix-mailcow to syslog are hidden to reduce repeating msgs
# Some other warnings are ignored
filter f_ignore {
not match("overriding earlier entry" value("MESSAGE"));
not match("TLS SNI from checks.mailcow.email" value("MESSAGE"));
not match("no SASL support" value("MESSAGE"));
not facility (local0, local1, local2, local3, local4, local5, local6, local7);
};
# end
log {
source(s_src);
filter(f_ignore);
destination(d_stdout);
filter(f_mail);
destination(d_redis_ui_log);
};

View File

@@ -1,13 +1,3 @@
FROM golang:1.25-bookworm AS builder
WORKDIR /src
ENV CGO_ENABLED=0 \
GO111MODULE=on
RUN git clone https://github.com/Zuplu/postfix-tlspol.git && \
cd postfix-tlspol && \
scripts/build.sh build-only
FROM debian:bookworm-slim
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
@@ -58,7 +48,6 @@ COPY rspamd-pipe-spam /usr/local/bin/rspamd-pipe-spam
COPY whitelist_forwardinghosts.sh /usr/local/bin/whitelist_forwardinghosts.sh
COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh
COPY docker-entrypoint.sh /docker-entrypoint.sh
COPY --from=builder /src/postfix-tlspol/build/postfix-tlspol /usr/local/bin/postfix-tlspol
RUN chmod +x /opt/postfix.sh \
/usr/local/bin/rspamd-pipe-ham \

View File

@@ -3,9 +3,6 @@
trap "postfix stop" EXIT
[[ ! -d /opt/postfix/conf/sql/ ]] && mkdir -p /opt/postfix/conf/sql/
[[ ! -d /opt/postfix/conf/postfix-tlspol ]] && mkdir -p /opt/postfix/conf/postfix-tlspol
[[ ! -d /etc/postfix-tlspol ]] && mkdir -p /etc/postfix-tlspol
[[ ! -d /var/lib/postfix-tlspol ]] && mkdir -p /var/lib/postfix-tlspol
# Wait for MySQL to warm-up
while ! mariadb-admin status --ssl=false --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do
@@ -506,26 +503,6 @@ if [[ ! -f /opt/postfix/conf/custom_postscreen_whitelist.cidr ]]; then
EOF
fi
cat <<EOF > /opt/postfix/conf/postfix-tlspol/config.yaml
server:
address: 127.0.0.1:8642
log-level: info
prefetch: true
cache-file: /var/lib/postfix-tlspol/cache.db
dns:
# must support DNSSEC
address: 127.0.0.11:53
EOF
# Fixing local command execution of postfix-tlspol with symlink to config
if [ ! -L /etc/postfix-tlspol/config.yaml ]; then
ln -s /opt/postfix/conf/postfix-tlspol/config.yaml /etc/postfix-tlspol/config.yaml
fi
# Fix Postfix permissions
chown -R root:postfix /opt/postfix/conf/sql/ /opt/postfix/conf/custom_transport.pcre
chmod 640 /opt/postfix/conf/sql/*.cf /opt/postfix/conf/custom_transport.pcre

View File

@@ -11,15 +11,6 @@ stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autostart=true
[program:postfix-tlspol]
startsecs=10
autorestart=true
command=/usr/local/bin/postfix-tlspol -config /opt/postfix/conf/postfix-tlspol/config.yaml
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:postfix]
command=/opt/postfix.sh
stdout_logfile=/dev/stdout

View File

@@ -152,7 +152,7 @@ smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_sender_dependent.cf
smtp_sasl_security_options =
smtp_sasl_mechanism_filter = plain, login
smtp_tls_policy_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf socketmap:inet:127.0.0.1:8642:QUERY
smtp_tls_policy_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf socketmap:inet:postfix-tlspol:8642:QUERY
smtp_header_checks = pcre:/opt/postfix/conf/anonymize_headers.pcre
mail_name = Postcow
# local_transport map catches local destinations and prevents routing local dests when the next map would route "*"

View File

@@ -378,6 +378,30 @@ services:
aliases:
- postfix
postfix-tlspol-mailcow:
image: ghcr.io/mailcow/postfix-tlspol:1.0
depends_on:
unbound-mailcow:
condition: service_healthy
postfix-mailcow:
condition: service_started
volumes:
- postfix-tlspol-vol-1:/var/lib/postfix-tlspol
environment:
- LOG_LINES=${LOG_LINES:-9999}
- TZ=${TZ}
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- REDISPASS=${REDISPASS}
- DEV_MODE=${DEV_MODE:-n}
restart: always
dns:
- ${IPV4_NETWORK:-172.22.1}.254
networks:
mailcow-network:
aliases:
- postfix-tlspol
memcached-mailcow:
image: memcached:alpine
restart: always
@@ -649,6 +673,7 @@ volumes:
redis-vol-1:
rspamd-vol-1:
postfix-vol-1:
postfix-tlspol-vol-1:
crypt-vol-1:
sogo-web-vol-1:
sogo-userdata-backup-vol-1: