By all accounts setting-up your own mail server can be a complex task and one I’ve always shied away from until recently when I thought I’d give iRedMail a go. Thanks to this open-source mail server solution I now have my own fully-functioning, well-configured mail server handling mail for numerous mail accounts on several domains.
Getting to this stage wasn’t easy, but not the nightmare it is often portrayed as. I relied heavily on these excellent guides to get the mail server up-and-running: How to Easily Set Up a Full-Featured Mail Server on Ubuntu 18.04 with iRedMail and How to Host Multiple Mail Domains in iRedMail with Nginx and then the official iRedMail documentation to fine tune the components.
During testing I re-provisioned the mail server many, many, many times and developed my own way of doing things, some of which may be useful to others.
Please note that the following were tested using iRedMail version 1.3.1.
Table of Contents
1. Create New Mail Domains from the Command Line
During installation iRedMail configures a single mail domain. Additional mail domains can be added using iRedAdmin – the iRedMail web admin panel. During testing a more efficient, consistent and convenient way for me to create new mail domains was from the MySQL command-line client.
To invoke the MySQL client as root:
sudo mysql -u root
To create the new mail domain:
SET @DOMAIN:='domain.com';
INSERT INTO `vmail`.`domain` (`domain`, `transport`, `settings`, `created`, `active`) VALUES (@DOMAIN, 'dovecot', 'default_user_quota:512;', NOW(), '1');
To display the newly created mail domain record:
SELECT `domain`, `transport`, `settings`, `created`, `active` FROM `vmail`.`domain` WHERE `domain`=@DOMAIN;
2. Create New Mail Accounts from the Command Line
iRedMail ships with a script – create_mail_user_SQL.sh
– to create mail accounts from the command line. The script requires two parameters – email address and password:
ADDRESS='steve@example.com'; \ PASSWORD='pAss71woRd'; \ cd ${HOME}/iRedMail-1.3.1/tools; \ bash create_mail_user_SQL.sh $ADDRESS $PASSWORD > user.sql; \ sudo mysql -u root -p -D vmail -e "SOURCE user.sql"; \ rm -f user.sql
The script does not allow the user’s quota to be set on an individual basis without amending the hard-coded value in the script file each time nor does it capitalise the first letter of the user’s name – steve
instead of Steve
– which is derived from the user’s email address.
Using sed
the original script can be amended so that it accepts the user’s quota as a third parameter and automatically capitalises the user’s first name. The differences between the original and amended script are detailed here:
sed -i.$(date +"%Y%m%d-%H%M%S") -e "s/^DEFAULT_QUOTA='1024'/DEFAULT_QUOTA=\$3/" -e "s/X'2'/X'3'/" -e "s/ltd plain_password/ltd plain_password mail_quota/" -e "s/'\${username}'/\"\$(echo \${username} | awk '{print toupper(substr(\$0,0,1))tolower(substr(\$0,2))}')\"/" $HOME/iRedMail-1.3.1/tools/create_mail_user_SQL.sh
The script can now be run with with a value for the user’s quota. Note that a value of 0
means there is no restriction on the size of the mailbox:
ADDRESS='steve@example.com'; \ PASSWORD='pAss71woRd'; \ QUOTA='0'; \ cd ${HOME}/iRedMail-1.3.1/tools; \ bash create_mail_user_SQL.sh $ADDRESS $PASSWORD $QUOTA > user.sql; \ sudo mysql -u root -p -D vmail -e "SOURCE user.sql"; \ rm -f user.sql
3. SOGo and Memcached
If you opted to have SOGo installed by the iRedMail installer you may see a lot of errors afterward containing SERVER HAS FAILED AND IS DISABLED UNTIL TIMED RETRY
in /var/log/sogo/sogo.log
and when the script /var/vmail/backup/backup_sogo.sh
is executed (usually as a daily cronjob). This is due to Memcached either not being installed or the Memcached server not running.
On Ubuntu, to check if Memcached is installed:
dpkg -L memcached
dpkg-query: package 'memcached' is not installed Use dpkg --info (= dpkg-deb --info) to examine archive files, and dpkg --contents (= dpkg-deb --contents) to list their contents.
/. /etc /etc/default /etc/default/memcached /etc/init.d /etc/init.d/memcached /lib /lib/systemd /lib/systemd/system /lib/systemd/system/memcached.service /usr /usr/bin /usr/bin/memcached /usr/include /usr/include/memcached /usr/include/memcached/protocol_binary.h /usr/lib /usr/lib/tmpfiles.d /usr/lib/tmpfiles.d/memcached.conf /usr/share /usr/share/doc /usr/share/doc/memcached /usr/share/doc/memcached/NEWS.Debian.gz /usr/share/doc/memcached/NEWS.gz /usr/share/doc/memcached/README.Debian /usr/share/doc/memcached/README.md /usr/share/doc/memcached/changelog.Debian.gz /usr/share/doc/memcached/copyright /usr/share/doc/memcached/protocol.txt.gz /usr/share/man /usr/share/man/man1 /usr/share/man/man1/memcached.1.gz /usr/share/memcached /usr/share/memcached/memcached.conf.default /usr/share/memcached/scripts /usr/share/memcached/scripts/README.damemtop /usr/share/memcached/scripts/damemtop /usr/share/memcached/scripts/damemtop.yaml /usr/share/memcached/scripts/memcached-tool /usr/share/memcached/scripts/start-memcached /usr/share/memcached/scripts/systemd-memcached-wrapper
To install Memcached:
sudo apt-get install -y memcached
After installing Memcached you’d be forgiven for thinking the Memcached server has started and is running without issue. To check the status of Memcached:
sudo systemctl status memcached
● memcached.service - memcached daemon Loaded: loaded (/lib/systemd/system/memcached.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2019-12-29 07:32:50 GMT; 2s ago Docs: man:memcached(1) Main PID: 19952 (memcached) Tasks: 10 (limit: 4583) CGroup: /system.slice/memcached.service └─19952 /usr/bin/memcached -u memcache -l 127.0.0.1
● memcached.service - memcached daemon Loaded: loaded (/lib/systemd/system/memcached.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Sun 2019-12-29 07:20:23 GMT; 7min ago Docs: man:memcached(1) Process: 19857 ExecStart=/usr/share/memcached/scripts/systemd-memcached-wrapper /etc/memcached.conf (code=exited, status=64) Main PID: 19857 (code=exited, status=64) Dec 29 07:20:23 mail.example.com systemd[1]: memcached.service: Service hold-off time over, scheduling restart. Dec 29 07:20:23 mail.example.com systemd[1]: memcached.service: Scheduled restart job, restart counter is at 5. Dec 29 07:20:23 mail.example.com systemd[1]: Stopped memcached daemon. Dec 29 07:20:23 mail.example.com systemd[1]: memcached.service: Start request repeated too quickly. Dec 29 07:20:23 mail.example.com systemd[1]: memcached.service: Failed with result 'exit-code'. Dec 29 07:20:23 mail.example.com systemd[1]: Failed to start memcached daemon.
When failing to start, the status messages don’t really give any clues as to why, but looking at /var/log/syslog
specifically for the Failed to start memcached daemon
message gives a clue: can't run as root without the -u switch
sudo grep -B 8 'Failed to start memcached daemon' /var/log/syslog
Dec 29 07:20:22 mail systemd-memcached-wrapper[19857]: can't run as root without the -u switch
Dec 29 07:20:22 mail systemd[1]: memcached.service: Main process exited, code=exited, status=64/n/a
Dec 29 07:20:22 mail systemd[1]: memcached.service: Failed with result 'exit-code'.
Dec 29 07:20:23 mail systemd[1]: memcached.service: Service hold-off time over, scheduling restart.
Dec 29 07:20:23 mail systemd[1]: memcached.service: Scheduled restart job, restart counter is at 5.
Dec 29 07:20:23 mail systemd[1]: Stopped memcached daemon.
Dec 29 07:20:23 mail systemd[1]: memcached.service: Start request repeated too quickly.
Dec 29 07:20:23 mail systemd[1]: memcached.service: Failed with result 'exit-code'.
Dec 29 07:20:23 mail systemd[1]: Failed to start memcached daemon.
To start the Memcached server – not as root
, but as user memcache
– add the following line to the file /etc/memcached.conf
:
-u memcache -l 127.0.0.1
Start the Memcached server:
sudo systemctl start memcached
4. Fail2ban Log File
The Fail2ban log file at /var/log/fail2ban.log
contains notifications of IP addresses first banned and subsequently unbanned from accessing your mail server.
The log file is initially created as owned by user syslog
with read/write
permissions and group adm
with read-only
permissions:
ls -lah /var/log/fail2ban.log
-rw-r----- 1 syslog adm 13K Sep 15 14:15 /var/log/fail2ban.log
The Faile2ban log file is rotated on a weekly basis when /var/log/fail2ban.log
becomes /var/log/fail2ban.log.1
and a new /var/log/fail2ban.log
is created. However, the newly created file is now owned by root
and consequently notifications will no longer be written to the new Fail2ban log file and it will remain empty:
ls -lah /var/log/fail2ban.log
-rw-r----- 1 root adm 0K Sep 20 06:25 /var/log/fail2ban.log
The reason for this change in ownership is due to the Logrotate configuration file for Fail2ban:
cat /etc/logrotate.d/fail2ban
/var/log/fail2ban.log {
...
# If fail2ban runs as non-root it still needs to have write access
# to logfiles.
# create 640 fail2ban adm
create 640 root adm
}
The line responsible for the Fail2ban log’s change in ownership is create 640 root adm
. Change this to create 640 syslog adm
and in future and any /var/log/fail2ban.log
will be writable:
sudo sed -i.$(date +"%Y%m%d-%H%M%S") 's/create 640 root adm/create 640 syslog adm/' /etc/logrotate.d/fail2ban && cat /etc/logrotate.d/fail2ban
/var/log/fail2ban.log { ... # If fail2ban runs as non-root it still needs to have write access # to logfiles. # create 640 fail2ban adm create 640 syslog adm }
If you have an existing /var/log/fail2ban.log
owned by root, change its ownership:
sudo chown syslog /var/log/fail2ban.log
Excellent write-up. I suggest to submit a pull request to improve the create-user shell script.