diff --git a/.dockerignore b/.dockerignore index 85ab7d3..b61de2f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,6 +2,7 @@ .gitignore .github .gitattributes +src/notused demo *.md local* diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a4ccc0..40b2d69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,31 @@ -# v1.1.2 +# 1.1.3 -- Update Dockerfile so that is works also for debian 9 -- Update assets/kopano-webaddr.sh now that we do not have builds for debian 8 +- The `setup-runit.sh` script now have options: down, force, log, name, source, quiet. +- Fixed the Apache runit script, using the new `setup-runit.sh` script. Stopping the parent process now also stops all child processes. Using the quiet option, Apache does not flood the logs anymore. +- Added support of the environment variable `LMTP_LISTEN=*:2003`, due to misconfiguration of `kopano-dagent` in recent releases (8.7.84). +- Simplified the health check. +- Changed repository directory structure to a more general one. +- Renamed some build variables, e.g., `DOCKER_RUNSV_DIR` (was `docker_build_runit_root`). +- Cleaning up `Makefile` +- Added more debug functionality in `demo/Makefile` + +# 1.1.2 + +- Update `Dockerfile` so that is works also for Debian 9 +- Update `kopano-webaddr.sh` now that we do not have builds for Debian 8 - Updated demo -# v1.1.1 +# 1.1.1 - Make sure the .env settings are honored also for MYSQL -# v1.1.0 +# 1.1.0 - Reversed tag naming scheme. now `full-8.7.80-3.5.2` instead of ~~8.7.80-3.5.2-full~~ - Demo based on `docker-compose.yml` and `Makefile` files - Check and fix file attributes in the `/var/lib/kopano/attachments` directory -# v1.0.0 +# 1.0.0 - Groupware server [Kopano WebApp](https://kopano.io/) - ActiveSync server [Z-Push](http://z-push.org/) diff --git a/Dockerfile b/Dockerfile index af57871..c75c63b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,14 +8,17 @@ ARG ARCH FROM ${ARCH:+$ARCH/}$DIST:$REL AS base LABEL maintainer=mlan ENV DEBIAN_FRONTEND=noninteractive \ - docker_build_runit_root=/etc/service \ - docker_build_deb_dir=/tmp/deb \ - docker_build_passes=1 \ + DOCKER_BIN_DIR=/usr/local/bin \ + DOCKER_RUNSV_DIR=/etc/service \ + DOCKER_BUILD_DEB_DIR=/tmp/deb \ + DOCKER_BUILD_PASSES=1 \ + SYSLOG_OPTIONS='-S' \ SYSLOG_LEVEL=4 # -# Copy helpers +# Copy utility scripts including entrypoint.sh to image # -COPY assets/setup-runit.sh /usr/local/bin/ +COPY src/*/bin $DOCKER_BIN_DIR/ + # # Install helpers # @@ -28,7 +31,7 @@ RUN apt-get update && apt-get install --yes --no-install-recommends \ ca-certificates \ tar \ gnupg \ - && setup-runit.sh "syslogd -n -O /dev/stdout -l $SYSLOG_LEVEL" + && setup-runit.sh "syslogd -n -O - -l $SYSLOG_LEVEL $SYSLOG_OPTIONS" @@ -55,7 +58,7 @@ RUN rm -f /etc/dpkg/dpkg.cfg.d/excludes \ # # Kopano-core # -FROM base-man AS kopano-core +FROM base-man AS core # # build arguments, amd64 is the default # @@ -66,49 +69,42 @@ ARG ARCH=amd64 # variables # ENV DEBIAN_FRONTEND=noninteractive \ - docker_build_runit_root=/etc/service \ - docker_build_deb_dir=/tmp/deb \ - docker_build_passes=1 -# -# Copy helpers -# -COPY assets/kopano-webaddr.sh /usr/local/bin/ -COPY assets/dpkg-version.sh /usr/local/bin/ -COPY assets/conf /usr/local/bin/ -COPY assets/entrypoint.sh /usr/local/bin/ -COPY assets/healthcheck.sh /usr/local/bin/ + DOCKER_RUNSV_DIR=/etc/service \ + DOCKER_BIN_DIR=/usr/local/bin \ + LMTP_LISTEN=*:2003 \ + DOCKER_BUILD_DEB_DIR=/tmp/deb \ + DOCKER_BUILD_PASSES=1 # # Install kopano-core # -RUN mkdir -p $docker_build_deb_dir \ +RUN mkdir -p $DOCKER_BUILD_DEB_DIR \ && webaddr=$(kopano-webaddr.sh core \ https://download.kopano.io/community ${DIST} ${REL} ${ARCH}) \ && echo "$webaddr<->${DIST} ${REL} ${ARCH}<-" \ - && curl $webaddr | tar -xzC $docker_build_deb_dir \ + && curl $webaddr | tar -xzC $DOCKER_BUILD_DEB_DIR \ && apt-get update \ - && for i in $(seq ${docker_build_passes}); do echo "\033[1;36mKOPANO CORE INSTALL PASS: $i\033[0m" \ - && dpkg --install --force-depends --skip-same-version --recursive $docker_build_deb_dir \ + && for i in $(seq ${DOCKER_BUILD_PASSES}); do echo "\033[1;36mKOPANO CORE INSTALL PASS: $i\033[0m" \ + && dpkg --install --force-depends --skip-same-version --recursive $DOCKER_BUILD_DEB_DIR \ && apt-get install --yes --no-install-recommends --fix-broken; done \ && mkdir -p /var/lib/kopano/attachments && chown kopano: /var/lib/kopano/attachments \ - && rm -rf $docker_build_deb_dir \ + && rm -rf $DOCKER_BUILD_DEB_DIR \ && setup-runit.sh \ "kopano-dagent -l" \ "kopano-gateway -F" \ "kopano-ical -F" \ - "kopano-search -F" \ + "-f kopano-search -F" \ "kopano-server -F" \ "kopano-spooler -F" \ - && setup-runit.sh --down \ - "kopano-grapi serve" \ - "kopano-kapid serve --log-timestamp=false" \ - "kopano-konnectd serve --log-timestamp=false" \ - "kopano-monitor -F" \ - "kopano-presence -F" \ - "kopano-spamd -F" + "-d kopano-grapi serve" \ + "-d kopano-kapid serve --log-timestamp=false" \ + "-d kopano-konnectd serve --log-timestamp=false" \ + "-d kopano-monitor -F" \ + "-d kopano-presence -F" \ + "-d kopano-spamd -F" # # Entrypoint, how container is run # -HEALTHCHECK --interval=5m --timeout=3s CMD healthcheck.sh +HEALTHCHECK CMD sv status ${DOCKER_RUNSV_DIR}/* ENTRYPOINT ["entrypoint.sh"] @@ -116,7 +112,7 @@ ENTRYPOINT ["entrypoint.sh"] # # Kopano-webapp # -FROM kopano-core AS kopano-core-webapp +FROM core AS core-webapp # # build arguments # @@ -126,21 +122,21 @@ ARG REL # variables # ENV DEBIAN_FRONTEND=noninteractive \ - docker_build_runit_root=/etc/service \ - docker_build_deb_dir=/tmp/deb \ - docker_build_passes=1 + DOCKER_RUNSV_DIR=/etc/service \ + DOCKER_BUILD_DEB_DIR=/tmp/deb \ + DOCKER_BUILD_PASSES=1 # # Install Kopano webapp # RUN apt-get install --yes --no-install-recommends apache2 libapache2-mod-php \ - && mkdir -p $docker_build_deb_dir \ + && mkdir -p $DOCKER_BUILD_DEB_DIR \ && webaddr=$(kopano-webaddr.sh webapp \ https://download.kopano.io/community ${DIST} ${REL} all) \ && echo "$webaddr<->${DIST} ${REL} all<-" \ - && curl $webaddr | tar -xzC $docker_build_deb_dir \ + && curl $webaddr | tar -xzC $DOCKER_BUILD_DEB_DIR \ && apt-get update \ - && for i in $(seq ${docker_build_passes}); do echo "\033[1;36mKOPANO WEBAPP INSTALL PASS: $i\033[0m" \ - && dpkg --install --force-depends --skip-same-version --recursive $docker_build_deb_dir \ + && for i in $(seq ${DOCKER_BUILD_PASSES}); do echo "\033[1;36mKOPANO WEBAPP INSTALL PASS: $i\033[0m" \ + && dpkg --install --force-depends --skip-same-version --recursive $DOCKER_BUILD_DEB_DIR \ && apt-get install --yes --no-install-recommends --fix-broken; done \ && dpkg-reconfigure php7-mapi \ && conf replace /etc/kopano/webapp/config.php 'define("INSECURE_COOKIES", false);' 'define("INSECURE_COOKIES", true);' \ @@ -148,16 +144,16 @@ RUN apt-get install --yes --no-install-recommends apache2 libapache2-mod-php \ && conf replace /etc/apache2/sites-available/kopano-webapp.conf 'Alias /webapp /usr/share/kopano-webapp' '\\nDocumentRoot /usr/share/kopano-webapp' \ && echo '' >> /etc/apache2/sites-available/kopano-webapp.conf \ && conf modify /etc/apache2/apache2.conf '^ErrorLog' syslog:user \ - && echo 'CustomLog "||/usr/bin/logger -t apache -i -p user.notice" vhost_combined' >> /etc/apache2/apache2.conf \ - && echo 'CustomLog "||/usr/bin/logger -t apache -i -p user.info" combined' >> /etc/apache2/apache2.conf \ + && echo 'CustomLog "||/usr/bin/logger -t apache -i -p user.debug" common' >> /etc/apache2/apache2.conf \ + && echo 'ServerName localhost' >> /etc/apache2/apache2.conf \ && mkdir -p /etc/kopano/theme/Custom \ && ln -sf /etc/kopano/theme/Custom /usr/share/kopano-webapp/plugins/. \ # && conf modify /etc/apache2/apache2.conf '^LogLevel' crit \ # && a2disconf other-vhosts-access-log \ && a2dissite 000-default.conf \ && a2ensite kopano-webapp \ - && rm -rf $docker_build_deb_dir \ - && setup-runit.sh "apache2ctl -D FOREGROUND -k start" + && rm -rf $DOCKER_BUILD_DEB_DIR \ + && setup-runit.sh "-q -s /etc/apache2/envvars apache2 -DFOREGROUND -DNO_DETACH -k start" # # Ports # @@ -168,7 +164,7 @@ EXPOSE 80 443 # # Z-Push # -FROM kopano-core-webapp AS kopano-full +FROM core-webapp AS full # # build arguments # @@ -178,9 +174,9 @@ ARG REL # variables # ENV DEBIAN_FRONTEND=noninteractive \ - docker_build_runit_root=/etc/service \ - docker_build_deb_dir=/tmp/deb \ - docker_build_passes=1 + DOCKER_RUNSV_DIR=/etc/service \ + DOCKER_BUILD_DEB_DIR=/tmp/deb \ + DOCKER_BUILD_PASSES=1 # # Add Z-Push repository and install Z-Push configured to be used with kopano and apache # @@ -200,7 +196,7 @@ RUN debaddr="$(kopano-webaddr.sh --deb final http://repo.z-hub.io/z-push: ${DIST -FROM kopano-full AS kopano-debugtools +FROM full AS debugtools # # Optionaly install debug tools # diff --git a/Makefile b/Makefile index d94b70c..9294475 100644 --- a/Makefile +++ b/Makefile @@ -1,74 +1,36 @@ -include *.mk -BLD_ARG ?= #BLD_ARG ?= --build-arg DIST=ubuntu --build-arg REL=18.04 --build-arg ARCH=i386 -IMG_REPO ?= mlan/kopano -IMG_VER ?= $(shell assets/kopano-webaddr.sh -VV) -IMG_CMD ?= /bin/bash +BLD_ARG ?= +BLD_REPO ?= mlan/kopano +BLD_VER ?= latest +BLD_TGT ?= full +SRC_VER ?= $(shell src/docker/bin/kopano-webaddr.sh -VV) -CNT_NAME ?= kopano-default -CNT_PORT ?= -p 80:80 -CNT_ENV ?= -CNT_VOL ?= +_version = $(if $(findstring $(BLD_TGT),$(1)),$(2),$(if $(findstring latest,$(2)),$(1),$(1)-$(2))) -.PHONY: build build-all bulid-core build-full build-debugtools \ - variables push shell exec run run-fg stop rm-container rm-image release logs +.PHONY: variables: make -pn | grep -A1 "^# makefile"| grep -v "^#\|^--" | sort | uniq -build: Dockerfile - docker build $(BLD_ARG) --target kopano-full -t $(IMG_REPO)\:$(IMG_VER) . +ps: + docker ps -a -build-all: build-core build-full build-debugtools +build-all: build_core build_full build_debugtools -build-core: Dockerfile - docker build $(BLD_ARG) --target kopano-core \ - -t $(IMG_REPO)\:$(IMG_VER)-core \ - -t $(IMG_REPO)\:latest-core . +build: build_$(BLD_TGT) -build-full: Dockerfile - docker build $(BLD_ARG) --target kopano-full \ - -t $(IMG_REPO)\:$(IMG_VER) \ - -t $(IMG_REPO)\:$(IMG_VER)-full \ - -t $(IMG_REPO)\:latest \ - -t $(IMG_REPO)\:latest-full . - -build-debugtools: Dockerfile - docker build $(BLD_ARG) --target kopano-debugtools \ - -t $(IMG_REPO)\:$(IMG_VER)-debugtools \ - -t $(IMG_REPO)\:latest-debugtools . - -push: - docker push $(IMG_REPO)\:$(IMG_VER) +build_%: Dockerfile + docker build $(BLD_ARG) --target $* \ + -t $(BLD_REPO):$(call _version,$*,$(BLD_VER)) \ + -t $(BLD_REPO):$(call _version,$*,$(SRC_VER)) . version: - assets/kopano-webaddr.sh -VV + src/docker/bin/kopano-webaddr.sh -VV -shell: - docker run --rm --name $(CNT_NAME)-$(CNT_INST) -i -t $(CNT_PORT) $(CNT_VOL) $(CNT_ENV) $(IMG_REPO)\:$(IMG_VER) $(IMG_CMD) - -exec: - docker exec -it $(CNT_NAME) $(IMG_CMD) - -run-fg: - docker run --rm --name $(CNT_NAME) $(CNT_PORT) $(CNT_VOL) $(CNT_ENV) $(IMG_REPO)\:$(IMG_VER) - -run: - docker run --rm -d --name $(CNT_NAME) $(CNT_PORT) $(CNT_VOL) $(CNT_ENV) $(IMG_REPO)\:$(IMG_VER) - -logs: - docker container logs $(CNT_NAME) - -stop: - docker stop $(CNT_NAME) - -rm-container: - docker rm $(CNT_NAME) - -rm-image: - docker image rm $(IMG_REPO):$(IMG_VER) - -release: build - make push -e IMG_VER=$(IMG_VER) +prune: + docker image prune +clean: + docker images | grep $(BLD_REPO) | awk '{print $$1 ":" $$2}' | uniq | xargs docker rmi diff --git a/README.md b/README.md index 163cd2a..7d55b82 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Brief feature list follows below - Multi-staged build providing the images `full`, `debugtools` and `core` - Configuration using environment variables - Log directed to docker daemon with configurable level -- Built in utility script [conf](assets/conf) helping configuring Kopano components, WebApp and Z-Push +- Built in utility script [conf](src/docker/bin/conf) helping configuring Kopano components, WebApp and Z-Push - Health check - Hook for theming - Demo based on `docker-compose.yml` and `Makefile` files @@ -265,10 +265,14 @@ docker exec -it mail-app conf replace /etc/kopano/webapp/config.php 'define("THE 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 +## 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` diff --git a/ROADMAP.md b/ROADMAP.md index 154b21c..d0e8b02 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,24 +1,24 @@ # Road map -## apache2 runit script not working properly +## kopano_spamd -See: https://github.com/phusion/baseimage-docker/issues/271 +[discussion](https://jira.kopano.io/browse/KC-666) -We now use: -```bash -apache2ctl -D FOREGROUND -k start" -``` +- let kopano-spamd create /var/lib/kopano/spamd/{ham,spam} with perm 770, user kopano, group amavis/spamassassin +- instead of invoking sa-learn, kopano-spamd should just write to ham or spam folder depending on what happens (move to spam, spam, move from spam, ham) +- create a simple python script that will use inotify on the ham and spam directory. Whenever a new file appear then run sa-learn --spam/–ham and delete the file on success. -try: -```bash -source /etc/apache2/envvars -exec /usr/sbin/apache2 -DFOREGROUND -``` +So let the Kopano and postfix containers share the `var/lib/kopano/spamd` folder and run the cron job in the postfix container. + +## Revisit Persistent Data + +Consider consolidating directories which are candidates for persistence under `/srv`. + +##Improve Health Check? -## Improve healthcheck Verify the user anonymously. ```bash -ldapsearch -h dockerhost -xLLL -b dc=circuit-factory,dc=com '(kopanoAccount=1)' +ldapsearch -h dockerhost -xLLL -b dc=example,dc=com '(kopanoAccount=1)' ``` Check if kopano can get the user from LDAP @@ -30,13 +30,3 @@ check that apache and mysql is running apache2ctl status mysqlcheck -A ``` - -## kopano_spamd - -[discussion](https://jira.kopano.io/browse/KC-666) - -- let kopano-spamd create /var/lib/kopano/spamd/{ham,spam} with perm 770, user kopano, group amavis/spamassassin -- instead of invoking sa-learn, kopano-spamd should just write to ham or spam folder depending on what happend (move to spam, spam, move from spam, ham) -- create a simple python script that will use inotify on the ham and spam directory. Whenever a new file appear then run sa-learn --spam/–ham and delete the file on success. - -So let the Kopano and postfix containers share the `var/lib/kopano/spamd` folder and run the cron job in the postfix container. \ No newline at end of file diff --git a/assets/dpkg-version.sh b/assets/dpkg-version.sh deleted file mode 100755 index 6747914..0000000 --- a/assets/dpkg-version.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -pkg=${1-kopano-server} -dpkg -l | sed -nr 's/.*'"$pkg"'\s+([^ ]+).*/\1/p' diff --git a/assets/healthcheck.sh b/assets/healthcheck.sh deleted file mode 100755 index 3cdfb5d..0000000 --- a/assets/healthcheck.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -# -# health check -# -# uses the runit tool to check if a service that is configured to run is down. -# This is a quite limited check. -# - -docker_build_runit_root=${docker_build_runit_root-/etc/service} - -if sv status $(ls $docker_build_runit_root) | grep "normally up, want up"; then - exit 1 -else - exit 0 -fi diff --git a/assets/setup-runit.sh b/assets/setup-runit.sh deleted file mode 100755 index ec73c8a..0000000 --- a/assets/setup-runit.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/sh - -# use /etc/service if $docker_build_runit_root not already defined -docker_build_runit_root=${docker_build_runit_root-/etc/service} -#docker_build_svlog_root=${docker_build_svlog_root-/var/log/sv} - -# -# Define helpers -# - -define_formats() { - name=$(basename $0) - f_norm="\e[0m" - f_bold="\e[1m" - f_red="\e[91m" - f_green="\e[92m" - f_yellow="\e[93m" -} - -inform() { - echo "$f_bold${f_green}INFO ($name)${f_norm} $@" -} - -# -# initialize runit services -# - -init_service() { - # create runit 'run' script for service - # if service is part of kopano suite also make the 'run' script - # delete lingering pid files, which appears to happen to kopano-search - local cmd="$1" - shift - local runit_dir=$docker_build_runit_root/${cmd##*/} - local svlog_dir=$docker_build_svlog_root/${cmd##*/} - local clear_pids_str= - if echo $cmd | grep kopano - >/dev/null; then - clear_pids_str="rm -f /var/run/kopano/${cmd#*kopano-}.pid*" - fi - cmd=$(which $cmd) - if [ ! -z "$cmd" ]; then - mkdir -p $runit_dir - cat <<-!cat > $runit_dir/run - #!/bin/sh -e - #exec 2>&1 - $(echo $clear_pids_str) - exec $cmd $@ - !cat - chmod +x $runit_dir/run - inform "runit configured to run: $cmd $@" - if [ -n "$docker_build_svlog_root" ]; then - mkdir -p $runit_dir/log $svlog_dir - cat <<-!cat > $runit_dir/log/run - #!/bin/sh - exec svlogd -tt $svlog_dir - !cat - chmod +x $runit_dir/log/run - fi - fi - } - -init_services() { - for cmd in "$@" ; do - init_service $cmd - done -} - -down_service() { - local cmd="$1" - touch $docker_build_runit_root/$cmd/down - inform "runit configured to down: $cmd" -} - -down_services() { - for cmd in "$@" ; do - down_service $cmd - done - } - -setup_services() { - case "$1" in - -d|--down) - shift - init_services "$@" - down_services "$@" - ;; - *) - init_services "$@" - ;; - esac -} - -# -# run -# - -define_formats -setup_services "$@" diff --git a/demo/.env b/demo/.env index ef279bb..f5ae002 100644 --- a/demo/.env +++ b/demo/.env @@ -1,4 +1,5 @@ COMPOSE_PROJECT_NAME=demo +SYSLOG_LEVEL=7 MAIL_DOMAIN=example.com MAIL_SRV=mx DKIM_SELECTOR=default diff --git a/demo/Makefile b/demo/Makefile index d2c59a0..2f576c1 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -1,12 +1,10 @@ -include *.mk .env .init.env -.PHONY: variables ps init up down destroy wait test \ - auth-up auth-down auth-cmd auth-logs auth-show_conf auth-show_user auth-add_user \ - mail-mta-up mail-mta-down mail-mta-cmd mail-mta-logs mail-mta-bayes mail-mta-test \ - mail-db-up mail-db-down mail-db-cmd mail-db-logs mail-db-test \ - mail-app-up mail-app-down mail-app-cmd mail-app-logs mail-app-debugtools \ - mail-app-man_server mail-app-man_ldap \ - mail-app-test mail-app-show_user1 mail-app-show_user2 +_ip = $(shell docker inspect -f \ + '{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' \ + $(1) | head -n1) + +.PHONY: variables: make -pn | grep -A1 "^# makefile"| grep -v "^#\|^--" | sort | uniq @@ -14,7 +12,7 @@ variables: ps: docker-compose ps -init: auth-up wait auth-add_user wait mail-db-up wait mail-mta-up wait mail-app-up +init: auth-up wait_1 auth-add_user mail-db-up mail-mta-up wait_2 mail-app-up up: docker-compose up -d @@ -25,9 +23,15 @@ down: destroy: docker-compose down -v -wait: +config: + docker-compose config + +wait_%: sleep 10 +web: + firefox localhost:8080 & + test: mail-mta-test auth-up: @@ -64,16 +68,23 @@ mail-mta-cmd: mail-mta-logs: docker container logs $(COMPOSE_PROJECT_NAME)_mail-mta_1 +mail-mta-diff: + docker container diff $(COMPOSE_PROJECT_NAME)_mail-mta_1 + mail-mta-bayes: docker-compose exec mail-mta sh -c 'rm -f bayesian.database.gz && wget http://artinvoice.hu/spams/bayesian.database.gz && gunzip bayesian.database.gz && sa-learn --restore bayesian.database && chown -R amavis: /var/amavis/.spamassassin && rm -rf bayesian.database' mail-mta-test: - printf "EHLO mx\nMAIL FROM: \nRCPT TO: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDATA\nFrom: A tester \nTo: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDate: $$(date)\nSubject: A test message\n\nGreat news! You can receive email.\n.\nQUIT\n" \ + printf "EHLO mx\nMAIL FROM: \nRCPT TO: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDATA\nFrom: A tester \nTo: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDate: $$(date)\nSubject: A SMTP test message\n\nGreat news! You can receive email.\n.\nQUIT\n" \ | nc -C localhost 25 mail-mta-razor: docker-compose exec mail-mta conf cntcfg_razor_register +mail-mta-debugtools: + docker-compose exec mail-mta apk --no-cache --update add \ + nano less lsof htop openldap-clients bind-tools iputils strace + mail-db-up: docker-compose up -d mail-db @@ -86,6 +97,9 @@ mail-db-cmd: mail-db-logs: docker container logs $(COMPOSE_PROJECT_NAME)_mail-db_1 +mail-db-diff: + docker container diff $(COMPOSE_PROJECT_NAME)_mail-db_1 + mail-db-test: docker-compose exec mail-db mysqlshow -u $(MYSQL_USER) $(MYSQL_DATABASE) -p$(MYSQL_PASSWORD) @@ -101,10 +115,16 @@ mail-app-cmd: mail-app-logs: docker container logs $(COMPOSE_PROJECT_NAME)_mail-app_1 +mail-app-diff: + docker container diff $(COMPOSE_PROJECT_NAME)_mail-app_1 + mail-app-debugtools: - docker-compose exec mail-app apt-get update + docker-compose exec mail-app apt-get update docker-compose exec mail-app apt-get install --yes \ - less nano ldap-utils htop net-tools lsof iputils-ping + less nano ldap-utils htop net-tools lsof iputils-ping strace + +mail-app-htop: mail-app-debugtools + docker-compose exec mail-app htop mail-app-man_server: docker-compose exec mail-app man kopano-server.cfg @@ -112,7 +132,10 @@ mail-app-man_server: mail-app-man_ldap: docker-compose exec mail-app man kopano-ldap.cfg -mail-app-test: mail-mta-test +mail-app-test_smtp: mail-mta-test + +mail-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)_mail-app_1) 2003 mail-app-show_user1: docker-compose exec mail-app kopano-admin -l diff --git a/demo/docker-compose.yml b/demo/docker-compose.yml index e04859c..302be47 100644 --- a/demo/docker-compose.yml +++ b/demo/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.7' +version: '3' services: mail-app: @@ -22,11 +22,13 @@ services: - MYSQL_DATABASE=${MYSQL_DATABASE-kopano} - MYSQL_USER=${MYSQL_USER-kopano} - MYSQL_PASSWORD=${MYSQL_PASSWORD-secret} - - SYSLOG_LEVEL=3 + - SYSLOG_LEVEL=${SYSLOG_LEVEL-3} volumes: - mail-conf:/etc/kopano - mail-atch:/var/lib/kopano/attachments - mail-sync:/var/lib/z-push + cap_add: # helps debugging by alowing strace + - sys_ptrace mail-mta: image: mlan/postfix-amavis @@ -47,9 +49,11 @@ services: - LDAP_USER_BASE=ou=${LDAP_USEROU-users},${LDAP_BASE-dc=example,dc=com} - LDAP_QUERY_FILTER_USER=(&(objectclass=${LDAP_USEROBJ-posixAccount})(mail=%s)) - DKIM_SELECTOR=${DKIM_SELECTOR-default} - - SYSLOG_LEVEL=4 + - SYSLOG_LEVEL=${SYSLOG_LEVEL-4} volumes: - mail-mta:/srv + cap_add: # helps debugging by alowing strace + - sys_ptrace mail-db: image: mariadb diff --git a/hooks/build b/hooks/build index e7cffc0..34ba6aa 100644 --- a/hooks/build +++ b/hooks/build @@ -6,10 +6,10 @@ echo "hooks/build called with IMAGE_NAME=${DOCKER_REPO}:${DOCKER_TAG}, so we wil #printenv case "${DOCKER_TAG}" in - core) bld_target=kopano-core ;; - full) bld_target=kopano-full ;; - debugtools) bld_target=kopano-debugtools ;; - webapp) bld_target=kopano-webapp ;; + core) bld_target=core ;; + full) bld_target=full ;; + debugtools) bld_target=debugtools ;; + webapp) bld_target=core-webapp ;; *) echo "NOTHING since we do not know how to build with tag=${DOCKER_TAG}" exit 1 diff --git a/hooks/post_push b/hooks/post_push index 060a0bf..dbe52e8 100644 --- a/hooks/post_push +++ b/hooks/post_push @@ -1,7 +1,7 @@ #!/usr/bin/env bash # hooks/post_push -version=$(assets/kopano-webaddr.sh -VV) +version=$(src/docker/bin/kopano-webaddr.sh -VV) _docker_add_tags() { local tag="$1" diff --git a/assets/conf b/src/docker/bin/conf similarity index 100% rename from assets/conf rename to src/docker/bin/conf diff --git a/assets/entrypoint.sh b/src/docker/bin/entrypoint.sh similarity index 84% rename from assets/entrypoint.sh rename to src/docker/bin/entrypoint.sh index 6c5228e..8efb57d 100755 --- a/assets/entrypoint.sh +++ b/src/docker/bin/entrypoint.sh @@ -4,7 +4,7 @@ # config # -docker_build_runit_root=${docker_build_runit_root-/etc/service} +DOCKER_RUNSV_DIR=${DOCKER_RUNSV_DIR-/etc/service} kopano_user=kopano kopano_cfg_dir=/etc/kopano kopano_atch_dir=/var/lib/kopano/attachments @@ -12,6 +12,7 @@ zpush_cfg_dir=/usr/share/z-push server_cfg_file=$kopano_cfg_dir/server.cfg ldap_cfg_file=$kopano_cfg_dir/ldap.cfg spooler_cfg_file=$kopano_cfg_dir/spooler.cfg +dagent_cfg_file=$kopano_cfg_dir/dagent.cfg zpush_cfg_file=$zpush_cfg_dir/config.php sqlstate_cfg_file=$zpush_cfg_dir/backend/sqlstatemachine/config.php @@ -22,6 +23,7 @@ sqlstate_cfg_file=$zpush_cfg_dir/backend/sqlstatemachine/config.php server_env_vars="MYSQL_HOST MYSQL_PORT MYSQL_DATABASE MYSQL_USER MYSQL_PASSWORD DISABLED_FEATURES USER_PLUGIN LOG_LEVEL" ldap_env_vars="LDAP_HOST LDAP_PORT LDAP_PROTOCOL LDAP_SEARCH_BASE LDAP_USER_TYPE_ATTRIBUTE_VALUE LDAP_GROUP_TYPE_ATTRIBUTE_VALUE LDAP_USER_SEARCH_FILTER" spooler_env_vars="SMTP_SERVER SMTP_PORT" +dagent_env_vars="LMTP_LISTEN" zpush_env_vars="TIMEZONE USE_CUSTOM_REMOTE_IP_HEADER USE_FULLEMAIL_FOR_LOGIN STATE_MACHINE STATE_DIR LOGBACKEND LOGLEVEL LOGAUTHFAIL LOG_SYSLOG_PROGRAM LOG_SYSLOG_FACILITY SYNC_CONFLICT_DEFAULT PING_INTERVAL FILEAS_ORDER SYNC_MAX_ITEMS UNSET_UNDEFINED_PROPERTIES ALLOW_WEBSERVICE_USERS_ACCESS USE_PARTIAL_FOLDERSYNC" sqlstate_env_vars="STATE_SQL_ENGINE STATE_SQL_SERVER STATE_SQL_PORT STATE_SQL_DATABASE STATE_SQL_USER STATE_SQL_PASSWORD STATE_SQL_OPTIONS" @@ -92,19 +94,20 @@ _php_cfg_gen() { } kopano_cfg() { - _kopano_cfg_gen $server_cfg_file $server_env_vars - _kopano_cfg_gen $ldap_cfg_file $ldap_env_vars - _kopano_cfg_gen $spooler_cfg_file $spooler_env_vars + _kopano_cfg_gen $server_cfg_file $server_env_vars + _kopano_cfg_gen $ldap_cfg_file $ldap_env_vars + _kopano_cfg_gen $spooler_cfg_file $spooler_env_vars + _kopano_cfg_gen $dagent_cfg_file $dagent_env_vars } php_cfg() { - _php_cfg_gen $zpush_cfg_file $zpush_env_vars - _php_cfg_gen $sqlstate_cfg_file $sqlstate_env_vars + _php_cfg_gen $zpush_cfg_file $zpush_env_vars + _php_cfg_gen $sqlstate_cfg_file $sqlstate_env_vars } loglevel() { if [ -n "$SYSLOG_LEVEL" -a $SYSLOG_LEVEL -ne 4 ]; then - setup-runit.sh "syslogd -n -O /dev/stdout -l $SYSLOG_LEVEL" + setup-runit.sh "syslogd -n -O - -l $SYSLOG_LEVEL $SYSLOG_OPTIONS" fi } @@ -119,5 +122,5 @@ php_cfg loglevel exec 2>&1 -exec runsvdir -P $docker_build_runit_root +exec runsvdir -P $DOCKER_RUNSV_DIR diff --git a/assets/kopano-webaddr.sh b/src/docker/bin/kopano-webaddr.sh similarity index 100% rename from assets/kopano-webaddr.sh rename to src/docker/bin/kopano-webaddr.sh diff --git a/src/docker/bin/setup-runit.sh b/src/docker/bin/setup-runit.sh new file mode 100755 index 0000000..871737f --- /dev/null +++ b/src/docker/bin/setup-runit.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# +# setup-runit.sh +# + +# use /etc/service if $DOCKER_RUNSV_DIR not already defined +DOCKER_RUNSV_DIR=${DOCKER_RUNSV_DIR-/etc/service} +DOCKER_SVLOG_DIR=${DOCKER_SVLOG_DIR-/var/log/sv} +DOCKER_RUN_DIR=${DOCKER_RUN_DIR-/var/run} + +# +# Define helpers +# +usage() { + cat <<-!cat + NAME + setup-runit.sh + + SYNOPSIS + setup-runit.sh [-d] [-f] [-h] [-l] [-n name] [-s file] [-q] command [args] + + OPTIONS + -d default down + -f remove lingering pid file at start up + -h print this text and exit + -l activate logging (svlogd) + -n name use this name instead of command + -s file source file + -q send stdout and stderr to /dev/null + + EXAMPLES + setup-runit.sh "kopano-dagent -l" "-d kopano-grapi serve" + "-q -s /etc/apache2/envvars apache2 -DFOREGROUND -DNO_DETACH -k start" + + !cat +} + +base_name() { local base=${1##*/}; echo ${base%%.*} ;} + +pid_name() { + local dir_name=${1%%-*} + local pid_name=${1##*-} + echo "${DOCKER_RUN_DIR}/${dir_name}/${pid_name}.pid" +} + +inform() { + name=$(basename $0) + case "$1" in + 0) pre_string="\e[1m\e[92mINFO ($name)\e[0m";; + 1) pre_string="\e[1m\e[93mWARN ($name)\e[0m";; + 2) pre_string="\e[1m\e[91mERROR ($name)\e[0m";; + esac + shift + printf "$pre_string %s\n" "$*" +} + +add_opt() { + if [ -z "$options" ]; then + options=$1 + else + options="$options,$1" + fi +} + +# +# Define main function +# + +init_service() { + local redirstd= + local clearpid= + local sourcefile= + local sv_name cmd runsv_dir svlog_dir sv_log sv_down sv_force options + while getopts ":dfhln:s:q" opts; do + case "${opts}" in + d) sv_down="down"; add_opt "down";; + f) sv_force="force"; add_opt "force";; + h) usage; exit;; + l) sv_log="log"; add_opt "log";; + n) sv_name="${OPTARG}"; add_opt "name";; + s) sourcefile=". ${OPTARG}"; add_opt "source";; + q) redirstd="exec >/dev/null"; add_opt "quiet";; + esac + done + shift $((OPTIND -1)) + cmd=$(which "$1") + sv_name=${sv_name-$(base_name $1)} + runsv_dir=$DOCKER_RUNSV_DIR/$sv_name + svlog_dir=$DOCKER_SVLOG_DIR/$sv_name + if [ -n "$sv_force" ]; then + forcepid="$(echo rm -f $(pid_name $sv_name)*)" + fi + shift + if [ ! -z "$cmd" ]; then + inform 0 "Setting up ($sv_name) options ($options) args ($@)" + mkdir -p $runsv_dir + cat <<-!cat > $runsv_dir/run + #!/bin/sh -e + exec 2>&1 + $forcepid + $redirstd + $sourcefile + exec $cmd $@ + !cat + chmod +x $runsv_dir/run + if [ -n "$sv_down" ]; then + touch $runsv_dir/down + fi + if [ -n "$sv_log" ]; then + mkdir -p $runsv_dir/log $svlog_dir + cat <<-!cat > $runsv_dir/log/run + #!/bin/sh + exec svlogd -tt $svlog_dir + !cat + chmod +x $runsv_dir/log/run + fi + fi + } + + +# +# run +# + +for cmd in "$@" ; do + init_service $cmd +done