- [docker](Dockerfile) Now use an unlock file, which is removed after a virgin container has been configured. This locks the configuration on restarts unless `FORCE_CONFIG` is given. |
||
---|---|---|
demo | ||
hooks | ||
src | ||
.dockerignore | ||
.gitignore | ||
.travis.yml | ||
CHANGELOG.md | ||
Dockerfile | ||
LICENSE.txt | ||
Makefile | ||
README.md | ||
ROADMAP.md |
README.md
The mlan/kopano
repository
This (non official) repository provides dockerized web mail service as well as Exchange ActiveSync (EAS), ICAL, IMAP and POP3 service. 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
- Groupware server Kopano WebApp
- Exchange ActiveSync (EAS) server Z-Push
- Multi-staged build providing the images
full
,debugtools
andcore
- Configuration using environment variables
- Log directed to docker daemon with configurable level
- Built in utility script conf helping configuring Kopano components, WebApp and Z-Push
- Health check
- Hook for theming
- Demo based on
docker-compose.yml
andMakefile
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:
- "127.0.0.1:8008:80" # WebApp & EAS (alt. HTTP)
- "127.0.0.1:110:110" # POP3 (not needed if all devices can use EAS)
- "127.0.0.1:143:143" # IMAP (not needed if all devices can use EAS)
- "127.0.0.1:8080:8080" # CalDAV (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=${LDAP_BASE-dc=example,dc=com}
- LDAP_USER_TYPE_ATTRIBUTE_VALUE=${LDAP_USEROBJ-posixAccount}
- LDAP_GROUP_TYPE_ATTRIBUTE_VALUE=${LDAP_GROUPOBJ-posixGroup}
- MYSQL_DATABASE=${MYSQL_DATABASE-kopano}
- MYSQL_USER=${MYSQL_USER-kopano}
- MYSQL_PASSWORD=${MYSQL_PASSWORD-secret}
- POP3_LISTEN=*:110 # also listen to eth0
- IMAP_LISTEN=*:143 # also listen to eth0
- ICAL_LISTEN=*:8080 # also listen to eth0
- DISABLED_FEATURES=${DISABLED_FEATURES-} # also enable IMAP and POP3
- SYSLOG_LEVEL=${SYSLOG_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:
- "127.0.0.1:25:25" # SMTP
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=${LDAP_USEROU-users},${LDAP_BASE-dc=example,dc=com}
- LDAP_QUERY_FILTER_USER=(&(objectclass=${LDAP_USEROBJ-posixAccount})(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
environment:
- LDAP_LOGLEVEL=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. 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
Then you can assess WebApp on the URL http://localhost:8008
and log in with the user name demo
and password demo
. You can send yourself a test email by typing:
make web
You can send yourself a test email by typing:
make test
When you are done testing you can destroy the test containers 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
When you create the mlan/kopano
container, you can adjust the configuration of the Kopano server by passing one or more environment variables or on the docker run command line. Note that any pre-existing configuration files within the container will be left untouched.
To see all available configuration variables you can run man
within the container by for example using the Makefile described above:
make mail-app-man_server
If you do, you will notice that configuration variable names are all lower case, but they will be matched with all uppercase environment variables by the container docker-entrypoint.sh
script.
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 authentication USER_PLUGIN
Kopano supports three different ways to manage user authentication. 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 server. All 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.
LDAP authentication
An LDAP server with user accounts configured to be used with Kopano is needed, but how to set one up is out of our scope here, instead see: Kopano Knowledge Base/Install and optimize OpenLDAP for use with Kopano Groupware Core.
Once the LDAP server is up and running, the mlan/kopano
container can be configured to use it using environment variables. In addition to the variables discussed below also set USER_PLUGIN=ldap
.
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/
.
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.
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.
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"
POP3_LISTEN
, IMAP_LISTEN
and ICAL_LISTEN
By default the kopano-gateway and kopano-ical services are configured to only listen on the loopback interface. To be able to access these services we need them to listen to any interface. This is achieved by setting POP3_LISTEN=*:110
, IMAP_LISTEN=*:143
and ICAL_LISTEN=*:8080
. These port numbers can be changed if desired.
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
.
emerg | alert | crit | err | warning | notice | info | debug |
---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
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
.
none | crit | err | warning | notice | info | debug |
---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 |
Custom themes
You can easily customize the Kopano WebApp see New! JSON themes in Kopano WebApp. Once you have the files you can install them in your docker container using the receipt below, where we assume that the container name is mail-app
and that the directory mytheme
contains the theme.json
and the other file defining the theme.
docker cp mytheme/. mail-app:/etc/kopano/theme/Custom
docker exec -it mail-app chown -R root: /etc/kopano/theme
docker exec -it mail-app run dc_replace /etc/kopano/webapp/config.php 'define("THEME", \x27\x27);' 'define("THEME", \x27Custom\x27);'
Please note that it is not possible to rename the directory /etc/kopano/theme/Custom
within the container without further modifications.
Mail transfer agent interaction
Environment variables can be used to configure where Kopano find the Mail Transfer Agent, such as Postfix. Likewise the Mail Transfer Agent need to know where to forward emails to.
LMTP_LISTEN
Added support (release 1.1.3) of the environment variable with default LMTP_LISTEN=*:2003
, due to misconfiguration of kopano-dagent
in recent releases (kopano-core 8.7.84).
SMTP_SERVER
Host name or IP address of the outgoing SMTP server. This server needs to relay mail for your server. Default: SMTP_SERVER=localhost
SMTP_PORT
TCP Port number used to contact the SMTP_SERVER
. Default: SMTP_PORT=25
Configuring postfix
The Kopano server listens to the port 2003 and expect the LMTP protocol. For Postfix you can define VIRTUAL_TRANSPORT=lmtp:mail-app:2003
assuming the mlan/kopano
container is named mail-app
Kopano-spamd integration with mlan/postfix-amavis
Kopano-spamd allow users to drag messages into the Junk folder triggering the anti-spam filter to learn it as spam. If the user moves the message back to the inbox, the anti-spam filter will unlearn it.
To allow kopano-spamd integration the kopano and postfix-amavis containers need to
share the /var/lib/kopano/spamd
folder. If this directory exists within the
postfix-amavis container, the spamd-spam and spamd-ham service will be started.
They will run sa-learn --spam
or sa-learn --ham
,
respectively when a message is placed in either var/lib/kopano/spamd/spam
or
var/lib/kopano/spamd/ham
.
Knowledge base
Here some topics relevant for arranging a mail server are presented.
Mail client configuration
Microsoft Outlook
Kopano, using Z-Push, allows native interfacing with Microsoft Outlook 2013 and above via the Exchange ActiveSync (EAS) protocol, providing synchronization of mail, calendar, tasks and contacts. For details please see Configuring Outlook.
It can be interesting to know that there is a Kopano OL Extension that can improve productivity. To install it download and run the KopanoOLExtension-<version>-combined.exe
file on your Windows PC.
Mobile devices
Most mobile devices, that is, Apple iOS, Android and Blackberry have support for Exchange ActiveSync (EAS), providing synchronization of mail, calendar, tasks and contacts. For details please see Configuring Mobile Devices.
Alternative mail synchronization
Some clients does not support Exchange ActiveSync (EAS), e.g., Linux ones, in which case either the IMAP or POP3 protocol are used via the Kopano gateway. These protocols only handle incoming mail, so for sending mail clients need to interface directly with a Mail Transfer Agent (MTA) over SMTP. For more details please see Configuring Alternative Mail Clients.
Please note that IMAP and POP3 access are not enabled by default, see Enabling IMAP and POP3 DISABLED_FEATURES
.
Alternative calendar synchronization
CalDAV offers calendar sync For more details please see Configuring CalDAV Clients.
Mozilla Thunderbird
Thunderbird does not support Exchange ActiveSync (EAS), so either IMAP or POP3 and SMTP is needed to synchronize mail, see Alternative mail synchronization.
To synchronize calendar, tasks and contacts CalDAV can be used. Interestingly Thunderbird has a add-on that provides calendar, tasks and contacts synchronization using Exchange ActiveSync (EAS), but not for mail. For details please see Provider for Exchange ActiveSync.
Implementation
Here some implementation details are presented.
Container init scheme
The container use runit, providing an init scheme and service supervision, allowing multiple services to be started. There is a Gentoo Linux runit wiki.
When the container is started, execution is handed over to the script docker-entrypoint.sh
. It has 4 stages; 0) register the SIGTERM signal (IPC) handler, which is programmed to run all exit scripts in /etc/docker/exit.d/
and terminate all services, 1) run all entry scripts in /etc/docker/entry.d/
, 2) start services registered in SVDIR=/etc/service/
, 3) wait forever, allowing the signal handler to catch the SIGTERM and run the exit scripts and terminate all services.
The entry scripts are responsible for tasks like, seeding configurations, register services and reading state files. These scripts are run before the services are started.
There is also exit script that take care of tasks like, writing state files. These scripts are run when docker sends the SIGTERM signal to the main process in the container. Both docker stop
and docker kill --signal=TERM
sends SIGTERM.
Build assembly
The entry and exit scripts, discussed above, as well as other utility scrips are copied to the image during the build phase. The source file tree was designed to facilitate simple scanning, using wild-card matching, of source-module directories for files that should be copied to image. Directory names indicate its file types so they can be copied to the correct locations. The code snippet in the Dockerfile
which achieves this is show below.
COPY src/*/bin $DOCKER_BIN_DIR/
COPY src/*/entry.d $DOCKER_ENTRY_DIR/
There is also a mechanism for excluding files from being copied to the image from some source-module directories. Source-module directories to be excluded are listed in the file .dockerignore
. Since we don't want files from the module notused
we list it in the .dockerignore
file:
src/notused