This post is part of a series on this project. Here is the series so far:
Having said in my last ‘Road to Docker’ post that I didn’t have any current plans for another post, something came up which warrants a write up here. I managed to solve the problem in question in a Dockerised fashion and I’m quite pleased with the solution. Let’s get into it….
The Backstory
After converting my web stack over to Docker recently, I had installed the WP Mail SMTP plugin in WordPress to handle mail from the site. This was required since WordPress could no longer send via a local mail setup. I configured the plugin to send via my existing mail server. This worked well for a while – then I encountered a speed bump on my road to Docker!
For some reason (I think due to an update of the WordPress container), I just stopped receiving email from the site. Upon investigation it seemed that the TLS connection was unable to be started correctly. I got the following debug log when testing mail via WordPress:
SMTP Debug:
2019-07-30 08:38:11 Connection: opening to mail.webworxshop.com:25, timeout=300, options=array (
)
2019-07-30 08:38:11 Connection: opened
2019-07-30 08:38:11 SERVER -> CLIENT: 220 mail.webworxshop.com ESMTP Postfix
2019-07-30 08:38:11 CLIENT -> SERVER: EHLO webworxshop.com
2019-07-30 08:38:11 SERVER -> CLIENT: 250-mail.webworxshop.com
250-PIPELINING
250-SIZE 30720000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
2019-07-30 08:38:11 CLIENT -> SERVER: STARTTLS
2019-07-30 08:38:11 SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
2019-07-30 08:38:12 SMTP Error: Could not connect to SMTP host.
2019-07-30 08:38:12 CLIENT -> SERVER: QUIT
2019-07-30 08:38:12 SERVER -> CLIENT:
2019-07-30 08:38:12 SMTP ERROR: QUIT command failed:
2019-07-30 08:38:12 Connection: closed
2019-07-30 08:38:12 SMTP Error: Could not connect to SMTP host.
Looking into the logs on the mail server, I found the following corresponding error:
warning: TLS library problem: 27261:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1275:SSL alert number 40:
I tried googling the error, but after trying a few of the suggested fixes, I gave up and decided to solve the problem a different way.
Fixing it, Take 1
My first attempt involved installing Postfix on the host in a smarthost configuration to my main server. This is the same setup as I use on most of my servers for system mail from cron, etc (via a custom Ansible role).
After getting the mail system running and able to send mail from the host, I tried to configure it in WordPress. However, I was unable to connect to the host machine from the container on the Docker host IP address. I investigated this and found that because I was using a private network the IP address was different than the standard Docker interface address.
Trying this address didn’t work either. Perhaps this is a security feature in Docker, or perhaps I was doing it wrong. Either way it pushed me on to a better solution.
Fixing it, Take 2
My next plan involved putting Postfix into a container. This would be put on the same private network as the WordPress container to allow access. I needed to keep the smarthost configuration to talk to the main mailserver. A quick search turned up a suitable image in the form of boky/postfix. This image is intended exactly for this purpose and I was able to set it up without too much trouble.
To spin this up I added the following to my previous docker-compose.yml
file:
postfix:
image: boky/postfix
ports:
- "127.0.0.1:587:587"
environment:
HOSTNAME: ${POSTFIX_HOSTNAME}
RELAYHOST: ${POSTFIX_RELAYHOST}
RELAYHOST_USERNAME: ${POSTFIX_RELAYHOST_USERNAME}
RELAYHOST_PASSWORD: ${POSTFIX_RELAYHOST_PASSWORD}
RELAYHOST_TLS_LEVEL: "verify"
ALLOWED_SENDER_DOMAINS: webworxshop.com
volumes:
- /home/rob/docker-data/postfix/spool:/var/spool/postfix
networks:
- internal
restart: always
Pretty simple! As per the previous post I put all the secrets into an env.sh
file to keep them separate from the stack.
The mail forwarder is available both on the internal
Docker network and on the host system to replace the native mail forwarding setup. Setting this up with WordPress ended up being trivial (see screenshot below). However, I required some further configuration to make the mail on the host system work.
MSMTP Setup
In order to redirect the system mail from the host via the Dockerised mail forwarder, I had to set up MSMTP. This is pretty effectively documented elsewhere, so I won’t go into details. The only differences in this setup are that we don’t require authentication or TLS to the mail forwarder because it’s only available locally. The mail forwarder itself is already handling authentication and TLS to the main mail server.
For reference, here is the msmtprc
file I ended up with:
# Set default values for all following accounts.
defaults
auth off
tls off
logfile /var/log/msmtp/msmtp.log
# Local mailserver
account local
host localhost
port 587
from someone@example.com
# Set a default account
account default : local
aliases /etc/aliases
Conclusion
Here we’ve seen how to quickly deploy a mail forwarding server for your Dockerised applications. We’ve also configured our host system to also use it, so we don’t need to run two forwarders.
I feel that this is the best solution to this problem (although I still don’t quite know what the original problem was!). It feels like a nicer solution than my original solution of running the mail forwarder locally. It has also resulted in one more Dockerised application!
I’m intending to convert my other Docker servers over to this approach in the near future. For the system mail part, I still need to create an Ansible role to push out the MSMTP configuration. Actually, the whole question of Ansible/host configuration and how it fits with Dockerised services is still something I need to work out. If anyone has any ideas feel free to share in the comments.
As I said in the last post, I don’t have any more ‘Road to Docker’ posts planned in the immediate future. However, the migration is ongoing so there will be more at some point!
Leave a Reply