diff --git a/CHANGELOG.md b/CHANGELOG.md index db50947..43b9110 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # 1.2.2 -- [kopano](src/kopano) Adding support for gateway / imap ical search configuration via envvars in, 50-kopano-apply-envvars. +- [kopano](src/kopano) Adding support for gateway / IMAP iCAL search configuration via envvars in, 50-kopano-apply-envvars. +- [kopano](src/kopano) Fixed old bug where set but empty environment variable was ignored by 50-kopano-apply-envvars. +- [demo](demo) Enable IMAP POP3 and CalDAV/iCAL in demo. - [docker](Dockerfile) Update kopano services. +- [docker](README.md) Added sections `Mail client configuration` and `Implementation`. # 1.2.1 diff --git a/README.md b/README.md index 837da00..6e1d86c 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,14 @@ ![docker stars](https://img.shields.io/docker/stars/mlan/kopano.svg?label=stars&style=popout-square&logo=docker) ![docker pulls](https://img.shields.io/docker/pulls/mlan/kopano.svg?label=pulls&style=popout-square&logo=docker) -This (non official) repository provides dockerized web mail service as well as ActiveSync, ICAL, IMAP and POP3 service. It is based on [Kopano](https://kopano.com) core components, as well as the Kopano WebApp and [Z-Push](http://z-push.org/). The image uses [nightly built packages](https://download.kopano.io/community/) which are provided by the Kopano community. +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](https://kopano.com) core components, as well as the Kopano WebApp and [Z-Push](http://z-push.org/). The image uses [nightly built packages](https://download.kopano.io/community/) 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](https://github.com/zokradonh/kopano-docker). ## Features -Brief feature list follows below - - Groupware server [Kopano WebApp](https://kopano.io/) -- ActiveSync server [Z-Push](http://z-push.org/) +- [Exchange ActiveSync (EAS)](https://en.wikipedia.org/wiki/Exchange_ActiveSync) server [Z-Push](http://z-push.org/) - Multi-staged build providing the images `full`, `debugtools` and `core` - Configuration using environment variables - Log directed to docker daemon with configurable level @@ -145,23 +143,55 @@ volumes: mta: ``` -This repository contains a [demo](demo) directory which hold the [docker-compose.yml](demo/docker-compose.yml) file as well as a [Makefile](demo/Makefile) which might come handy. From within the [demo](demo) directory you can start the containers by typing: +## Demo + +This repository contains a [demo](demo) directory which hold the [docker-compose.yml](demo/docker-compose.yml) file as well as a [Makefile](demo/Makefile) which might come handy. Start with cloning the [github](https://github.com/mlan/docker-kopano) repository. + +```bash +git clone https://github.com/mlan/docker-kopano.git +``` + +From within the [demo](demo) directory you can start the containers by typing: ```bash make init ``` -Then you can assess WebApp on the URL [`http://localhost:8080`](http://localhost:8080) and log in with the user name `demo` and password `demo` . You can send yourself a test email by typing: +Then you can assess WebApp on the URL [`http://localhost:8008`](http://localhost:8008) and log in with the user name `demo` and password `demo` . You can send yourself a test email by typing: + +```bash +make web +``` + +You can send yourself a test email by typing: ```bash make test ``` -When you are done testing you can destroy the test container by typing: + +When you are done testing you can destroy the test containers by typing ```bash 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=/srv/etc/.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. @@ -210,10 +240,6 @@ When the `ATTACHMENT_STORAGE` option is `ATTACHMENT_STORAGE=files`, this option 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`. -## Persistent data - -There are at least three directories which should be considered mounted; 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`. - ## 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`. @@ -254,9 +280,17 @@ 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 and POP3 `DISABLED_FEATURES` +### Enabling IMAP, POP3 and ICAL -By default the `imap` and `pop3` services are disabled for all users. You can set the environment variable `DISABLED_FEATURES=` to enable both `imap` and `pop3`. In this list you can disable certain features for users. This list is space separated, and currently may contain the following features: `imap`, `pop3`. Default: `DISABLED_FEATURES=imap pop3` +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` @@ -316,3 +350,65 @@ 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](http://z-push.org/), allows native interfacing with Microsoft Outlook 2013 and above via the [Exchange ActiveSync (EAS)](https://en.wikipedia.org/wiki/Exchange_ActiveSync) protocol, providing synchronization of mail, calendar, tasks and contacts. For details please see [Configuring Outlook](https://documentation.kopano.io/user_manual_kopanocore/configure_outlook.html). + +It can be interesting to know that there is a [Kopano OL Extension](https://kb.kopano.io/display/WIKI/Setting+up+the+Kopano+OL+Extension) that can improve productivity. To install it [download](https://download.kopano.io/community/olextension%3A/) and run the `KopanoOLExtension--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)](https://en.wikipedia.org/wiki/Exchange_ActiveSync), providing synchronization of mail, calendar, tasks and contacts. For details please see [Configuring Mobile Devices](https://documentation.kopano.io/user_manual_kopanocore/configure_mobile_devices.html). + +### Alternative mail synchronization + +Some clients does not support [Exchange ActiveSync (EAS)](https://en.wikipedia.org/wiki/Exchange_ActiveSync), e.g., Linux ones, in which case either the [IMAP](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol) or [POP3](https://en.wikipedia.org/wiki/Post_Office_Protocol) 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)](https://en.wikipedia.org/wiki/Message_transfer_agent) over [SMTP](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol). For more details please see [Configuring Alternative Mail Clients](https://documentation.kopano.io/user_manual_kopanocore/configure_alternative_mail_clients.html). + +Please note that IMAP and POP3 access are not enabled by default, see [Enabling IMAP and POP3 `DISABLED_FEATURES`](#enabling-imap-and-pop3-disabled_features). + +### Alternative calendar synchronization + +CalDAV offers calendar sync For more details please see [Configuring CalDAV Clients](https://documentation.kopano.io/user_manual_kopanocore/configure_caldav_clients.html). + +### Mozilla Thunderbird + +Thunderbird does not support [Exchange ActiveSync (EAS)](https://en.wikipedia.org/wiki/Exchange_ActiveSync), so either [IMAP](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol) or [POP3](https://en.wikipedia.org/wiki/Post_Office_Protocol) and SMTP is needed to synchronize mail, see [Alternative mail synchronization](#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)](https://en.wikipedia.org/wiki/Exchange_ActiveSync), but not for mail. For details please see [Provider for Exchange ActiveSync](https://addons.thunderbird.net/en-US/thunderbird/addon/eas-4-tbsync/). + +# Implementation + +Here some implementation details are presented. + +## Container init scheme + +The container use [runit](http://smarden.org/runit/), providing an init scheme and service supervision, allowing multiple services to be started. There is a Gentoo Linux [runit wiki](https://wiki.gentoo.org/wiki/Runit). + +When the container is started, execution is handed over to the script [`docker-entrypoint.sh`](src/docker/bin/docker-entrypoint.sh). It has 4 stages; 0) *register* the SIGTERM [signal (IPC)](https://en.wikipedia.org/wiki/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. + +```dockerfile +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`](https://docs.docker.com/engine/reference/builder/#dockerignore-file). Since we don't want files from the module `notused` we list it in the `.dockerignore` file: + +```sh +src/notused +``` + diff --git a/ROADMAP.md b/ROADMAP.md index d899dd7..a575b6c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,5 +1,13 @@ # Road map +## Dockerfile + +Consider removing debugtools build target. There already exists a app-debugtools target in the demo Makefile. + +## kDAV + +Consider integrating support for kDAV which provides CalDAV and CardDAV. + ## Common configurations The following directives exist: @@ -8,6 +16,10 @@ The following directives exist: !include common.cfg ``` +## ACME TLS + +Arrange ACME TLS certificates for kopano-gateway (IMAP POP3). + ## Revisit Persistent Data Consider consolidating directories which are candidates for persistence under `/srv`. diff --git a/demo/Makefile b/demo/Makefile index 4db8f6f..bd2a074 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -141,7 +141,20 @@ app-test_smtp: mta-test app-test_lmtp: printf "LHLO mx\nMAIL FROM: \nRCPT TO: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDATA\nFrom: A tester \nTo: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDate: $$(date)\nSubject: A LMTP test message from me to you\n\nDelete me, please \n.\nQUIT\n" | nc -C $(call _ip,$(COMPOSE_PROJECT_NAME)_app_1) 2003 -app-show_user1: +app-hostaddr: + $(eval myhost := $(call _ip,$(COMPOSE_PROJECT_NAME)_app_1)) + +app-test_imap: app-hostaddr + curl imap://$(myhost) -X CAPABILITY + curl imap://$(myhost) -u $(LDAP_TEST_USER):$(LDAP_TEST_PASSWD) + +app-test_pop3: app-hostaddr + curl pop3://$(myhost) -u $(LDAP_TEST_USER):$(LDAP_TEST_PASSWD) + +app-test_ical: app-hostaddr + curl http://$(myhost):8080 -u $(LDAP_TEST_USER):$(LDAP_TEST_PASSWD) + +app-show_user1: docker-compose exec app kopano-admin -l app-show_user2: app-debugtools diff --git a/demo/docker-compose.yml b/demo/docker-compose.yml index 452b789..bad1bc6 100644 --- a/demo/docker-compose.yml +++ b/demo/docker-compose.yml @@ -9,12 +9,12 @@ services: - "127.0.0.1:8008:80" # WebApp & EAS (alt. HTTP) - "127.0.0.1:110:110" # POP3 - "127.0.0.1:143:143" # IMAP - - "127.0.0.1:8080:8080" # ICAL + - "127.0.0.1:8080:8080" # CalDAV/iCAL depends_on: - auth - db - mta - environment: + environment: # Virgin config, ignored on restarts unless FORCE_CONFIG given. - USER_PLUGIN=ldap - LDAP_URI=ldap://auth:389/ - MYSQL_HOST=db @@ -25,6 +25,10 @@ services: - 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 @@ -44,7 +48,7 @@ services: - "127.0.0.1:25:25" # SMTP depends_on: - auth - environment: + environment: # Virgin config, ignored on restarts unless FORCE_CONFIG given. - MESSAGE_SIZE_LIMIT=${MESSAGE_SIZE_LIMIT-25600000} - LDAP_HOST=auth - VIRTUAL_TRANSPORT=lmtp:app:2003 diff --git a/src/docker/bin/docker-config.sh b/src/docker/bin/docker-config.sh index 2e3ac62..377d66e 100644 --- a/src/docker/bin/docker-config.sh +++ b/src/docker/bin/docker-config.sh @@ -239,6 +239,6 @@ dc_lock_config() { } # -# true if there is no lock file or FORCE_CONFIG is not empty +# true if there is no unlock file or FORCE_CONFIG is not empty # dc_is_unlocked() { [ -f "$DOCKER_UNLOCK_FILE" ] || [ -n "$FORCE_CONFIG" ] ;} diff --git a/src/docker/bin/docker-entrypoint.sh b/src/docker/bin/docker-entrypoint.sh index d70dc8a..7e81982 100755 --- a/src/docker/bin/docker-entrypoint.sh +++ b/src/docker/bin/docker-entrypoint.sh @@ -61,7 +61,7 @@ term_trap() { # exec 2>&1 -trap 'kill $!; term_trap' TERM +trap 'kill $!; term_trap' SIGTERM # # Stage 1) run all entry scripts in $DOCKER_ENTRY_DIR diff --git a/src/kopano/entry.d/50-kopano-apply-envvars b/src/kopano/entry.d/50-kopano-apply-envvars index e36c700..fd64812 100755 --- a/src/kopano/entry.d/50-kopano-apply-envvars +++ b/src/kopano/entry.d/50-kopano-apply-envvars @@ -30,7 +30,7 @@ zpush_cfg_file=$DOCKER_CONF_DIR2/config.php # dagent_env_vars="LMTP_LISTEN LOG_LEVEL SPAM_HEADER_NAME SPAM_HEADER_VALUE" -gateway_env_vars="DISABLE_PLAINTEXT_AUTH HTML_SAFETY_FILTER IMAP_CAPABILITY_IDLE IMAP_EXPUNGE_ON_DELETE IMAP_IGNORE_COMMAND_IDLE IMAP_LISTEN IMAP_MAX_FAIL_COMMANDS IMAP_MAX_MESSAGESIZE IMAP_ONLY_MAILFOLDERS IMAP_PUBLIC_FOLDERS IMAPS_LISTEN POP3_LISTEN POP3S_LISTEN" +gateway_env_vars="BYPASS_AUTH DISABLE_PLAINTEXT_AUTH HTML_SAFETY_FILTER IMAP_CAPABILITY_IDLE IMAP_EXPUNGE_ON_DELETE IMAP_IGNORE_COMMAND_IDLE IMAP_LISTEN IMAP_MAX_FAIL_COMMANDS IMAP_MAX_MESSAGESIZE IMAP_ONLY_MAILFOLDERS IMAP_PUBLIC_FOLDERS IMAPS_LISTEN POP3_LISTEN POP3S_LISTEN DISABLE_PLAINTEXT_AUTH" ical_env_vars="ICAL_LISTEN ICALS_LISTEN ENABLE_ICAL_GET" ldap_env_vars="LDAP_URI LDAP_HOST LDAP_PORT LDAP_PROTOCOL LDAP_SEARCH_BASE LDAP_USER_TYPE_ATTRIBUTE_VALUE LDAP_GROUP_TYPE_ATTRIBUTE_VALUE LDAP_USER_SEARCH_FILTER" search_env_vars="INDEX_PROCESSES INDEX_DRAFTS INDEX_JUNK SUGGESTIONS INDEX_ATTACHMENTS INDEX_ATTACHMENT_MAX_SIZE" @@ -52,7 +52,7 @@ _kopano_apply_envvars_gen() { local env_vars=$@ if [ ! -e $cfg_file ]; then for env_var in $env_vars; do - if [ -n "${!env_var}" ]; then + if [ -n "${!env_var+x}" ]; then dc_log 5 "Setting ${env_var,,} = ${!env_var} in $cfg_file" echo ${env_var,,} = ${!env_var} >> $cfg_file fi