mlan/kopano

By mlan

Updated over 3 years ago

This (non official) repository provides dockerized web mail service, ActiveSync and more

Image
0

7.0K

The mlan/kopano repository

travis-ci testdocker buildimage Sizedocker pullsdocker starsgithub stars

This (non official) repository provides dockerized web mail service as well as Exchange ActiveSync (EAS), IMAP, POP3 and ICAL service (and their secure variants IMAPS, POP3S and ICALS). It is based on Kopano core components, as well as the Kopano WebApp and Z-Push. The image uses nightly built packages which are provided by the Kopano community.

Hopefully this repository can be retired once the Kopano community make official images available. To learn more about this activity see zokradonh/kopano-docker.

Features

  • Kopano WebApp the main client to access all the features provided by Kopano core
  • Exchange ActiveSync (EAS) server Z-Push
  • IMAP, POP3 and ICAL services provided by Kopano core
  • Secure protocols IMAPS, POP3S and ICALS
  • Hooks for integrating Let’s Encrypt LTS certificates using the reverse proxy Traefik
  • Multi-staged build providing the images full and core
  • Configuration using environment variables
  • Log directed to docker daemon with configurable level
  • Built in utility script run helping configuring Kopano components, WebApp and Z-Push
  • Move to public with LDAP lookup
  • Crontab support.
  • Health check
  • Hook for theming
  • Demo based on docker-compose.yml and Makefile files

Tags

The mlan/kopano repository contains a multi staged built. You select which build using the appropriate tag.

The version part of the tag is not based on the version of this repository. It is instead, based on the combined revision numbers of the nightly Kopano core and Kopano WebApp package suits that was available when building the images. For example, 8.7.80-3.5.2 indicates that the image was built using the 8.7.80 version of Kopano core and 3.5.2 version of Kopano WebApp.

The build part of the tag is one of full and core. The image with tag full contain Kopano core components, as well as, the Kopano WebApp and Z-Push. The image with tag core contains the Kopano core components proving the server and IMAP, POP3 and ICAL access, but no web access.

The tags latest, full, or core all reference the most recent builds.

To exemplify the usage of the tags, lets assume that the latest version tag is 8.7.80-3.5.2. In this case latest, 8.7.80-3.5.2, full, and full-8.7.80-3.5.2 all identify the same image.

Usage

In most use cases the mlan/kopano container also needs a SQL database (e.g., MySQL or MariaDB), Mail Transfer Agent (e.g., Postfix) and authentication (e.g., OpenLDAP). Docker images of such services are available.

Often you want to configure Kopano and its components. There are different methods available to achieve this. You can use the environment variables described below set in the shell before creating the container. These environment variables can also be explicitly given on the command line when creating the container. They can also be given in an docker-compose.yml file (and the .env file), see below. Moreover docker volumes or host directories with desired configuration files can be mounted in the container. And finally you can exec into a running container and modify configuration files directly.

The docker compose example below is used to demonstrate how to configure these services.

Docker compose example

An example of how to configure an web mail server using docker compose is given below. It defines 4 services, app, mta, db and auth, which are the web mail server, the mail transfer agent, the SQL database and LDAP authentication respectively.

version: '3'

services:
  app:
    image: mlan/kopano
    networks:
      - backend
    ports:           # Expose ports to host interfaces
      - "80:80"      # WebApp & EAS (alt. HTTP)
      - "143:143"    # IMAP (not needed if all devices can use EAS)
      - "110:110"    # POP3 (not needed if all devices can use EAS)
      - "8080:8080"  # ICAL (not needed if all devices can use EAS)
      - "993:993"    # IMAPS (not needed if all devices can use EAS)
      - "995:995"    # POP3S (not needed if all devices can use EAS)
      - "8443:8443"  # ICALS (not needed if all devices can use EAS)
    depends_on:
      - auth
      - db
      - mta
    environment: # Virgin config, ignored on restarts unless FORCE_CONFIG given.
      - USER_PLUGIN=ldap
      - LDAP_URI=ldap://auth:389/
      - MYSQL_HOST=db
      - SMTP_SERVER=mta
      - LDAP_SEARCH_BASE=${AD_BASE-dc=example,dc=com}
      - LDAP_USER_TYPE_ATTRIBUTE_VALUE=${AD_USR_OB-kopano-user}
      - LDAP_GROUP_TYPE_ATTRIBUTE_VALUE=${AD_GRP_OB-kopano-group}
      - LDAP_GROUPMEMBERS_ATTRIBUTE_TYPE=dn
      - LDAP_PROPMAP=
      - DAGENT_PLUGINS=movetopublicldap
      - MYSQL_DATABASE=${MYSQL_DATABASE-kopano}
      - MYSQL_USER=${MYSQL_USER-kopano}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD-secret}
      - IMAP_LISTEN=*:143                       # also listen to eth0
      - POP3_LISTEN=*:110                       # also listen to eth0
      - ICAL_LISTEN=*:8080                      # also listen to eth0
      - IMAPS_LISTEN=*:993                      # enable TLS
      - POP3S_LISTEN=*:995                      # enable TLS
      - ICALS_LISTEN=*:8443                     # enable TLS
      - PLUGIN_SMIME_USER_DEFAULT_ENABLE_SMIME=true
      - SYSLOG_LEVEL=${SYSLOG_LEVEL-3}
      - LOG_LEVEL=${LOG_LEVEL-3}
    volumes:
      - app-conf:/etc/kopano
      - app-atch:/var/lib/kopano/attachments
      - app-sync:/var/lib/z-push
      - app-spam:/var/lib/kopano/spamd          # kopano-spamd integration
      - /etc/localtime:/etc/localtime:ro        # Use host timezone
    cap_add: # helps debugging by allowing strace
      - sys_ptrace

  mta:
    image: mlan/postfix-amavis
    hostname: ${MAIL_SRV-mx}.${MAIL_DOMAIN-example.com}
    networks:
      - backend
    ports:           # Expose ports to host interfaces
      - "25:25"      # SMTP
      - "465:465"    # SMTPS authentication required
    depends_on:
      - auth
    environment: # Virgin config, ignored on restarts unless FORCE_CONFIG given.
      - LDAP_HOST=auth
      - VIRTUAL_TRANSPORT=lmtp:app:2003
      - LDAP_USER_BASE=ou=${AD_USR_OU-users},${AD_BASE-dc=example,dc=com}
      - LDAP_QUERY_FILTER_USER=(&(objectclass=${AD_USR_OB-kopano-user})(mail=%s))
    volumes:
      - mta:/srv
      - app-spam:/var/lib/kopano/spamd          # kopano-spamd integration
      - /etc/localtime:/etc/localtime:ro        # Use host timezone
    cap_add: # helps debugging by allowing strace
      - sys_ptrace

  db:
    image: mariadb
    command: ['--log_warnings=1']
    networks:
      - backend
    environment:
      - LANG=C.UTF-8
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD-secret}
      - MYSQL_DATABASE=${MYSQL_DATABASE-kopano}
      - MYSQL_USER=${MYSQL_USER-kopano}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD-secret}
    volumes:
      - db:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro        # Use host timezone

  auth:
    image: mlan/openldap
    networks:
      - backend
    command: --root-cn ${AD_ROOT_CN-admin} --root-pw ${AD_ROOT_PW-secret}
    environment:
      - LDAPBASE=${AD_BASE-dc=example,dc=com}
      - LDAPDEBUG=${AD_DEBUG-parse}
    volumes:
      - auth:/srv
      - /etc/localtime:/etc/localtime:ro        # Use host timezone

networks:
  backend:

volumes:
  app-atch:
  app-conf:
  app-spam:
  app-sync:
  auth:
  db:
  mta:

Demo

This repository contains a demo directory which hold the docker-compose.yml file as well as a Makefile which might come handy. To run the demo you need docker-compose installed. By default curl and firefox is expected to be installed, but if not, run make utils-container within the demo directory once the repository has been cloned. The make utility works nicely with bash-completion so it can be worth considering having it installed too. Once the dependencies are met, start with cloning the github repository.

git clone https://github.com/mlan/docker-kopano.git

From within the demo directory you can start the containers by typing:

make init

Now you can assess WebApp on the custom docker network at URL http://app and log in with the user name demo and password demo.

make web

You can send yourself a test email by typing:

make test

When you are done testing you can destroy the test containers and their volumes by typing:

make destroy

Persistent storage

By default, docker will store the user data and service configurations within the container. This has the drawback that the user data and service configurations are lost together with the container should it be deleted. It can therefore be a good idea to use docker volumes and mount the run directories and/or the configuration directories there so that the data will survive a container deletion.

There are at least three directories which should be considered for persistent storage; the configuration files, /etc/kopano, the mail attachments, if they are kept in files, /var/lib/kopano/attachments and the active sync device states, if they are kept in files, /var/lib/z-push.

Configuration / seeding procedure

The mlan/kopano image contains an elaborate configuration / seeding procedure. The configuration is controlled by environment variables, described below.

The seeding procedure will leave any existing configuration untouched. This is achieved by the using an unlock file: DOCKER_UNLOCK_FILE=/etc/kopano/.docker.unlock. During the image build this file is created. When the the container is started the configuration / seeding procedure will be executed if the DOCKER_UNLOCK_FILE can be found. Once the procedure completes the unlock file is deleted preventing the configuration / seeding procedure to run when the container is restarted.

The unlock file approach was selected since it is difficult to accidentally create a file.

In the rare event that want to modify the configuration of an existing container you can override the default behavior by setting FORCE_CONFIG=overwrite to a no-empty string.

Environment variables and service parameters

When you create the mlan/kopano container, you can adjust the configuration of the Kopano server by defining one or more environment variables. During container initiation environment variables are matched against all possible parameters for all Kopano services. When matched, configuration files are updated with the value of the matching environment variable.

To see all available configuration parameters you can run run list_parms <service> within the container or when when using the demo described above just type:

make app-parms_dagent
make app-parms_server
Overlapping parameter names

Some services use the same parameter names. When such a parameter is set using en environment variable all configuration files of the related services will be updated. This is not always desired. To address this you can prefix the parameter name with the name of the service you which to target by using the following syntax: <service>_<parameter>.

For example when using the Kopano-archiver service, you often want to use one SQL database for the server and one separate one for the archiver. In this situation you can have two separate SQL database containers, one at db-srv and the other at db-arc. To set the MYSQL_HOST parameter in the two relevant configuration files use SERVER_MYSQL_HOST=db-srv and ARCHIVER_MYSQL_HOST=db-arc. If for some reason you want both services to call the same container, instead use: MYSQL_HOST=db.

SQL database configuration

The Kopano server uses a SQL database, which needs to be initiated, see below. Once the SQL database has been initiated you can create the Kopano container and configure it to use the SQL database using environment variables.

MYSQL_HOST

The host name of the MySQL server to use. Default MYSQL_HOST=localhost.

MYSQL_PORT

The port of the MySQL server to use. Default MYSQL_PORT=3306

MYSQL_USER

The user under which we connect with MySQL. Default MYSQL_USER=root. For security reasons it is probably wise not to use the root user. Use the same name as was used when initiating the SQL database, see below.

MYSQL_PASSWORD

The password to use for MySQL. It is possible to leave it empty for no password, but that is advised against. Default MYSQL_PASSWORD=. Use the same password as was used when initiating the SQL database, see below.

MYSQL_DATABASE

The MySQL database to connect to. Default MYSQL_DATABASE=kopano. Use the same database name as was used when initiating the SQL database, see below.

ATTACHMENT_STORAGE

The location where attachments are stored. This can be in the MySQL database, or as separate files. The drawback of database is that the large data of attachment will push useful data from the MySQL cache. The drawback of separate files is that a mysqldump is not enough for a full disaster recovery. Possible values: database, files, files_v2 (experimental). Default: ATTACHMENT_STORAGE=files

ATTACHMENT_COMPRESSION

When the ATTACHMENT_STORAGE option is ATTACHMENT_STORAGE=files, this option controls the compression level for the attachments. Higher compression levels will compress data better, but at the cost of CPU usage. Lower compression levels will require less CPU but will compress data less. Setting the compression level to 0 will effectively disable compression completely. Changing the compression level, or switching it on or off, will not affect any existing attachments, and will remain accessible as normal. Set to 0 to disable compression completely. The maximum compression level is 9. Default: ATTACHMENT_COMPRESSION=6

SQL Database initialization

When creating the SQL container you can use environment variables to initiate it. For example, MYSQL_ROOT_PASSWORD=topsecret, MYSQL_DATABASE=kopano, MYSQL_USER=kopano and MYSQL_PASSWORD=verysecret.

User management USER_PLUGIN

Kopano supports three different plugins for user management. Use the USER_PLUGIN environment variable to select the source of the user base. Possible values are: db (default), ldap and unix.

db: Retrieve the users from the Kopano database. Use the kopano-admin tool to create users and groups. There are no additional settings for this plug-in.

ldap: Retrieve the users and groups information from an LDAP directory server. Additional LDAP settings are needed, see below.

unix: Retrieve the users and groups information from the Linux password files. This option is probably not interesting here.

Accessing an LDAP directory server

The USER_PLUGIN=ldap retrieves user information from an LDAP directory server. A brief description of how that is achieved is described in Setup an LDAP directory server. Once the LDAP directory server is up and running, the mlan/kopano container can be configured to use it using environment variables.

Host address LDAP_URI

Specifies the URI of one or more LDAP server(s) to use, without any DN portion, such as ldap://server:389/, ldaps://server:636/ or ldapi:///. Defaults: LDAP_URI=ldap://localhost:389/.

Note that. the historic directives LDAP_HOST, LDAP_PORT, LDAP_PROTOCOL are no longer supported (8.7.85).

LDAP_SEARCH_BASE

This is the subtree entry where all objects are defined in the LDAP server. Default: LDAP_SEARCH_BASE=dc=kopano,dc=com

LDAP_USER_TYPE_ATTRIBUTE_VALUE

This variable determines what defines a valid Kopano user. Default: LDAP_USER_TYPE_ATTRIBUTE_VALUE=posixAccount

LDAP_GROUP_TYPE_ATTRIBUTE_VALUE

This variable determines what defines a valid Kopano group. Default: LDAP_GROUP_TYPE_ATTRIBUTE_VALUE=posixGroup

LDAP_USER_SEARCH_FILTER

Adds an extra filter to the user search. Default LDAP_USER_SEARCH_FILTER=

Hint: Use the kopanoAccount attribute in the filter to differentiate between non-Kopano and Kopano users.

LDAP_BIND_USER, LDAP_BIND_PASSWD

The defaults for these environment variables are empty. If you cannot bind anonymously, do it with this distinguished name and password. Example: LDAP_BIND_USER=cn=admin,dc=example,dc=com, LDAP_BIND_PASSWD=secret.

Kopano LDAP attributes LDAP_PROPMAP

The Kopano services needs to know which of the users LDAP attributes, like addresses, phone numbers and company information, to use. This information is defined in the propmap file, which is included in the Kopano installation files here /usr/share/kopano/ldap.propmap.cfg. When using USER_PLUGIN=ldap this LDAP propmap file is used by the Kopano services by setting LDAP_PROPMAP= to an empty string. Optionally you can use another file, for exampleLDAP_PROPMAP=/etc/kopano/ldap.propmap.cfg. If no file can be found there the installed one will be copied there.

Enabling IMAP, POP3 and ICAL

By default the IMAP and POP3 services are disabled for all users. Set the environment variable DISABLED_FEATURES= to an empty string to enable both IMAP and POP3 for all users. You can override this setting for each user independently by enabling or disabling features in the LDAP directory server see, Setup an LDAP directory server.

DISABLED_FEATURES

The environment variable DISABLED_FEATURES take a space separated list of features. Currently it may contain the following features: imap, mobile, outlook, pop3 and webapp. Default: DISABLED_FEATURES="imap pop3"

IMAP_LISTEN, POP3_LISTENand ICAL_LISTEN

By default the kopano-gateway and kopano-ical services are configured to only listen on the loop-back interface. To be able to access these services we need them to listen to any interface. This is achieved by setting IMAP_LISTEN=*:143, POP3_LISTEN=*:110 and ICAL_LISTEN=*:8080. These port numbers can be changed if desired.

Enabling IMAPS, POP3S and ICALS

By default the secure protocols are not enabled.

IMAPS_LISTEN, POP3S_LISTENand ICALS_LISTEN

To enable secure access we need to explicitly define their listening ports. This is achieved by setting any combination of IMAPS_LISTEN=*:993, POP3S_LISTEN=*:995 and ICALS_LISTEN=*:8443. These port numbers can be changed if desired.

If any of IMAPS_LISTEN, POP3S_LISTEN and ICALS_LISTEN are explicitly defined but there are no certificate files defined, a self-signed certificate will be generated when the container is created.

SSL/LTS certificate and private key

For most deployments a trusted SSL/TLS certificate is desired. During startup the mlan/kopano looks for RSAPEM certificate and private key with these specific names: /etc/kopano/ssl/cert.pem and /etc/kopano/ssl/priv_key.pem. If found they will used by the secure protocols IMAPS, POP3S and ICALS. Moreover the file ownership will be changed if needed to make them readable by the Kopano services.

SSL_CERTIFICATE_FILE and SSL_PRIVATE_KEY_FILE

If you use other file names or directories, you let the Kopano services know by setting the variables SSL_CERTIFICATE_FILE=/etc/kopano/ssl/cert.pem and SSL_PRIVATE_KEY_FILE=/etc/kopano/ssl/priv_key.pem on the docker run command line or in the docker-compose.yml file.

For testing purposes you can create a self-signed certificate using the openssl utility, see below. Note that this is not necessary since, when secure protocols are defined, a self-signed certificate and private key will be automatically be created during container startup if they are not found.

openssl genrsa -out ssl/priv_key.pem
openssl req -x509 -utf8 -new -batch -subj "/CN=app" -key ssl/priv_key.pem -out ssl/cert.pem

One way to allow the container to read the certificate and private key is to bind mount the host directory holding the files to the container:

docker run -d -name app -v $pwd/ssl:/etc/kopano/ssl mlan/kopano

A other way is to copy them to the container:

docker create -name app mlan/kopano
docker cp ssl/. app:/etc/kopano/ssl
docker start app

If you copy the files to a running container you need to make sure that the user kopano can read them.

Let’s Encrypt LTS certificates using Traefik

Let’s Encrypt provide free, automated, authorized certificates when you can demonstrate control over your domain. Automatic Certificate Management Environment (ACME) is the protocol used for such demonstration. There are many agents and applications that supports ACME, e.g., certbot. The reverse proxy Traefik also supports ACME.

ACME_FILE, ACME_POSTHOOK

The mlan/kopano image looks for a file ACME_FILE=/acme/acme.json at container startup and every time this file changes certificates within this file are extracted. If the host or domain name of one of those certificates matches HOSTNAME=$(hostname) or DOMAIN=${HOSTNAME#*.} it will be used by the secure protocols.

Once the certificates and keys have been updated, we run the command in the environment variable ACME_POSTHOOK="sv restart kopano-gateway kopano-ical". Kopano services needs to be restarted to update the LTS parameters. If such automatic reloading is not desired, set ACME_POSTHOOK= to empty.

So reusing certificates from Traefik will work out of the box if the /acme directory in the Traefik container is also mounted in the mlan/kopano container.

docker run -d -name proxy -v proxy-acme:/acme traefik
docker run -d -name app -v proxy-acme:/acme:ro mlan/kopano

Note, if the target certificate Common Name (CN) or Subject Alternate Name (SAN) is changed the container needs to be restarted.

Moreover, do not set any of SSL_CERTIFICATE_FILE and SSL_PRIVATE_KEY_FILE when using ACME_FILE.

Logging SYSLOG_LEVEL, LOG_LEVEL

The level of output for logging is in the range from 0 to 7. The default is: SYSLOG_LEVEL=5.

emergalertcriterrwarningnoticeinfodebug
01234567

Separately, LOG_LEVEL controls the logging level of the Kopano services. LOG_LEVEL takes valued from 0 to 6, where the default is LOG_LEVEL=3.

nonecriterrwarningnoticeinfodebug
0123456

Kopano add-ons

Kopano Archiver

The Kopano Archiver provides a Hierarchical Storage Management (HSM) solution for Kopano. With the Kopano Archiver older messages will be automatically moved to slower and thus cheaper storage. The slow storage consists of one or more additional Kopano Archive servers which sole task it is to store archived messages.

Typically the archiver needs its own SQL database. You can configure it using environment variables. When you do, pay attention to overlapping parameter names. Also the archiver does not run as a daemon but instead you can set up cron jobs. For example, to run the archiver

Docker Pull Command

docker pull mlan/kopano