diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..08114c8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +# Override for Makefile +# Override for Makefile +[{Makefile, makefile, GNUmakefile}] +indent_style = tab +indent_size = 4 + +[Makefile.*] +indent_style = tab +indent_size = 4 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c214b6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build-harness/ +.build-harness \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f414c99 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +sudo: required +addons: + apt: + packages: + - git + - make + - curl +env: + - DOCKER_IMAGE_NAME=cloudposse/postfix +services: +- docker +install: +- make init +- make docker:login + +script: +- make docker:build + +after_success: +- make travis:docker-tag-and-push diff --git a/Dockerfile b/Dockerfile index c08196f..bd8d8a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,14 @@ +# Inspired by: +# http://uname.pingveno.net/blog/index.php/post/2014/02/01/Configure-Postfix-as-STMP-standalone-single-domain-server-using-Unix-users-and-PAM-on-Debian +# +# Test with: +# testsaslauthd -u postmaster -p password -f /var/spool/postfix/var/run/saslauthd/mux +# perl -MMIME::Base64 -e 'print encode_base64("\000postmaster\000password")' +# openssl s_client -starttls smtp -crlf -connect localhost:587 +# AUTH PLAIN AHBvc3RtYXN0ZXIAcGFzc3dvcmQ= + FROM ubuntu:14.04 -MAINTAINER Alex Sanz +MAINTAINER Cloud Posse, LLC ENV DEBIAN_FRONTEND noninteractive ENV POSTMASTER_USER postmaster ENV POSTMASTER_PASS password @@ -25,18 +34,4 @@ RUN echo "force-unsafe-io" > /etc/dpkg/dpkg.cfg.d/02apt-speedup && \ adduser --quiet --disabled-password -shell /bin/bash --home /home/$POSTMASTER_USER --gecos "Postmaster" $POSTMASTER_USER && \ echo "$POSTMASTER_USER:$POSTMASTER_PASS" | chpasswd -# Inspired by: -# http://uname.pingveno.net/blog/index.php/post/2014/02/01/Configure-Postfix-as-STMP-standalone-single-domain-server-using-Unix-users-and-PAM-on-Debian - -ADD start /start -ADD rsyslogd.conf /etc/rsyslog.d/stdout.conf -ADD master.cf /etc/postfix/ -ADD pam.d/ /etc/pam.d/ -ADD saslauthd /etc/default/saslauthd -ADD smtpd.conf /etc/postfix/sasl/smtpd.conf - -# Test with: testsaslauthd -u postmaster -p password -f /var/spool/postfix/var/run/saslauthd/mux -# perl -MMIME::Base64 -e 'print encode_base64("\000postmaster\000password")' -# openssl s_client -starttls smtp -crlf -connect localhost:587 -# AUTH PLAIN AHBvc3RtYXN0ZXIAcGFzc3dvcmQ= - +ADD rootfs / diff --git a/LICENSE b/LICENSE index d668ffd..3dc06d8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,6 @@ -Copyright (c) 2014, Alex Sanz +Original work Copyright (c) 2014, Alex Sanz +Modified work Copyright (c) 2014-2017, Cloud Posse, LLC + All rights reserved. Redistribution and use in source and binary forms, with or without @@ -11,7 +13,7 @@ modification, are permitted provided that the following conditions are met: this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -* Neither the name of the {organization} nor the names of its +* Neither the name of the Alex Sanz and Cloud Posse, LLC, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -25,4 +27,3 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4adc9c1 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +include $(shell curl --silent -o .build-harness "https://raw.githubusercontent.com/cloudposse/build-harness/master/templates/Makefile.build-harness"; echo .build-harness) \ No newline at end of file diff --git a/README.md b/README.md index 902a5d1..58e87cb 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,40 @@ +# postfix [![Travis](https://img.shields.io/travis/cloudposse/postfix.svg)]() -postfix mail server with configurable hostname and trusted hosts and proper -shutdown handling +This is project implements as a docker container a postfix mail server. It supports a configurable hostname, trusted hosts, proper +shutdown handling and mail relay (e.g. to mailgun). -Notes -=== +## Notes By default, connected rfc1918 networks are detected and allowed. Local networks (127.0.0.1, ::1) are also allowed. -Syslog -=== +## Syslog Rsyslog is started automatically and sends logs to stdout -Suggested Volumes -=== +## Suggested Volumes * `/var/spool/postfix` is the spool directory. Its also where postfix chroots to by default. * `/etc/postfix` is the configuation directory -Options -=== +## Configuration You can customize the image behavior using environmental variables or entrypoint arguments. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Enviromental Variable(s)Entrypoint OptionDescription
(use --hostname)--mail-nameMail name to use (appears in mail headers). Defaults to hostname
RELAYHOST="[relay hostname]--relayhost []The host to relay mail to.
TRUST="local" or TRUST_LOCAL="0"--trust-localTrust addresses on the lo interface. Enabled by default
TRUST="connected-rfc1918" or TRUST_CONNECTED_RFC="1"--trust-connected-rfc1918Trust all locally connected rfc1918 subnets. Enabled by default
TRUST="connected" or TRUST_CONNECTED="1"--trust-connectedTrust all addresses connected (excluding IPv6 local-link addresses). Disabled by default
TRUST="rfc1918" or TRUST_RFC1918="1"--trust-rfc1918Trust all rfc1918 address. Disabled by default
TRUST_LLA="1"--trust-llaTrust the fe80::/64 IPv6 subnet. Disabled by default
TRUST_SUBNETS="[space separated list of subnets]"--trust-subnet []Trust the specified subnet (IPv4 and IPv6 supported). Disabled by default
TRUST_INTERFACES="[space separated list of interfaces]"--trust-interface []Trust all network address on the interface (excluding IPv6 LLA). Disabled by default
--skip-trust-*Use with local, connected-rfc1918, connected, rfc1918, or lla to skip trusting it. Disabled by default
--skip-allDisable/reset all trusts. Disabled by default
+ +| Enviromental Variable(s) | Entrypoint Option | Description | +|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| +| (use --hostname) | --mail-name | Mail name to use (appears in mail headers). Defaults to hostname | +| RELAYHOST="[relay hostname] | --relayhost [] | The host to relay mail to. | +| TRUST="local" or TRUST_LOCAL="0" | --trust-local | Trust addresses on the lo interface. Enabled by default | +| TRUST="connected-rfc1918" or TRUST_CONNECTED_RFC="1" | --trust-connected-rfc1918 | Trust all locally connected rfc1918 subnets. Enabled by default | +| TRUST="connected" or TRUST_CONNECTED="1" | --trust-connected | Trust all addresses connected (excluding IPv6 local-link addresses). Disabled by default | +| TRUST="rfc1918" or TRUST_RFC1918="1" | --trust-rfc1918 | Trust all rfc1918 address. Disabled by default | +| TRUST_LLA="1" | --trust-lla | Trust the fe80::/64 IPv6 subnet. Disabled by default | +| TRUST_SUBNETS="[space separated list of subnets]" | --trust-subnet [] | Trust the specified subnet (IPv4 and IPv6 supported). Disabled by default | +| TRUST_INTERFACES="[space separated list of interfaces]" | --trust-interface [] | Trust all network address on the interface (excluding IPv6 LLA). Disabled by default | +| | --skip-trust-* | `local`, `connected-rfc1918`, `connected`, `rfc1918`, or `lla` to skip trusting it. | +| | --skip-all | Disable/reset all trusts. Disabled by default | + + diff --git a/saslauthd b/rootfs/etc/default/saslauthd similarity index 100% rename from saslauthd rename to rootfs/etc/default/saslauthd diff --git a/pam.d/smtp b/rootfs/etc/pam.d/smtp similarity index 100% rename from pam.d/smtp rename to rootfs/etc/pam.d/smtp diff --git a/master.cf b/rootfs/etc/postfix/master.cf similarity index 100% rename from master.cf rename to rootfs/etc/postfix/master.cf diff --git a/smtpd.conf b/rootfs/etc/postfix/sasl/smtpd.conf similarity index 100% rename from smtpd.conf rename to rootfs/etc/postfix/sasl/smtpd.conf diff --git a/rsyslogd.conf b/rootfs/etc/rsyslog.d/stdout.conf similarity index 100% rename from rsyslogd.conf rename to rootfs/etc/rsyslog.d/stdout.conf diff --git a/start b/rootfs/start similarity index 78% rename from start rename to rootfs/start index 38a1e21..e90dc77 100755 --- a/start +++ b/rootfs/start @@ -1,5 +1,6 @@ #!/bin/sh +SASL_PASSWD=/etc/postfix/sasl_passwd # Parse options if [ -n "$MAILNAME" ] @@ -29,6 +30,36 @@ then relayhost="$RELAYHOST" fi +if [ -n "$RELAY_AUTH_ENABLED" ] +then + relay_auth_enabled=true +else + relay_auth_enabled=false +fi + +if [ -n "$RELAY_AUTH_DOMAIN" ] +then + relay_auth_domain="$RELAY_AUTH_DOMAIN" +fi + +if [ -n "$RELAY_AUTH_USER" ] +then + relay_auth_user="$RELAY_AUTH_USER" +fi + +if [ -n "$RELAY_AUTH_PASS" ] +then + relay_auth_pass="$RELAY_AUTH_PASS" +fi + +if [ -n "$RELAY_AUTH_TLS" ] +then + relay_auth_tls=true +else + relay_auth_tls=false +fi + + if [ -n "$TRUST" ] then trust_connected_rfc1918=0 @@ -110,6 +141,11 @@ Default: --trust-local --trust-connected-rfc1918 --skip-trust-* Use with local, connected-rfc1918, connected, rfc1918, or lla to skip trusting it --skip-all Disable/reset all trusts --relayhost Sets the relay host +--relay-auth-enabled Set relay authentication enabled +--relay-auth-domain Set relay authentication domain +--relay-auth-tls Set relay authentication using TLS +--relay-auth-user Set relay authentication user +--relay-auth-pass Set relay authentication password EOF exit 1 ;; @@ -128,6 +164,45 @@ EOF fi ;; + (--relay-auth-enabled) + if [ "$2" -eq "false" ] || [ "$2" -eq "0" ] + then + relay_auth_enabled=false + else + relay_auth_enabled=true + fi + ;; + + (--relay-auth-tls) + if [ "$2" -eq "false" ] || [ "$2" -eq "0" ] + then + relay_auth_tls=false + else + relay_auth_tls=true + fi + ;; + + (--relay-auth-domain) + if [ -n "$2" ] + then + relay_auth_domain="$2" + fi + ;; + + (--relay-auth-user) + if [ -n "$2" ] + then + relay_auth_user="$2" + fi + ;; + + (--relay-auth-pass) + if [ -n "$2" ] + then + relay_auth_pass="$2" + fi + ;; + (--skip-trust-all) trust_local=0 trust_connected=0 @@ -341,14 +416,42 @@ fi # Update the hostname if [ -n "$mailname" ] then - sed -i "s#myhostname =.*#myhostname = $mailname#" /etc/postfix/main.cf + postconf -e "myhostname = $mailname" fi - seded_mynetworks=`echo $MYNETWORK | sed 's/#/\\#/g'` -sed -i -r "s#mynetworks = (.*)#mynetworks = $mynetworks#g" /etc/postfix/main.cf -sed -i -r "s#relayhost = (.*)#relayhost = $relayhost#g" /etc/postfix/main.cf +postconf -e "mynetworks = $mynetworks" + +if [ -n "$relayhost" ] +then + postconf -e "relayhost = $relayhost" +fi + +if [ -n "$relay_auth_enabled" ] +then + postconf -e 'smtp_sasl_auth_enable = yes' + postconf -e 'smtp_sasl_security_options = noanonymous' + postconf -e 'smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd' + + if [ -n "$relay_auth_tls" ] + then + postconf -e 'smtp_use_tls = yes' + postconf -e 'smtp_sasl_tls_security_options = noanonymous' + postconf -e 'smtp_tls_security_level = may' + postconf -e 'smtp_tls_note_starttls_offer = yes' + else + postconf -e 'smtp_use_tls = may' + fi + + if [ -n "$relay_auth_domain" ] && [ -n "$relay_auth_user" ] && [ -n "$relay_auth_pass" ] + then + echo "$relay_auth_domain $relay_auth_user:$relay_auth_pass" > $SASL_PASSWD + chmod 600 $SASL_PASSWD + fi + + postmap $SASL_PASSWD +fi # Utilize the init script to configure the chroot (if needed) /etc/init.d/postfix start > /dev/null @@ -382,7 +485,7 @@ pid=$! /etc/init.d/saslauthd start /etc/init.d/rsyslog start - +echo "postmaster:$POSTMASTER_PASS" | chpasswd # Loop "wait" until the postfix master exits while wait $pid; test $? -gt 128 do