iRedMail Docker Container

Disclaimer

Unfortunately this docker image is far from being truly persistent and docker-way. It is more like Ubuntu VM but inside a container.

To improve it one should use separate DB container w/ or w/o mounted volume/data-container for persistence, create setup and startup scripts and start all services inside container with startup script, not Ubuntu init.

Information

This project uses iRedMail-0.9.0 (as on 02/2015) with:

  • iRedAdmin-0.4.1
  • iRedAPD-1.4.4
  • roundcubemail-1.0.4

What is inside

Image builds with:

  • Debian Wheezy
  • OpenLDAP
  • Apache
  • Roundcube
  • SOGo
  • MySQL

Building image

1. Editing iRedMail config file

You have to edit files/config.example file:

  1. Replace "example.com" with your domain (lines marked with "!")

    • repalce dc=example,dc=com with dc=test,dc=com:

      dn=dc=test,dc=com && sed -ri 's/^!(export .*)(dc=example,dc=com)/\1'"$dn"'/' files/config.example
    • repalce example.com_ with test.com:

      fqdn=test.com && sed -ri 's/^!(export .*)(example.com)/\1'"$fqdn"'/' files/config.example
    • repalce example_ with test:

      domain=test && sed -ri 's/^!(export .*)(example)/\1'"$domain"'/' files/config.example
  2. Replace "password_pm", "password_ldap", "password_db" with postmaster password, ldap manager password, DBA password (lines marked with "!!")*

    • replace password_ldap with ldap_password:

      pass=ldap_password && sed -ri 's/^!!(export .*)(password_ldap)/\1'"$pass"'/' files/config.example
    • replace password_db with db_password:

      pass=db_password && sed -ri 's/^!!(export .*)(password_db)/\1'"$pass"'/' files/config.example
    • replace password_pm with pm_password:

      pass=pm_password && sed -ri 's/^!!(export .*)(password_pm)/\1'"$pass"'/' files/config.example
  3. Replace "password_random" with line from date | sha256sum | base64 | head -c 30 ; echo or cat /dev/urandom | head -n 1 | tr -dc 'a-z0-9' | sha256sum | base64 | head -c 30 (lines marked with "!!!")

    • replace password_random with random passwords:

      for i in {1..10}; do 
          sed -ri '0,/^!!!(export .*)(password_random)/s/^!!!(export .*)(password_random)/\1'"$(cat /dev/urandom | head -n 1 | tr -dc 'a-z0-9' | sha256sum | base64 | head -c 30)"'/' files/config.example
      done
  4. Remove all "!" signs from file and make sure everything configured

  5. Rename files/config.example to files/config

* - It is strongly recommended to use random passwords

2. Editing hostname & uname fakes

You have to edit files/hostname.example and files/uname.example files by changing hostnames in them and renaming files (removing .example from their names):

fqdn=test.com && sed -ri 's/example.com/'"$fqdn"'/' files/uname.example files/hostname.example files/mail_users.csv.example

3. Editing Dockerfile

You have to edit Dockerfile.example:

  1. Rename Dockerfile.example to Dockerfile
  2. Replace hostname and passwords near TODO comments with yours

4. (Optional) Configure mail users

You can add initial mail users to OpenLDAP:

  1. Rename mail_users.csv.example to mail_users.csv
  2. Fill this file with data (see below)
  3. For passwords please use date | sha256sum | base64 | head -c 8 ; echo

CSV file format:
domain name, username, password, [common name], [quota_in_bytes], [groups]

Example:

iredmail.org, zhang, plain_password, Zhang Huangbin, 104857600, group1:group2
iredmail.org, zhang, plain_password, Zhang Huangbin, ,
iredmail.org, zhang, plain_password, , 104857600, group1:group2

Note:

  • Domain name, username and password are REQUIRED, others are optional:
    • common name.
      • It will be the same as username if it's empty.
      • Non-ascii character is allowed in this field, they will be
        encoded automaticly. Such as Chinese, Korea, Japanese, etc.
    • quota. It will be 0 (unlimited quota) if it's empty.
    • groups.
      • valid group name (hr@a.cn): hr
      • incorrect group name: hr@a.cn
      • Do NOT include domain name in group name, it will be
        appended automaticly.
      • Multiple groups must be seperated by colon.
  • Leading and trailing Space will be ignored.

5. (Optional) Configure mail lists, modify users, tool

You can add mail lists by placing your *.ldif files into files/ldifs directory and naming them like 10_any_name.ldif.
Moreover, you can place there any *.ldif you like naming it 30_name.ldif.
To prepare your ldif files read corresponding iRedMail docs.
You can copy any necessary tools to files/tools directory to be added to image.

6. (Optional) Replacing sources.list

File sources.list.ru contains sources list for Russia, you could replace it with more adequate fro your region.

7. Building image

To build image, run:

sudo docker build -t cema/iredmail:latest .

Running image

Running with docker run

To run image use command:

sudo docker run -d -P -h mail.example.com \
  -v /opt/containers/iredmail/backups/:/backups \
  --name iredmail cema/iredmail:latest /sbin/init 2

Where /opt/containers/iredmail/backups/ is backups path in which containers /var/vmail/ directory copied.

Running with docker-compose

To run image with docker-compose you have to modify docker-compose.yml.example file:

  1. Rename file to docker-compose.yml
  2. Replace image name if you have changed it
  3. Replace hostname and domainname in file

After all run sudo docker-compose up -d

Postinstall

After starting up container:

  1. Set up DNS records (A, MX, SPF and DKIM) (see docs).
    To get DKIM use:

    sudo docker exec docker_mailserver_1 amavisd-new showkeys

To check it use:

```bash
sudo docker exec docker_mailserver_1 amavisd-new testkeys
```
  1. (Optional) if you use jwilder/nginx-proxy, copy container certs with commands:

    sudo docker cp docker_mailserver_1:/etc/ssl/certs/iRedMail.crt \
      /opt/docker/mail-server/certs/
    sudo docker cp docker_mailserver_1:/etc/ssl/private/iRedMail.key \
      /opt/docker/mail-server/certs/
    sudo mv /opt/docker/mail-server/certs/{iRedMail,mx.example.com}.crt
    sudo mv /opt/docker/mail-server/certs/{iRedMail,mx.example.com}.key

Testing container

From inside container

Enter container:

sudo docker exec -it iredmail /bin/bash

Check Manager password
ldapwhoami -x -D 'cn=Manager,dc=example,dc=com' -W

Check added domains
ldapsearch -D 'cn=Manager,dc=example,dc=com' -b 'o=domains,dc=example,dc=com' -W

See users of domain

ldapsearch -D 'cn=Manager,dc=example,dc=com' \
  -b 'ou=Users,domainName=example.com,o=domains,dc=example,dc=com' -W

Check user password

ldapsearch -D 'mail=postmaster@example.com,ou=Users,\
  domainName=example.com,o=domains,dc=example,dc=com' \
  -b 'ou=Users,domainName=example.com,o=domains,dc=example,dc=com' -W

From outside container

Check LDAP
curl ldap://0.0.0.0:49258 -v
or

curl -u uid=postmaster:password \
  ldap://0.0.0.0:49258/ou=Users,domainName=example.com,\
  o=domains,dc=example,dc=com -v

Check SMTP

curl smtp://0.0.0.0:49251 --ssl -k \
  -u postmaster@example.com:password 
  -v --mail-rcpt "postmaster@example.com" --anyauth

Maintaining container

Reading log files

Enter container:

sudo docker exec -it iredmail /bin/bash

Then use tail -f -n30 /var/log/logfilename to read logfilename.

Geting backups from container manualy

Run:
sudo docker cp iredmail:/var/vmail/* /opt/containers/iredmail/backups/

May be useful

Creating SSHA password

Create SSHA password (w/o slap utils)

#!/bin/sh
# http://wiki.nginx.org/Faq#How_do_I_generate_an_htpasswd_file_without_having_Apache_tools_installed.3F
 
PASSWORD=$1;
SALT="$(openssl rand -base64 3)"
SHA1=$(printf "$PASSWORD$SALT" | openssl dgst -binary -sha1 | sed 's#$#'"$SALT"'#' | base64);
 
printf "{SSHA}$SHA1\n"

Create SSHA password (w slap utils)

slappasswd -s passphrase

Create SSHA password (w iRedMail tools)

python /opt/itools/generate_password_hash.py SSHA passphrase

Encrypting/Decrypting files

Encrypt/Decrypt iRedMail.tips file

echo 'passphrase' | openssl enc \
  -in /opt/iredmail/iRedMail.tips \
  -out /opt/iRedMail.tips.enc \
  -e -aes256 -pass stdin
echo 'passphrase' | openssl enc \
  -in /opt/iRedMail.tips.enc \
  -out /opt/iRedMail.tips \
  -d -aes256 -pass stdin