mirror of
https://git.myvelabs.com/docker/myvemailbackup.git
synced 2025-12-17 19:46:18 +00:00
First commit
This commit is contained in:
commit
cd1be5abe2
6 changed files with 423 additions and 0 deletions
181
01-setup.sh
Executable file
181
01-setup.sh
Executable file
|
|
@ -0,0 +1,181 @@
|
|||
#!/usr/bin/env bash
|
||||
# Fill in the following variables
|
||||
domain= #www.google.com
|
||||
mailver= #latest/stable
|
||||
|
||||
# Exit on any error
|
||||
set -e
|
||||
|
||||
# Check for subdomain
|
||||
if [ $(echo ${domain} | awk -F . '{print $3}') ]
|
||||
then
|
||||
_subdomain=$(echo ${domain} | awk -F . '{print $1}')
|
||||
_domain="$(echo ${domain} | awk -F . '{print $2}').$(echo ${domain} | awk -F . '{print $3}')"
|
||||
else
|
||||
echo "Invalid \${domain} variable, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Variable check
|
||||
if [ -z ${domain} ]
|
||||
then
|
||||
echo "Missing variable, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Certbot
|
||||
sudo certbot certonly --nginx --non-interactive --agree-tos --no-eff-email \
|
||||
--staple-ocsp --hsts --no-redirect --renew-hook 'docker exec myvemailbackup postfix reload' \
|
||||
-m eff@${_domain} -d ${domain}
|
||||
|
||||
# Log
|
||||
[ -d ./data/log/ ] || install --directory ./data/log/
|
||||
echo | tee ./data/log/{mail,downtime}
|
||||
|
||||
# SSL
|
||||
[ -d ./data/ssl/ ] || install --directory ./data/ssl/
|
||||
sudo ln -s -f /etc/letsencrypt/live/${domain}/fullchain.pem ./data/ssl/tls.pem
|
||||
sudo ln -s -f /etc/letsencrypt/live/${domain}/privkey.pem ./data/ssl/tls.key
|
||||
|
||||
# Environment file
|
||||
[ -f ./.env ] || \
|
||||
cat >./.env <<- gen-env
|
||||
# Required
|
||||
# Mail domain
|
||||
MYVEMAIL_SUBDOMAIN=${_subdomain}
|
||||
MYVEMAIL_DOMAIN=${_domain}
|
||||
|
||||
# Webmail port
|
||||
MYVEMAIL_PORT=${proxyport}
|
||||
|
||||
# Optional
|
||||
# Version: latest or stable (defaults to latest)
|
||||
MYVEMAIL_VERSION=${mailver}
|
||||
|
||||
# Additional mail domains separated by commas
|
||||
MYVEMAIL_ADDMX=${_domain}
|
||||
|
||||
# Backup mail servers separated by commas
|
||||
MYVEMAIL_PRIMARYMX=
|
||||
|
||||
# Volumes
|
||||
MYVEMAIL_VOLUME_SSL=
|
||||
MYVEMAIL_VOLUME_LOG=
|
||||
gen-env
|
||||
|
||||
# Cleanup
|
||||
rm -r ${0} ./build/ ./README.md -f
|
||||
|
||||
# Create a downtime log
|
||||
echo >./data/log/downtime
|
||||
|
||||
# Add postqueue check systemd service
|
||||
sudo tee /etc/systemd/system/postqueue-check.service >/dev/null <<'POSTQ-SERVICE'
|
||||
[Unit]
|
||||
Description=Check postfix mail queue
|
||||
|
||||
[Service]
|
||||
ExecStart=docker exec myvemailbackup postqueue-check
|
||||
Type=oneshot
|
||||
|
||||
[Install]
|
||||
WantedBy=basic.target
|
||||
POSTQ-SERVICE
|
||||
sudo tee /etc/systemd/system/postqueue-check.timer >/dev/null <<'POSTQ-TIMER'
|
||||
[Unit]
|
||||
Description=Run postqueue-check every 5 seconds
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*:*:0/5
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
POSTQ-TIMER
|
||||
sudo systemctl enable --now postqueue-check.timer
|
||||
|
||||
# Log downtimes
|
||||
sudo install /dev/stdin /usr/local/bin/downtime-check >/dev/null <<MAILSERVER
|
||||
#!/usr/bin/env bash
|
||||
if ping -q -c 1 -W 15 1.1.1.1 >/dev/null && ping -q -c 1 -W 15 google.com >/dev/null
|
||||
then
|
||||
if [[ \$(ssh ${domain} docker container inspect -f '{{.State.Running}}' myvemail) == true ]]
|
||||
then
|
||||
exit 0
|
||||
else
|
||||
echo "${domain} was inaccessible on \$(date)" >>$(pwd)/data/log/downtime
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
MAILSERVER
|
||||
sudo tee /etc/systemd/system/downtime-check.service >/dev/null <<'MAILSERVER-SERVICE'
|
||||
[Unit]
|
||||
Description=Log downtimes
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/downtime-check
|
||||
Type=oneshot
|
||||
|
||||
[Install]
|
||||
WantedBy=basic.target
|
||||
MAILSERVER-SERVICE
|
||||
sudo tee /etc/systemd/system/downtime-check.timer >/dev/null <<'MAILSERVER-TIMER'
|
||||
[Unit]
|
||||
Description=Run primary mail server check every minute
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*:0/1
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
MAILSERVER-TIMER
|
||||
|
||||
sudo tee /etc/systemd/system/downtime-send.service >/dev/null <<'POSTQ-SERVICE'
|
||||
[Unit]
|
||||
Description=Send downtime log
|
||||
|
||||
[Service]
|
||||
ExecStart=docker exec myvemailbackup downtime-send
|
||||
Type=oneshot
|
||||
|
||||
[Install]
|
||||
WantedBy=basic.target
|
||||
POSTQ-SERVICE
|
||||
sudo tee /etc/systemd/system/downtime-send.timer >/dev/null <<'POSTQ-TIMER'
|
||||
[Unit]
|
||||
Description=Send downtime log monthly
|
||||
|
||||
[Timer]
|
||||
OnCalendar=monthly
|
||||
AccuracySec=1h
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
POSTQ-TIMER
|
||||
sudo systemctl enable --now downtime-check.timer downtime-send.timer
|
||||
|
||||
# fail2ban postfix
|
||||
sudo tee /etc/fail2ban/jail.d/postfix.local >/dev/null <<POSTFIX-FLOOD-ATTACK
|
||||
[postfix-flood-attack]
|
||||
enabled = true
|
||||
bantime = 12h
|
||||
filter = postfix-flood-attack
|
||||
action = iptables-multiport[name=postfix, port="http,https,smtp,submission,pop3,pop3s,imap,imaps,sieve", protocol=tcp]
|
||||
logpath = $(pwd)/data/log/mail
|
||||
|
||||
[postfix]
|
||||
enabled = true
|
||||
maxretry = 3
|
||||
bantime = 12h
|
||||
filter = postfix
|
||||
logpath = $(pwd)/data/log/mail
|
||||
POSTFIX-FLOOD-ATTACK
|
||||
sudo tee /etc/fail2ban/filter.d/postfix-flood-attack.conf >/dev/null <<'POSTFIX-FLOOD-ATTACK'
|
||||
[Definition]
|
||||
failregex = lost connection after AUTH from (.*)\[<HOST>\]
|
||||
ignoreregex =
|
||||
POSTFIX-FLOOD-ATTACK
|
||||
43
README.md
Normal file
43
README.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# MyveMail Backup
|
||||
|
||||
All-in-one docker container to host your own personal backup mail server, powered by Postfix mail transfer agent. If your primary mail server goes down, emails will be temporarily sent to this backup server, which then returns these emails to the primary as soon as it comes back online.
|
||||
|
||||
*Note: ISP must have SMTP Port 25 open.*
|
||||
|
||||
## :: Pre-installation
|
||||
Update your DNS registry to reflect the following records
|
||||
```
|
||||
# MX Record
|
||||
@ 300 IN MX 10 ${subdomain}.${domain}.
|
||||
|
||||
# A Record
|
||||
${subdomain} 300 IN A ${server-ip-address}
|
||||
```
|
||||
Example entries:
|
||||
```
|
||||
server-ip-address= # Host IPv4 address
|
||||
subdomain=mail
|
||||
domain=website.com
|
||||
```
|
||||
|
||||
## :: Installation
|
||||
Clone this repo and build it locally or pull it on the registry specified in docker-compose.yaml:
|
||||
|
||||
```
|
||||
git clone https://git.myvelabs.com/docker/myvemailbackup.git
|
||||
```
|
||||
|
||||
Supply the variables asked for in 01-setup.sh.
|
||||
|
||||
Run **01-setup.sh** to install the Letsencrypt certificates to be used by Postfix. It also generates a functional docker-compose env file.
|
||||
|
||||
*Note: The container will fail if this step is skipped.*
|
||||
|
||||
Once completed, the container may be brought up:
|
||||
|
||||
```
|
||||
docker compose up --detach
|
||||
```
|
||||
|
||||
## :: Post-installation
|
||||
Add the backup server's IP address to the primary mail server's Postfix **mynetworks** configuration to properly receive the bounced emails.
|
||||
28
build/Dockerfile
Normal file
28
build/Dockerfile
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# syntax = docker/dockerfile:1
|
||||
FROM alpine:edge
|
||||
|
||||
# LABEL about the custom image
|
||||
LABEL description="MyveMail Backup"
|
||||
|
||||
# Copy required files folders
|
||||
ADD run/docker-entrypoint /docker-entrypoint/
|
||||
ADD run/installer.sh /tmp/
|
||||
|
||||
# Update Ubuntu Software repository and install requisites
|
||||
RUN printf '%s\n' 'https://dl-cdn.alpinelinux.org/alpine/latest-stable/main/' \
|
||||
'https://dl-cdn.alpinelinux.org/alpine/latest-stable/community/' >/etc/apk/repositories \
|
||||
&& apk update \
|
||||
&& apk upgrade \
|
||||
&& apk add --no-cache \
|
||||
bash bash-completion ncurses \
|
||||
ca-certificates openssl \
|
||||
postfix \
|
||||
# Installer
|
||||
&& /tmp/installer.sh \
|
||||
&& rm /tmp/installer.sh
|
||||
|
||||
# Expose ports
|
||||
EXPOSE 25
|
||||
|
||||
# Entrypoint hd-wallet-derive script
|
||||
CMD ["/docker-entrypoint/entrypoint.sh"]
|
||||
75
build/run/docker-entrypoint/entrypoint.sh
Executable file
75
build/run/docker-entrypoint/entrypoint.sh
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env bash
|
||||
# Abort if an error is encountered
|
||||
set -e
|
||||
|
||||
# Exit function
|
||||
trap '[ "${?}" -ne 77 ] || exit 77' ERR
|
||||
function die
|
||||
{
|
||||
local reset="\e[0m"
|
||||
local red="\e[0m\e[0;31m"
|
||||
local yellow="\e[0m\e[0;33m"
|
||||
|
||||
echo -e "${red}
|
||||
Error encountered in the following init script:
|
||||
${yellow}
|
||||
${@}
|
||||
${red}
|
||||
Aborting...
|
||||
${reset}"
|
||||
|
||||
exit 77
|
||||
}
|
||||
|
||||
# Reset
|
||||
echo | tee /var/log/maillog /etc/postfix/{relaydomains,transportmaps,helo_access,rbl_override}
|
||||
|
||||
# Postfix
|
||||
echo ${MYVEMAIL_DOMAIN} >/etc/mailname
|
||||
postconf -e "myhostname = ${MYVEMAIL_SUBDOMAIN}.${MYVEMAIL_DOMAIN}"
|
||||
postconf -e "mydestination = \$myhostname, ${MYVEMAIL_SUBDOMAIN}.${MYVEMAIL_DOMAIN}, localhost, localhost.localdomain, localhost"
|
||||
postconf -e "mydomain = ${MYVEMAIL_DOMAIN}"
|
||||
|
||||
# resolv.conf
|
||||
[ -d /var/spool/postfix/etc/ ] || mkdir /var/spool/postfix/etc/
|
||||
cp /etc/resolv.conf /var/spool/postfix/etc/resolv.conf
|
||||
|
||||
# Add primary mail servers to mynetworks
|
||||
if [ ${MYVEMAIL_PRIMARYMX} ]
|
||||
then
|
||||
primarymx+=(${MYVEMAIL_PRIMARYMX//,/ })
|
||||
postconf -e "$(postconf mynetworks)$(printf ' %s/32' ${primarymx[@]})"
|
||||
fi
|
||||
|
||||
# Relay setup
|
||||
addmx=(${MYVEMAIL_DOMAIN})
|
||||
addmx+=(${MYVEMAIL_ADDMX//,/ })
|
||||
printf '%s OK\n' ${addmx[@]} >/etc/postfix/relaydomains
|
||||
for domain in ${addmx[@]}
|
||||
do
|
||||
echo "${domain} smtp:mail.${domain}:25" | tee -a /etc/postfix/transportmaps >/dev/null
|
||||
echo "${domain} OK" | tee -a /etc/postfix/{helo_access,rbl_override} >/dev/null
|
||||
done
|
||||
|
||||
# Start postfix
|
||||
postfix start
|
||||
postmap /etc/postfix/relaydomains /etc/postfix/transportmaps /etc/postfix/helo_access /etc/postfix/rbl_override
|
||||
postfix reload
|
||||
|
||||
# Downtime log
|
||||
install /dev/stdin /usr/local/bin/downtime <<- downtime
|
||||
#!/usr/bin/env bash
|
||||
# Send downtime log to downtime email address
|
||||
echo "From: ${MYVEMAIL_SUBDOMAIN}@${MYVEMAIL_DOMAIN}
|
||||
To: downtime@${MYVEMAIL_DOMAIN}
|
||||
Subject: Monthly downtime log
|
||||
|
||||
\$(cat /var/log/downtime)" | sendmail downtime@${MYVEMAIL_DOMAIN}
|
||||
|
||||
# Delete log to start anew
|
||||
echo >/var/log/downtime
|
||||
downtime
|
||||
|
||||
# Monitor log
|
||||
echo -e "\n\e[1;32mMail service is ready\e[0m\n"
|
||||
tail -f /var/log/maillog
|
||||
62
build/run/installer.sh
Executable file
62
build/run/installer.sh
Executable file
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
###############
|
||||
#//
|
||||
#// Postfix
|
||||
#//
|
||||
###############
|
||||
# Postfix
|
||||
postconf -e 'myorigin = $mydomain'
|
||||
postconf -e 'inet_interfaces = all'
|
||||
postconf -e 'inet_protocols = ipv4'
|
||||
postconf -e 'smtp_address_preference = ipv4'
|
||||
postconf -e 'message_size_limit = 0'
|
||||
postconf -e 'mailbox_size_limit = 0'
|
||||
|
||||
# Touch aliases db
|
||||
newaliases
|
||||
|
||||
# Logging
|
||||
postconf -e "maillog_file = /var/log/maillog"
|
||||
|
||||
# Backup mail server specific settings
|
||||
postconf -e 'maximal_queue_lifetime = 30d'
|
||||
postconf -e 'minimal_backoff_time = 60s'
|
||||
postconf -e 'relay_recipient_maps = '
|
||||
postconf -e "relay_domains = lmdb:/etc/postfix/relaydomains"
|
||||
postconf -e "transport_maps = lmdb:/etc/postfix/transportmaps"
|
||||
|
||||
# Security
|
||||
postconf -e 'smtpd_tls_security_level = may'
|
||||
postconf -e 'smtp_tls_security_level = may'
|
||||
|
||||
postconf -e 'smtpd_tls_loglevel = 1'
|
||||
postconf -e 'smtp_tls_verify_cert_match = hostname, nexthop, dot-nexthop'
|
||||
postconf -e 'smtp_tls_CApath = /etc/ssl/certs'
|
||||
postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
|
||||
postconf -e 'smtp_tls_loglevel = 1'
|
||||
openssl rehash /etc/ssl/certs || c_rehash /etc/ssl/certs
|
||||
|
||||
[ -d /etc/postfix/ssl/ ] || mkdir -p /etc/postfix/ssl/
|
||||
postconf -e "smtpd_tls_key_file = /etc/postfix/ssl/tls.key"
|
||||
postconf -e "smtpd_tls_cert_file = /etc/postfix/ssl/tls.pem"
|
||||
|
||||
# # Enforce TLSv1.2 or TLSv1.2
|
||||
postconf -e "smtpd_tls_protocols = >=TLSv1.2"
|
||||
|
||||
# Spam filters (https://www.linuxbabe.com/mail-server/block-email-spam-postfix)
|
||||
postconf -e "smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unknown_sender_domain, reject_unknown_reverse_client_hostname, reject_unknown_client_hostname"
|
||||
postconf -e "smtpd_helo_required = yes"
|
||||
postconf -e "smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, check_helo_access lmdb:/etc/postfix/helo_access, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_helo_hostname"
|
||||
postconf -e "smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"
|
||||
|
||||
# Check postqueue every 5 seconds
|
||||
install /dev/stdin /usr/local/bin/postqueue-check >/dev/null <<'postqueue'
|
||||
#!/usr/bin/env bash
|
||||
if postqueue -p | grep -q 'Mail queue is empty'
|
||||
then
|
||||
exit 0
|
||||
else
|
||||
postqueue -f
|
||||
fi
|
||||
postqueue
|
||||
34
docker-compose.yaml
Normal file
34
docker-compose.yaml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
services:
|
||||
myvemailbackup:
|
||||
image: hub.myvelabs.com/lab/myvemailbackup:${MYVEMAIL_VERSION:-latest}
|
||||
container_name: myvemailbackup
|
||||
restart: unless-stopped
|
||||
|
||||
# build: .
|
||||
|
||||
ports:
|
||||
- 25:25/tcp
|
||||
|
||||
environment:
|
||||
# Backup mmail domain details
|
||||
MYVEMAIL_SUBDOMAIN: ${MYVEMAIL_SUBDOMAIN}
|
||||
MYVEMAIL_DOMAIN: ${MYVEMAIL_DOMAIN}
|
||||
|
||||
# Primary mail domain names separated by commas
|
||||
MYVEMAIL_ADDMX: ${MYVEMAIL_ADDMX}
|
||||
|
||||
# Primary mail servers IP addresses separated by commas
|
||||
MYVEMAIL_PRIMARYMX: ${MYVEMAIL_PRIMARYMX}
|
||||
volumes:
|
||||
# Logs
|
||||
- ${MYVEMAIL_VOLUME_LOG:-./data/log/mail}:/var/log/maillog
|
||||
- ${MYVEMAIL_VOLUME_LOG:-./data/log/downtime}:/var/log/downtime
|
||||
# SSL (point to individual files in case symlinks are being used)
|
||||
- ${MYVEMAIL_VOLUME_SSL:-./data/ssl}/tls.key:/etc/postfix/ssl/tls.key
|
||||
- ${MYVEMAIL_VOLUME_SSL:-./data/ssl}/tls.pem:/etc/postfix/ssl/tls.pem
|
||||
networks:
|
||||
- myvemailbackup
|
||||
|
||||
networks:
|
||||
myvemailbackup:
|
||||
external: false
|
||||
Loading…
Add table
Add a link
Reference in a new issue