Last active
June 7, 2024 15:08
-
-
Save henno/c4dc7da7eca7900e52eda458de8b477b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# ABOUT THIS SCRIPT | |
# This script automates the setup of an email server on Alpine Linux using Postfix, OpenDKIM, and PostSRSd. | |
# It configures all necessary components to send and receive emails securely and handles virtual mailing lists. | |
# | |
# USAGE | |
# 1. Modify the configuration variables below to match your domain and server settings. | |
# 2. Run the script as root. | |
# 3. After running the script, ensure that you see the master process, the postsrsd process and the opendkim process in the | |
# netstat output that is shown after the script completes. | |
# 4. Run the following command to get the value of your DKIM record: | |
# echo -n 'v=DKIM1; k=rsa; '; grep -o 'p=.*' /etc/opendkim/keys/YOURDKIMSELECTOR.txt | sed 's/.*p="//;s/"[^"]*$//' | |
# 5. Go to your DNS panel and add new TXT record YOURDKIMSELECTOR._domainkey with the previous command's output as its value. | |
# 6. Install Swaks from https://jetmore.org/john/code/swaks/installation.html and send a test mail to your Gmail address. | |
# Then observe /var/log/mail.log and if the message reaches your Gmail then open the message and choose Show original from | |
# the three dots menu and check if DMARC, SPF and DKIM all are PASS. | |
# Before running, ensure you have set up DNS records as described below: | |
# | |
# DNS REQUIREMENTS | |
# 1. Ensure that the hostname (e.g., mail.example.com) has a correct PTR record, pointing back to the A record of the IP address. | |
# 2. Add a TXT record for DKIM in your DNS with the name 'example._domainkey.example.com' where example is your DKIM_SELECTOR | |
# and the value provided by the OpenDKIM key generation (this script will generate this value). | |
# 3. Ensure SPF and DMARC records are set up to enhance email deliverability and security. | |
# | |
# Ensure you modify the configuration variables below as per your domain and server settings. | |
# Configuration variables | |
MYHOSTNAME="mail.example.com" # must match the reverse DNS of the IP address that is used to send emails | |
MYDOMAIN="example.com" # the domain that is used to send emails from the server | |
DKIM_SELECTOR="example" # the DKIM selector that is listed in the DNS records of the domain | |
MYDESTINATION="localhost, ${MYHOSTNAME}, ${MYDOMAIN}, ${MYDOMAIN}.localdomain" # the destinations that the server will accept emails for | |
MAILING_LIST="list@${MYDOMAIN}" # a mailing list that will be used to send emails to multiple recipients | |
MAILING_LIST_MEMBERS="user1@example.net, user2@example.org" # mailing list members who will receive emails sent to the list | |
# Check for root privileges | |
if [ "$(id -u)" -ne 0 ]; then | |
echo "This script must be run as root." 1>&2 | |
exit 1 | |
fi | |
# Define the version of Alpine to check for the community repository | |
ALPINE_VERSION=$(cut -d'.' -f1-2 /etc/alpine-release) | |
COMMUNITY_REPO="http://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VERSION}/community" | |
# Check and ensure the community repository is in the repositories file | |
if ! grep -Fq "$COMMUNITY_REPO" /etc/apk/repositories; then | |
echo "$COMMUNITY_REPO" >> /etc/apk/repositories | |
echo "Community repository added." | |
else | |
# Ensure it's not commented out if already present | |
COMMUNITY_REPO_ESCAPED=$(echo "$COMMUNITY_REPO" | sed 's/\//\\\//g') | |
sed -i -e "/^#.*$COMMUNITY_REPO_ESCAPED/s/^#//" /etc/apk/repositories | |
fi | |
# Update and install necessary packages | |
apk update | |
apk add postfix postfix-pcre postsrsd opendkim opendkim-utils | |
# Configure Postfix | |
postconf -e "myhostname = $MYHOSTNAME" | |
postconf -e "mydestination = $MYDESTINATION" | |
postconf -e "myorigin = $MYDOMAIN" | |
postconf -e "virtual_alias_maps = lmdb:/etc/postfix/virtual" | |
postconf -e "milter_default_action = accept" | |
postconf -e "milter_protocol = 2" | |
postconf -e "smtpd_milters = inet:localhost:8891" | |
postconf -e "non_smtpd_milters = inet:localhost:8891" | |
postconf -e "relay_domains = $MYHOSTNAME" | |
postconf -e "relayhost = " | |
postconf -e "smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination" | |
postconf -e "mynetworks = 127.0.0.0/8, 10.0.0.0/8" | |
echo "$MAILING_LIST $MAILING_LIST_MEMBERS" > /etc/postfix/virtual | |
postmap /etc/postfix/virtual | |
# Configure OpenDKIM | |
mkdir -p /etc/opendkim/keys | |
chown opendkim:opendkim /etc/opendkim /etc/opendkim/keys | |
# Update OpenDKIM configuration to use the right paths | |
cat > /etc/opendkim/opendkim.conf << EOF | |
BaseDirectory /run/opendkim | |
LogWhy yes | |
Syslog yes | |
SyslogSuccess yes | |
Canonicalization relaxed/simple | |
Domain $MYDESTINATION | |
ReportAddress postmaster@$MYDOMAIN | |
SendReports yes | |
InternalHosts 127.0.0.1, 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12 | |
PidFile /var/run/opendkim/opendkim.pid | |
UserID opendkim:opendkim | |
Socket inet:8891@localhost | |
Selector $DKIM_SELECTOR | |
KeyFile /etc/opendkim/keys/${DKIM_SELECTOR}.private | |
EOF | |
opendkim-genkey -D /etc/opendkim/keys/ -d $MYHOSTNAME -s $DKIM_SELECTOR | |
chown opendkim:opendkim /etc/opendkim/keys/$DKIM_SELECTOR.private | |
# Configure PostSRSd v2 | |
cat > /etc/postsrsd/postsrsd.conf << EOF | |
# PostSRSd configuration file | |
domains = { "$MYDOMAIN" } | |
syslog = on | |
debug = on | |
socketmap = inet:localhost:10003 | |
keep-alive = 30 | |
original-envelope = embedded | |
secrets-file = "/etc/postsrsd/postsrsd.secret" | |
separator = "=" | |
hash-length = 4 | |
hash-minimum = 4 | |
always-rewrite = off | |
unprivileged-user = "postsrsd" | |
chroot-dir = "/var/lib/postsrsd" | |
EOF | |
# Create the chroot directory for PostSRSd | |
mkdir -p /etc/postsrsd/root | |
# Postfix configuration to use PostSRSd | |
postconf -e 'sender_canonical_maps = socketmap:inet:localhost:10003:forward' | |
postconf -e 'sender_canonical_classes = envelope_sender' | |
postconf -e 'recipient_canonical_maps = socketmap:inet:localhost:10003:reverse' | |
postconf -e 'recipient_canonical_classes = envelope_recipient, header_recipient' | |
# Check and set correct permissions | |
chmod 755 /var/spool/postfix | |
chmod 640 /etc/postfix/main.cf /etc/postfix/master.cf | |
chmod 700 /etc/opendkim/keys | |
chmod 600 /etc/opendkim/keys/$DKIM_SELECTOR.private | |
# Log mail and subject | |
postconf -e 'maillog_file = /var/log/mail.log' | |
echo '/^subject:/ WARN' >> /etc/postfix/header_checks | |
postconf -e 'header_checks = pcre:/etc/postfix/header_checks' | |
# Reload and restart services | |
rc-service opendkim start | |
rc-service postsrsd start | |
rc-service postfix restart | |
rc-update add postfix default | |
rc-update add opendkim default | |
rc-update add postsrsd default | |
netstat -plant |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment