You can create your own mail server in a jiffy.
- Preconfigured Postfix/Dovecot/SpamAssassin/Fail2ban.
- Move mail from/to Spam folder to train bayers filter.
- Manage domains and mailboxes from web by PostfixAdmin.
- A webmail system powered by RainLoop community edition.
- Certbot!!!
Suppose you're doing these on a brand new machine.
Modify docker-compose.yml
, expose NGINX service to port 80
- - "127.0.0.1:20007:80"
+ - "80:80"
And bring it up
$ docker-compose up -d nginx
$ docker-compose run --rm certbot certonly --webroot /known -d mail.your.domain -d another.host -d another.domain --cert-name mail
You'll be asked for few questions for authenticating
Then, link the key and cert.
# *MUST* enter data/cert before linking
$ cd data/cert
$ ln -s live/mail/fullchain.pem mail.pem
$ ln -s live/mail/privkey.pem mail.key
Certbot will periodically renewal your certification via cron.
PostfixAdmin needs your password to be:
- Minimum length is 5.
- At least 3 characters.
- At least 2 digits.
You have to manually edit the data/config.inc.php
to loosen/tighten these restrictions before running install script.
After deciding your setup_password, run install.sh
with it:
$ ./install.sh my_secert_password_for_postfix_admin
$ docker-compose up -d
RainLoop provides a defult administrator account admin
/12345
, which is VERY dangerous at this point.
Navigate to http://mail.your.domain/?admin
to change password IMMEDIATELY!!!
- IMAP: set server to
dovecot
, port to993
and usingSSL/TLS
. - SMTP: set server to
postfix
, port to587
and usingSTARTTLS
. - Don't forget to check the
Use authentication
- Setting
White List
and enable2-Step Verification
is always a good idea for better security.
Here's a modified Rainloop change password plugin (all credits to original author) at assets/change-password-mysql
, just copy it into RainLoop plugin directory with cp -r assets/change-password-mysql data/webmail/data/_data_/_default_/plugins/
, and enable it at web ui.
Since RainLoop is written with PHP, you'll have to modify BOTH PHP and NGINX settings. Say you're setting it to around 10M:
- Add
client_max_body_size 10m;
indata/nginx.conf
. - Create
data/php-upload-size.ini
with following contents:
upload_max_filesize = 10M
post_max_size = 10M
- Modify
docker-compose.yml
, add- "./data/php-upload-size.ini:/usr/local/etc/php/conf.d/php-upload-size.ini"
tophp
'svolumes
. docker-compose restart nginx
to restart NGINX container.docker-compose up -d
to recreate PHP container.
- Navigate to
http://mail.your.domain/_postadmin/setup.php
and create an administrator account. - Use that account to log into
http://mail.your.domain/_postadmin/index.php
and setup mail domains and mailboxes. - Optionally, remove
data/postadmin/setup.php
to lower security risk a bit.
By using HTTPS/HTTP2, your RainLoop/PostfixAdmin is free from fearing of MITM attack.
For best extensibility, I personally suggest you to host a reverse proxy in front of these docker service.
So we got to revert the settings of NGINX container back.
$ git checkout docker-compose.yml
$ docker-compose up -d nginx
As an example, I'll use NGINX on bare metal as reverse proxy below.
# install nginx (Debian for example)
$ apt-get install -y nginx-light
Create dhparam.pem
for NGINX
$ openssl dhparam -out /etc/nginx/dhparams.pem 2048
I'd like to limit access to admin panels from only trusted IP. Here's the configuration:
server {
server_name mail.* smtp.* imap.*;
listen 80;
# this is for Certbot
location /.well-known/ {
proxy_pass http://127.0.0.1:20007;
include proxy_params;
}
location /_postadmin/ {
# allow accessing from 127.0.0.1
allow 127.0.0.1;
deny all;
proxy_pass http://127.0.0.1:20007;
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
# complex setting for RainLoop
# 1. no limit for trusted ip
# 2. return 404 for admin panel
# 3. redirect other requests to HTTPS
set $disallow 0;
set $redir 1;
if ($request ~* admin) {
set $disallow 1;
}
# trust 127.0.0.1
if ($remote_addr = "127.0.0.1")
set $disallow 0;
set $redir 0;
}
if ($redir) {
return 301 https://$host$uri;
}
if ($disallow) {
return 404;
}
proxy_pass http://127.0.0.1:20007;
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
server {
server_name mail.* smtp.* imap.*;
include ssl_params;
ssl_certificate /home/ronmi/docker/mail/data/cert/mail.pem;
ssl_certificate_key /home/ronmi/docker/mail/data/cert/mail.key;
location /_postadmin/ {
# allow accessing from 127.0.0.1
allow 127.0.0.1;
deny all;
proxy_pass http://127.0.0.1:20007;
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
# complex setting for RainLoop
# 1. no limit for trusted ip
# 2. return 404 for admin panel
set $disallow 0;
if ($request ~* admin) {
set $disallow 1;
}
# trust 127.0.0.1
if ($remote_addr = "127.0.0.1")
set $disallow 0;
}
if ($disallow) {
return 404;
}
proxy_pass http://127.0.0.1:20007;
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Wish you a secured mail server.