diff --git a/Dockerfile b/Dockerfile index 1d15cb9..5063ed3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,7 @@ RUN set -x \ RUN set -x \ && export DEBIAN_FRONTEND=noninteractive \ && apt-get update \ - && apt-get install -y --no-install-recommends postfix mailutils busybox-syslogd opendkim opendkim-tools libsasl2-modules sasl2-bin curl ca-certificates procps s6 \ + && apt-get install -y --no-install-recommends postfix mailutils busybox-syslogd opendkim opendkim-tools libsasl2-modules sasl2-bin curl ca-certificates procps s6 inotify-tools \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* \ ; diff --git a/Makefile b/Makefile index 82b2af7..bcdb2df 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ run: ## Runs the docker image in a test mode -e MAILNAME=mail.example.com \ -e SIZELIMIT=20480000 \ -e LOGOUTPUT=/var/log/maillog \ + -e CONFIG_RELOADER_ENABLED=true \ -e POSTFIX_EXPORTER_ENABLED=false $(IMAGE_NAME):$(TAG))) $(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID})) @echo "Running ${ID} @ smtp://${IP}" @@ -26,6 +27,7 @@ run-dkim: dkim.key ## Runs the docker image in a test mode with DKIM $(eval ID := $(shell docker rm -f $(NAME) >/dev/null 2>&1; docker run -d --name $(NAME) --hostname mail.example.com \ -e RELAYHOST=172.17.0.2 \ -e MAILNAME=mail.example.com \ + -e CONFIG_RELOADER_ENABLED=true \ -e USE_DKIM=yes -v `pwd`/dkim.key:/etc/opendkim/dkim.key $(IMAGE_NAME):$(TAG))) $(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID})) @echo "Running ${ID} @ smtp://${IP}" diff --git a/README.md b/README.md index c260bd0..dbc7f3c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ This image is available on quay.io `quay.io/panubo/postfix` and AWS ECR Public ` - `MYNETWORKS` - comma separated list of IP subnets that are allowed to relay. Default `127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16` - `LOGOUTPUT` - Log file location. eg `/var/log/maillog`. Default `/dev/stdout`. See [Logging](#logging) - `TZ` - set timezone. This is used by Postfix to create `Received` headers. Default `UTC`. -- `POSTFIX_EXPORTER_ENABLED` - enable the postfix_exporter. Default `false`. See [Postfix Exporter](#postfix-exporter) +- `POSTFIX_EXPORTER_ENABLED` - enable the Prometheus postfix_exporter. Default `false`. See [Postfix Exporter](#postfix-prometheus-exporter) **General Postfix:** @@ -90,7 +90,13 @@ POSTCONF=masquerade_domains=foo.example.com example.com;masquerade_exceptions=ro Would result in `masquerade_domains` and `masquerade_exceptions` being configured for Postfix. -## Postfix Exporter +**Config Reloader** + +The config reloader watches the known TLS cert and keys (`TLS_CRT`, `TLS_KEY` etc) for changes (`mv` or updated Kubernetes secret) then reloads Postfix. + +- `CONFIG_RELOADER_ENABLED` - Enable the config reloader. Default `false`, must be set to `true` to enable. + +## Postfix Prometheus Exporter This image comes with [kumina/postfix_exporter](https://github.com/kumina/postfix_exporter) pre-installed. To enable set the environment variable `POSTFIX_EXPORTER_ENABLED=true` (this must be exactly "true"). The exporter requires that the logoutput is `/dev/stdout` it can't be anything else. @@ -100,13 +106,13 @@ See [Logging](#logging) ## Logging -This container outputs the postfix mail log to stdout by default, additionally logs are saved to `/var/log/s6-maillog/current` which is rotated every 10MB with only 3 log files retained. +This container outputs the Postfix mail log to stdout by default, additionally logs are saved to `/var/log/s6-maillog/current` which is rotated every 10MB with only 3 log files retained. If you want to output somewhere else you can set environment variable `LOGOUTPUT`. For example `LOGOUTPUT=/var/log/maillog`. When enabled OpenDKIM only supports syslog output, the syslogd daemon is only used for OpenDKIM. Only /dev/stdout is supported for OpenDKIM syslog logs. -_Note: the postfix exporter only works when the logs are left at /dev/stdout. This requirement of logs going to /dev/stdout is due to the containers logging structure. This may be improved but was needed to keep with backwards compatibility without adding additional variables to configured_ +_Note: the Postfix Prometheus exporter only works when the logs are left at /dev/stdout. This requirement of logs going to /dev/stdout is due to the containers logging structure. This may be improved but was needed to keep with backwards compatibility without adding additional variables to configured_ _Note: The log `/var/log/s6-maillog/current` is always created but won't actually contain any logs if `LOGOUTPUT` is not `/dev/stdout`._ diff --git a/s6/config-reloader/finish b/s6/config-reloader/finish new file mode 100755 index 0000000..8c281d2 --- /dev/null +++ b/s6/config-reloader/finish @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +: "${CONFIG_RELOADER_ENABLED:=false}" + +if [[ "${CONFIG_RELOADER_ENABLED}" == "true" ]]; then + # Shutdown everything and exit the process crashes or is stopped. + s6-svscanctl -t /etc/s6 +fi diff --git a/s6/config-reloader/run b/s6/config-reloader/run new file mode 100755 index 0000000..a4ca461 --- /dev/null +++ b/s6/config-reloader/run @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# This script watches the known TLS cert and keys for changes (`mv` or updated Kubernetes secret) then reloads postfix. + +: "${CONFIG_RELOADER_ENABLED:=false}" + +if [[ "${CONFIG_RELOADER_ENABLED}" != "true" ]]; then + echo "config-reloader >> Config reloader is not being started" + s6-svc -d "$(pwd)" + exit +fi + +watch_files=( + "${TLS_CRT:-/etc/ssl/certs/ssl-cert-snakeoil.pem}" + "${TLS_KEY:-/etc/ssl/private/ssl-cert-snakeoil.key}" + "${CLIENT_TLS_KEY:-/etc/ssl/certs/ssl-cert-snakeoil.pem}" + "${CLIENT_TLS_CRT:-/etc/ssl/private/ssl-cert-snakeoil.key}" +) + +# Start infinite loop +while true; do + postfix reload + echo "config-reloader >> Waiting on config changes..." + # delete_self is the event that triggers when the link is removed and replaced. + inotifywait --event delete_self "${watch_files[@]}" + # sleep to prevent race condition + sleep 3 +done