diff --git a/.gitignore b/.gitignore index 3718fd4..1e3541e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -debug.sh -sftp-config.json -assets/domainkeys/mail.* \ No newline at end of file +.DS_Store +.env.prod +data/opendkim/* +data/.users.prod diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 5395bf5..0000000 --- a/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -From ubuntu:trusty -MAINTAINER Elliott Ye - -# Set noninteractive mode for apt-get -ENV DEBIAN_FRONTEND noninteractive - -# Update -RUN apt-get update - -# Start editing -# Install package here for cache -RUN apt-get -y install supervisor postfix sasl2-bin opendkim opendkim-tools - -# Add files -ADD assets/install.sh /opt/install.sh - -# Run -CMD /opt/install.sh;/usr/bin/supervisord -c /etc/supervisor/supervisord.conf diff --git a/LICENSE b/LICENSE index bdedff0..8244556 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Minghou Ye +Copyright (c) 2014 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/README.md b/README.md index 955a64c..2b3db56 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,93 @@ docker-postfix ============== -run postfix with smtp authentication (sasldb) in a docker container. -TLS and OpenDKIM support are optional. - -## Requirement -+ Docker 1.0 +Postfix with SMTP authentication (SASLdb) in a Docker container. +TLS and OpenDKIM are also supported. +With a simple environment and configuration file, you can set up multiple domains and email addresses. +The settings allow you to forward incoming emails to other addresses, such as Gmail. +This option can be useful if you want to use Google Gmail with your own email domain. ## Installation 1. Build image ```bash - $ sudo docker pull catatnight/postfix + $ docker compose build ``` -## Usage -1. Create postfix container with smtp authentication +## Configure the service: +There are two important files: +1. One for the environment, which should contain two variables: +``` +maindomain=example01.com +maildomains=example01.com,example02.com +``` +The `maindomain`, as its name indicates, should be the main domain of your server and will be used to set the Postfix variable `myhostname`. +The second variable, `maildomains`, is the list of domains that you want Postfix to support. This value will be used to set the Postfix `virtual_alias_domains`. +It will also be used by OpenDKIM to generate the required keys for each domain. +Please check the example file `docker/.env.example`. - ```bash - $ sudo docker run -p 25:25 \ - -e maildomain=mail.example.com -e smtp_user=user:pwd \ - --name postfix -d catatnight/postfix - # Set multiple user credentials: -e smtp_user=user1:pwd1,user2:pwd2,...,userN:pwdN - ``` -2. Enable OpenDKIM: save your domain key ```.private``` in ```/path/to/domainkeys``` +2. The second file is the list of users/emails that need to be created. We use a Docker volume to sync this file into the container path /tmp/passwd. +The file follows this format: +``` +_domain:_user:_password:_cannonical +example01.com:info@example01.com:somepassword:info.example01@gmail.com +``` +The content of this file is used to set up the SASL DB (`/etc/sasldb2`). +Additionally, it sets the Postfix `sender_canonical` and `header_checks` variables, which replace outgoing emails `_canonical` `From` values with the email address for our domain `_user`. +Please check the example file `data/.users.example`. - ```bash - $ sudo docker run -p 25:25 \ - -e maildomain=mail.example.com -e smtp_user=user:pwd \ - -v /path/to/domainkeys:/etc/opendkim/domainkeys \ - --name postfix -d catatnight/postfix - ``` -3. Enable TLS(587): save your SSL certificates ```.key``` and ```.crt``` to ```/path/to/certs``` - ```bash - $ sudo docker run -p 587:587 \ - -e maildomain=mail.example.com -e smtp_user=user:pwd \ - -v /path/to/certs:/etc/postfix/certs \ - --name postfix -d catatnight/postfix - ``` +## Start the service +All the service configurations will be performed by simply running the `setup.sh` script inside the container. This script will read the environment variables and the user list file to generate the required Postfix and OpenDKIM configuration files. +The steps to follow are: +```BASH +# login to the container +docker exec -it postfix sh + +# when you get the container prompt then you run the setup script: +./setup.sh + +# After the setup we launch the service in this order +syslogd # optional to capture opemdkim logs +opendkim # start the opmkdim service +postfix start # to start postfix +``` + +You can check if the services started properly by tailing the logs: +```BASH +tail -f /var/log/messages # sys log where you can find details about openkdim service +tail -f /var/log/postfix.log +``` + +## Setting up your DNS records: +You can find plenty documentation about this on internet but basically to have a valid smtp server running you need 3 things: +### SPF: It specifies a list of IP addresses where email messages are allowed to sent on behalf of that domain. +For instance, if you want to be able to use your SMTP server to send email from a google gmail account, then you can do something like this: +``` +Type: txt +Name: @ +Data/Value: v=spf1 mx a include:_spf.google.com -all +``` +You can use this generator: https://dmarcly.com/tools/spf-record-generator + +### DKIM: DKIM detects forged header fields and content in emails. DKIM enables the receiver to check if email headers and content have been altered in transit. +The content of this records will be automatically generated by the `setup.sh` script and it will place it in the docker volume `data/opendkim/domainkey` with the name convention `{domain}.txt`. +``` +Type: txt +Name: mail._domainkey +Data/Value: v=DKIM1; k=rsa; p={your_pub_key_generated_by_opendkim} +``` +You can use this generator: https://dmarcly.com/tools/dkim-record-generator -## Note -+ Login credential should be set to (`username@mail.example.com`, `password`) in Smtp Client -+ You can assign the port of MTA on the host machine to one other than 25 ([postfix how-to](http://www.postfix.org/MULTI_INSTANCE_README.html)) -+ Read the reference below to find out how to generate domain keys and add public key to the domain's DNS records +### DMARC: Domain-based Message Authentication Reporting & Conformance (DMARC) is an email security protocol. +You can learn more about this here (https://www.fortinet.com/resources/cyberglossary/dmarc) +Example: +``` +Type: txt +Name: _dmarc +Data/Value: v=DMARC1; p=reject; rua=mailto:your_email@here.com; adkim=s; aspf=s; +``` +You can use this generator: https://dmarcly.com/tools/dmarc-generator -## Reference -+ [Postfix SASL Howto](http://www.postfix.org/SASL_README.html) -+ [How To Install and Configure DKIM with Postfix on Debian Wheezy](https://www.digitalocean.com/community/articles/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy) -+ TBD +### My favorite validator: +I use this exceptional validator https://www.learndmarc.com/ to see if everything is working as expected. diff --git a/assets/certs/readme b/assets/certs/readme deleted file mode 100644 index 2edd6fe..0000000 --- a/assets/certs/readme +++ /dev/null @@ -1 +0,0 @@ -put your SSL certificates key(.key) and cert(.crt) here \ No newline at end of file diff --git a/assets/domainkeys/readme b/assets/domainkeys/readme deleted file mode 100644 index 625ae5a..0000000 --- a/assets/domainkeys/readme +++ /dev/null @@ -1 +0,0 @@ -put your domain key file (.private) here \ No newline at end of file diff --git a/assets/install.sh b/assets/install.sh deleted file mode 100755 index 0b2aaff..0000000 --- a/assets/install.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/bash - -#judgement -if [[ -a /etc/supervisor/conf.d/supervisord.conf ]]; then - exit 0 -fi - -#supervisor -cat > /etc/supervisor/conf.d/supervisord.conf <> /opt/postfix.sh <> /etc/postfix/sasl/smtpd.conf < /tmp/passwd -while IFS=':' read -r _user _pwd; do - echo $_pwd | saslpasswd2 -p -c -u $maildomain $_user -done < /tmp/passwd -chown postfix.sasl /etc/sasldb2 - -############ -# Enable TLS -############ -if [[ -n "$(find /etc/postfix/certs -iname *.crt)" && -n "$(find /etc/postfix/certs -iname *.key)" ]]; then - # /etc/postfix/main.cf - postconf -e smtpd_tls_cert_file=$(find /etc/postfix/certs -iname *.crt) - postconf -e smtpd_tls_key_file=$(find /etc/postfix/certs -iname *.key) - chmod 400 /etc/postfix/certs/*.* - # /etc/postfix/master.cf - postconf -M submission/inet="submission inet n - n - - smtpd" - postconf -P "submission/inet/syslog_name=postfix/submission" - postconf -P "submission/inet/smtpd_tls_security_level=encrypt" - postconf -P "submission/inet/smtpd_sasl_auth_enable=yes" - postconf -P "submission/inet/milter_macro_daemon_name=ORIGINATING" - postconf -P "submission/inet/smtpd_recipient_restrictions=permit_sasl_authenticated,reject_unauth_destination" -fi - -############# -# opendkim -############# - -if [[ -z "$(find /etc/opendkim/domainkeys -iname *.private)" ]]; then - exit 0 -fi -cat >> /etc/supervisor/conf.d/supervisord.conf <> /etc/opendkim.conf <> /etc/default/opendkim <> /etc/opendkim/TrustedHosts <> /etc/opendkim/KeyTable <> /etc/opendkim/SigningTable <> /etc/postfix/sasl/smtpd.conf <> /etc/postfix/sender_canonical + echo "/From:$_cannonical/ REPLACE From: $_user" >> /etc/postfix/header_checks +done < /tmp/passwd + +postconf -e sender_canonical_classes=envelope_sender,header_sender +postconf -e sender_canonical_maps=regexp:/etc/postfix/sender_canonical +postconf -e smtp_header_checks=regexp:/etc/postfix/header_checks + +########################## +# Setting up fordwarding # +########################## +ALL_DOMAINS="${maildomains//,/ }" +postconf -e virtual_alias_domains=$ALL_DOMAINS +postconf -e virtual_alias_maps=lmdb:/etc/postfix/virtual +while IFS=':' read -r _domain _user _pwd _cannonical; do + echo $_user $_cannonical >> /etc/postfix/virtual +done < /tmp/passwd +postmap /etc/postfix/virtual + +##################### +# Setting up loggin # +##################### +postconf -e maillog_file=/var/log/postfix.log + +############## +# opendkim # +############## +# /etc/postfix/main.cf +postconf -e milter_protocol=2 +postconf -e milter_default_action=accept +postconf -e smtpd_milters=inet:localhost:12301 +postconf -e non_smtpd_milters=inet:localhost:12301 + +cat > /etc/opendkim/opendkim.conf <> /etc/opendkim/TrustedHosts <> /etc/opendkim/TrustedHosts + echo "mail._domainkey.$domain $domain:mail:/etc/opendkim/domainkey/$domain.private" >> /etc/opendkim/KeyTable + echo "*@$domain mail._domainkey.$domain" >> /etc/opendkim/SigningTable + if [ ! -f /etc/opendkim/domainkey/$domain.private ]; then + opendkim-genkey -b 1024 -d $domain -D /etc/opendkim/domainkey -s $domain -v + chmod 400 /etc/opendkim/domainkey/$domain.private + fi + chown app-user:app-user -R /etc/opendkim/domainkey +done +IFS=$OLDIFS diff --git a/hub/alpine/Dockerfile b/hub/alpine/Dockerfile new file mode 100644 index 0000000..f10da6e --- /dev/null +++ b/hub/alpine/Dockerfile @@ -0,0 +1,31 @@ +From alpine:latest + +# Defining packages to install +ENV ESSENTIAL_PACKAGES="python3 postfix opendkim opendkim-utils" \ + UTILITY_PACKAGES="busybox mlocate vim" \ + BUILDER_PACKAGES="g++ gdbm-dev make openssl-dev" + +# Installing packages +RUN apk update && \ + apk --no-cache --progress add $ESSENTIAL_PACKAGES $UTILITY_PACKAGES $BUILDER_PACKAGES + +# building cyrus-sasl because alpine package give error +RUN wget https://github.com/cyrusimap/cyrus-sasl/releases/download/cyrus-sasl-2.1.28/cyrus-sasl-2.1.28.tar.gz && \ + tar -xvzf cyrus-sasl-2.1.28.tar.gz && \ + cd cyrus-sasl-2.1.28 && \ + ./configure --enable-plain --enable-login --enable-cram --enable-digest --enable-ntlm && \ + make && \ + make install + +# Removing non needed builder packages +RUN apk del $BUILDER_PACKAGES + +# touch log file +RUN mkdir -p /var/log && touch /var/log/postfix.log + +# setup user +RUN addgroup --gid 1000 app-user && \ + adduser --disabled-password --no-create-home --gecos "" --home /root --ingroup app-user --uid 1000 app-user && \ + addgroup app-user postfix + +WORKDIR /root