feature/postfix-pgsql-image #8
38
images/postfix-pgsql/Dockerfile
Normal file
38
images/postfix-pgsql/Dockerfile
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Postfix + PostgreSQL Relay/MTA Image
|
||||||
|
#
|
||||||
|
# A pure SMTP relay/MTA: receives inbound mail and forwards it based on
|
||||||
|
# PostgreSQL-backed relay_domains/transport_maps lookups, equivalent to the
|
||||||
|
# Postfix setup described in the SimpleLogin self-hosting documentation
|
||||||
|
# (https://github.com/simple-login/app). No domain, hostname, or database
|
||||||
|
# credentials are baked into the image; everything is templated from
|
||||||
|
# environment variables at container startup. This image has no knowledge
|
||||||
|
# of what consumes the relayed mail.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# POSTFIX_VERSION pins the Debian base image tag (e.g. "12-slim"), which in
|
||||||
|
# turn pins the postfix/postfix-pgsql package versions available via apt.
|
||||||
|
ARG POSTFIX_VERSION=12-slim
|
||||||
|
FROM debian:${POSTFIX_VERSION}
|
||||||
|
|
||||||
|
LABEL maintainer="Damien Arnodo"
|
||||||
|
LABEL description="Postfix SMTP relay/MTA with PostgreSQL-backed relay_domains and transport_maps lookups"
|
||||||
|
|
||||||
|
RUN echo "postfix postfix/main_mailer_type select No configuration" | debconf-set-selections \
|
||||||
|
&& echo "postfix postfix/mailname string localhost" | debconf-set-selections \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
postfix \
|
||||||
|
postfix-pgsql \
|
||||||
|
gettext-base \
|
||||||
|
openssl \
|
||||||
|
ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY templates/ /etc/postfix/templates/
|
||||||
|
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||||
|
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 25
|
||||||
|
|
||||||
|
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||||
62
images/postfix-pgsql/docker-entrypoint.sh
Normal file
62
images/postfix-pgsql/docker-entrypoint.sh
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# Renders Postfix config templates from environment variables and starts
|
||||||
|
# Postfix in the foreground.
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TEMPLATE_DIR="/etc/postfix/templates"
|
||||||
|
SSL_DIR="/etc/postfix/ssl"
|
||||||
|
|
||||||
|
require_var() {
|
||||||
|
local name="$1"
|
||||||
|
if [ -z "${!name:-}" ]; then
|
||||||
|
echo "ERROR: required environment variable ${name} is not set" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for var in MAIL_DOMAIN MYHOSTNAME \
|
||||||
|
POSTGRES_HOST POSTGRES_PORT POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DB \
|
||||||
|
SMTP_RELAY_HOST SMTP_RELAY_PORT; do
|
||||||
|
require_var "$var"
|
||||||
|
done
|
||||||
|
|
||||||
|
# TLS: use mounted cert/key if provided, otherwise generate a self-signed
|
||||||
|
# "snakeoil" certificate on first start, matching the upstream docs' approach.
|
||||||
|
mkdir -p "$SSL_DIR"
|
||||||
|
if [ -n "${TLS_CERT_FILE:-}" ] && [ -n "${TLS_KEY_FILE:-}" ]; then
|
||||||
|
export SMTPD_TLS_CERT_FILE="$TLS_CERT_FILE"
|
||||||
|
export SMTPD_TLS_KEY_FILE="$TLS_KEY_FILE"
|
||||||
|
else
|
||||||
|
export SMTPD_TLS_CERT_FILE="${SSL_DIR}/snakeoil.pem"
|
||||||
|
export SMTPD_TLS_KEY_FILE="${SSL_DIR}/snakeoil.key"
|
||||||
|
if [ ! -f "$SMTPD_TLS_CERT_FILE" ] || [ ! -f "$SMTPD_TLS_KEY_FILE" ]; then
|
||||||
|
echo "No TLS_CERT_FILE/TLS_KEY_FILE provided, generating a self-signed certificate"
|
||||||
|
openssl req -x509 -nodes -days 3650 \
|
||||||
|
-newkey rsa:2048 \
|
||||||
|
-subj "/CN=${MYHOSTNAME}" \
|
||||||
|
-keyout "$SMTPD_TLS_KEY_FILE" \
|
||||||
|
-out "$SMTPD_TLS_CERT_FILE"
|
||||||
|
chmod 600 "$SMTPD_TLS_KEY_FILE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
render() {
|
||||||
|
local template="$1"
|
||||||
|
local destination="$2"
|
||||||
|
envsubst '${MAIL_DOMAIN} ${MYHOSTNAME} ${SMTPD_TLS_CERT_FILE} ${SMTPD_TLS_KEY_FILE} ${POSTGRES_HOST} ${POSTGRES_PORT} ${POSTGRES_USER} ${POSTGRES_PASSWORD} ${POSTGRES_DB} ${SMTP_RELAY_HOST} ${SMTP_RELAY_PORT}' \
|
||||||
|
< "$template" > "$destination"
|
||||||
|
}
|
||||||
|
|
||||||
|
render "${TEMPLATE_DIR}/main.cf.template" /etc/postfix/main.cf
|
||||||
|
render "${TEMPLATE_DIR}/pgsql-relay-domains.cf.template" /etc/postfix/pgsql-relay-domains.cf
|
||||||
|
render "${TEMPLATE_DIR}/pgsql-transport-maps.cf.template" /etc/postfix/pgsql-transport-maps.cf
|
||||||
|
|
||||||
|
# The pgsql lookup config files embed the database password; restrict access.
|
||||||
|
chown root:postfix /etc/postfix/pgsql-relay-domains.cf /etc/postfix/pgsql-transport-maps.cf
|
||||||
|
chmod 640 /etc/postfix/pgsql-relay-domains.cf /etc/postfix/pgsql-transport-maps.cf
|
||||||
|
|
||||||
|
postfix check
|
||||||
|
|
||||||
|
exec /usr/sbin/postfix start-fg
|
||||||
39
images/postfix-pgsql/templates/main.cf.template
Normal file
39
images/postfix-pgsql/templates/main.cf.template
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Postfix main.cf template
|
||||||
|
#
|
||||||
|
# Rendered at container startup by docker-entrypoint.sh, with values
|
||||||
|
# substituted from environment variables. See README.md for the full list
|
||||||
|
# of supported variables.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
myhostname = ${MYHOSTNAME}
|
||||||
|
mydomain = ${MAIL_DOMAIN}
|
||||||
|
myorigin = $mydomain
|
||||||
|
mydestination =
|
||||||
|
inet_interfaces = all
|
||||||
|
inet_protocols = ipv4
|
||||||
|
|
||||||
|
# Dynamic relay/transport decisions backed by PostgreSQL lookup maps.
|
||||||
|
relay_domains = pgsql:/etc/postfix/pgsql-relay-domains.cf
|
||||||
|
transport_maps = pgsql:/etc/postfix/pgsql-transport-maps.cf
|
||||||
|
|
||||||
|
# This instance only relays mail for the domains returned by relay_domains;
|
||||||
|
# it does not accept mail for arbitrary destinations.
|
||||||
|
smtpd_relay_restrictions = permit_mynetworks, reject_unauth_destination
|
||||||
|
mynetworks = 127.0.0.0/8, [::1]/128
|
||||||
|
|
||||||
|
# TLS
|
||||||
|
smtpd_tls_cert_file = ${SMTPD_TLS_CERT_FILE}
|
||||||
|
smtpd_tls_key_file = ${SMTPD_TLS_KEY_FILE}
|
||||||
|
smtpd_use_tls = yes
|
||||||
|
smtpd_tls_security_level = may
|
||||||
|
smtp_tls_security_level = may
|
||||||
|
|
||||||
|
# Log to stdout/stderr so `docker logs` captures Postfix activity directly,
|
||||||
|
# without needing a syslog daemon inside the container.
|
||||||
|
maillog_file = /dev/stdout
|
||||||
|
|
||||||
|
biff = no
|
||||||
|
append_dot_mydomain = no
|
||||||
|
readme_directory = no
|
||||||
|
compatibility_level = 3.6
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Postfix pgsql_table lookup: relay_domains
|
||||||
|
#
|
||||||
|
# Returns the domain itself when Postfix should relay mail for it.
|
||||||
|
# Rendered at container startup from environment variables.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
user = ${POSTGRES_USER}
|
||||||
|
password = ${POSTGRES_PASSWORD}
|
||||||
|
hosts = ${POSTGRES_HOST}:${POSTGRES_PORT}
|
||||||
|
dbname = ${POSTGRES_DB}
|
||||||
|
query = SELECT domain FROM relay_domain WHERE domain='%s'
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Postfix pgsql_table lookup: transport_maps
|
||||||
|
#
|
||||||
|
# Returns the internal SMTP relay target that accepted mail gets forwarded
|
||||||
|
# to once a recipient domain matches relay_domains. The target itself is
|
||||||
|
# baked into the query from SMTP_RELAY_HOST/SMTP_RELAY_PORT at startup; this
|
||||||
|
# image has no further knowledge of what consumes the mail downstream.
|
||||||
|
# Rendered at container startup from environment variables.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
user = ${POSTGRES_USER}
|
||||||
|
password = ${POSTGRES_PASSWORD}
|
||||||
|
hosts = ${POSTGRES_HOST}:${POSTGRES_PORT}
|
||||||
|
dbname = ${POSTGRES_DB}
|
||||||
|
query = SELECT 'smtp:[${SMTP_RELAY_HOST}]:${SMTP_RELAY_PORT}' FROM relay_domain WHERE domain='%s'
|
||||||
Reference in New Issue
Block a user