From eec3b7d6bc76a5864503a2bbdb94fca44e07b743 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Fri, 19 Jul 2019 10:07:43 +0200 Subject: [PATCH] move Docker stuff to egroupware repo for automatic builds --- doc/docker/README.md | 131 ++++++++++++++++++++++++++++++++++ doc/docker/docker-compose.yml | 114 +++++++++++++++++++++++++++++ doc/docker/fpm/Dockerfile | 95 ++++++++++++++++++++++++ doc/docker/fpm/build.sh | 36 ++++++++++ doc/docker/fpm/entrypoint.sh | 48 +++++++++++++ doc/docker/nginx.conf | 115 +++++++++++++++++++++++++++++ 6 files changed, 539 insertions(+) create mode 100644 doc/docker/README.md create mode 100644 doc/docker/docker-compose.yml create mode 100644 doc/docker/fpm/Dockerfile create mode 100755 doc/docker/fpm/build.sh create mode 100755 doc/docker/fpm/entrypoint.sh create mode 100644 doc/docker/nginx.conf diff --git a/doc/docker/README.md b/doc/docker/README.md new file mode 100644 index 0000000000..67233b1278 --- /dev/null +++ b/doc/docker/README.md @@ -0,0 +1,131 @@ +# Running EGroupware in Docker + +## Quick instructions +``` +curl https://raw.githubusercontent.com/EGroupware/egroupware/master/doc/docker/docker-compose.yml > docker-compose.yml +curl https://raw.githubusercontent.com/EGroupware/egroupware/master/doc/docker/nginx.conf > nginx.conf +# edit docker-compose.yml or nginx.conf, by default it will run on http://localhost:8080/ +docker-compose up -d +``` +## More information +The provided docker-compose.yml will run the following container: +* **egroupware** running latest PHP 7.3 as FPM (see fpm subdirectory for more information) +* **egroupware-nginx** running Nginx as webserver (by default http only on port 8080) +* **egroupware-db** latest MariaDB 10.4 +* **egroupware-watchtower** updating all above container automatically daily at 4am +``` +version: '3' +volumes: + sources: + db: + data: + driver_opts: + type: none + o: bind + # to upgrade an existing non-docker installation most easy is to use the existing + # data directory /var/lib/egroupware AND the host database see below + #device: /var/lib/egroupware + # otherwise data is stored in data subdirectory of the current directory + device: $PWD/data + # extra sources with apps not part of egroupware container + #extra: + # driver_opts: + # type: none + # o: bind + # # location of deprecated EGroupware packages like Wiki, SiteMgr, KnowledgeBase + # device: /usr/share/egroupware + # #device: $PWD/extra +services: + egroupware: + image: quay.io/egroupware/egroupware:latest + # EPL image: download.egroupware.org/egroupware/epl:latest + # setting a default language for a new installation + #environment: + #- LANG=de + volumes: + - sources:/usr/share/egroupware + # extra-sources rsync from entry-point into sources + #- extra:/usr/share/egroupware-extra + - data:/var/lib/egroupware + # if you want to use the host database: + # 1. comment out the whole db service below AND + # 2. set EGW_DB_HOST=localhost AND + # 3. uncomment the next line and modify the host path (first one), it depends on your distro: + # - RHEL/CentOS /var/lib/mysql/mysql.sock + # - openSUSE/SLE /var/run/mysql/mysql.sock + # - Debian/Ubuntu /var/run/mysqld/mysqld.sock + #- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock + environment: + # MariaDB/MySQL host to use: for internal service use "db", for host database (socket bind-mounted into container) use "localhost" + - EGW_DB_HOST=db + # for internal db service you should to specify a root password here AND in db service + # a database "egroupware" with a random password is created for you on installation (password is stored in header.inc.php in data directory) + #- EGW_DB_ROOT=root + - EGW_DB_ROOT_PW=secret + # alternativly you can specify an already existing database with full right by the given user! + #- EGW_DB_NAME=egroupware + #- EGW_DB_USER=egroupware + #- EGW_DB_PASS= + restart: always + depends_on: + - db + container_name: egroupware + # set the ip-address of your docker host AND your official DNS name so EGroupware + # can access Rocket.Chat or Collabora without the need to go over your firewall + #extra_hosts: + #- "my.host.name:ip-address" + + nginx: + image: nginx:stable-alpine + volumes: + - sources:/usr/share/egroupware:ro + # to add a certificate create a certificate.pem containing (in that order) + # 1. private key + # 2. public key + # 3. (optional) chain certificates + # uncomment to the next line + # ./certificate.pem:/etc/ssl/private/certificate.pem + # AND uncomment the three lines starting with "listen 443", "ssl_certificate", "ssl_certificate_key" in nginx.conf + - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro + ports: + # if no webserver is running on the host, change (first) number to 80 or 443 + - "8080:80" + - "4443:443" + depends_on: + - egroupware + container_name: egroupware-nginx + + # run an own MariaDB:10.4 (you can use EGroupware's database backup and restore to add your existing database) + db: + image: mariadb + environment: + #- MYSQL_ROOT=root + - MYSQL_ROOT_PASSWORD=secret + volumes: + - db:/var/lib/mysql + container_name: egroupware-db + + # automatic updates of all containers daily at 4am + # see https://containrrr.github.io/watchtower for more information + watchtower: + image: containrrr/watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + # For automatic EPL Updates you need to add your credentials here too + environment: + - WATCHTOWER_CLEANUP=true # delete old image after update to not fill up the disk + #- REPO_USER="your-repo-username" + #- REPO_PASSWORD="your-repo-password" + # for email notifications add your email and mail-server here + #- WATCHTOWER_NOTIFICATIONS=email + #- WATCHTOWER_NOTIFICATIONS_LEVEL=info # possible values: panic, fatal, error, warn, info or debug + #- WATCHTOWER_NOTIFICATION_EMAIL_FROM="watchtower@my-domain.com" + #- WATCHTOWER_NOTIFICATION_EMAIL_TO="me@my-domain.com" + #- WATCHTOWER_NOTIFICATION_EMAIL_SERVER="mail.my-domain.com" # if you give your MX here, you need no user/password + #- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=25 + #- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER="watchtower@my-domain.com" + #- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD="secret" + command: --schedule "0 0 4 * * *" + container_name: egroupware-watchtower + restart: always +``` diff --git a/doc/docker/docker-compose.yml b/doc/docker/docker-compose.yml new file mode 100644 index 0000000000..ad3c90f8f6 --- /dev/null +++ b/doc/docker/docker-compose.yml @@ -0,0 +1,114 @@ +version: '3' +volumes: + sources: + db: + data: + driver_opts: + type: none + o: bind + # to upgrade an existing non-docker installation most easy is to use the existing + # data directory /var/lib/egroupware AND the host database see below + #device: /var/lib/egroupware + # otherwise data is stored in data subdirectory of the current directory + device: $PWD/data + # extra sources with apps not part of egroupware container + #extra: + # driver_opts: + # type: none + # o: bind + # # location of deprecated EGroupware packages like Wiki, SiteMgr, KnowledgeBase + # device: /usr/share/egroupware + # #device: $PWD/extra +services: + egroupware: + image: quay.io/egroupware/egroupware:latest + # EPL image: download.egroupware.org/egroupware/epl:latest + # setting a default language for a new installation + #environment: + #- LANG=de + volumes: + - sources:/usr/share/egroupware + # extra-sources rsync from entry-point into sources + #- extra:/usr/share/egroupware-extra + - data:/var/lib/egroupware + # if you want to use the host database: + # 1. comment out the whole db service below AND + # 2. set EGW_DB_HOST=localhost AND + # 3. uncomment the next line and modify the host path (first one), it depends on your distro: + # - RHEL/CentOS /var/lib/mysql/mysql.sock + # - openSUSE/SLE /var/run/mysql/mysql.sock + # - Debian/Ubuntu /var/run/mysqld/mysqld.sock + #- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock + environment: + # MariaDB/MySQL host to use: for internal service use "db", for host database (socket bind-mounted into container) use "localhost" + - EGW_DB_HOST=db + # for internal db service you should to specify a root password here AND in db service + # a database "egroupware" with a random password is created for you on installation (password is stored in header.inc.php in data directory) + #- EGW_DB_ROOT=root + - EGW_DB_ROOT_PW=secret + # alternativly you can specify an already existing database with full right by the given user! + #- EGW_DB_NAME=egroupware + #- EGW_DB_USER=egroupware + #- EGW_DB_PASS= + restart: always + depends_on: + - db + container_name: egroupware + # set the ip-address of your docker host AND your official DNS name so EGroupware + # can access Rocket.Chat or Collabora without the need to go over your firewall + #extra_hosts: + #- "my.host.name:ip-address" + + nginx: + image: nginx:stable-alpine + volumes: + - sources:/usr/share/egroupware:ro + # to add a certificate create a certificate.pem containing (in that order) + # 1. private key + # 2. public key + # 3. (optional) chain certificates + # uncomment to the next line + # ./certificate.pem:/etc/ssl/private/certificate.pem + # AND uncomment the three lines starting with "listen 443", "ssl_certificate", "ssl_certificate_key" in nginx.conf + - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro + ports: + # if no webserver is running on the host, change (first) number to 80 or 443 + - "8080:80" + - "4443:443" + depends_on: + - egroupware + container_name: egroupware-nginx + + # run an own MariaDB:10.4 (you can use EGroupware's database backup and restore to add your existing database) + db: + image: mariadb + environment: + #- MYSQL_ROOT=root + - MYSQL_ROOT_PASSWORD=secret + volumes: + - db:/var/lib/mysql + container_name: egroupware-db + + # automatic updates of all containers daily at 4am + # see https://containrrr.github.io/watchtower for more information + watchtower: + image: containrrr/watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + # For automatic EPL Updates you need to add your credentials here too + environment: + - WATCHTOWER_CLEANUP=true # delete old image after update to not fill up the disk + #- REPO_USER="your-repo-username" + #- REPO_PASSWORD="your-repo-password" + # for email notifications add your email and mail-server here + #- WATCHTOWER_NOTIFICATIONS=email + #- WATCHTOWER_NOTIFICATIONS_LEVEL=info # possible values: panic, fatal, error, warn, info or debug + #- WATCHTOWER_NOTIFICATION_EMAIL_FROM="watchtower@my-domain.com" + #- WATCHTOWER_NOTIFICATION_EMAIL_TO="me@my-domain.com" + #- WATCHTOWER_NOTIFICATION_EMAIL_SERVER="mail.my-domain.com" # if you give your MX here, you need no user/password + #- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=25 + #- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER="watchtower@my-domain.com" + #- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD="secret" + command: --schedule "0 0 4 * * *" + container_name: egroupware-watchtower + restart: always diff --git a/doc/docker/fpm/Dockerfile b/doc/docker/fpm/Dockerfile new file mode 100644 index 0000000000..a20ad2abd4 --- /dev/null +++ b/doc/docker/fpm/Dockerfile @@ -0,0 +1,95 @@ +################################################################################ +## +## EGroupware FPM container using Ubuntu 18.04 and PHP 7.3 from ondrej/php PPA +## +################################################################################ +FROM ubuntu:18.04 +MAINTAINER rb@egroupware.org + +ARG VERSION=dev-master + +RUN apt-get update \ + && apt-get install -y software-properties-common \ + && LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php \ + && apt-get update \ + && bash -c "apt-get install -y php7.3-{cli,mysql,json,gd,xsl,bz2,opcache,apcu,tidy,zip,bcmath,mbstring,smbclient,ldap,curl,fpm,pgsql}" \ + # fpm and php.ini settings + && sed -e 's/^;\?listen \?=.*/listen = 9000/g' \ + -e '/allowed_clients/d' \ + -e '/pm.max_children/s/=.*/= 80/' \ + -e '/catch_workers_output/s/^;/;/' \ + -e '/error_log/d' \ + -e 's/^;\?pm.max_requests =.*/pm.max_requests = 30/' \ + -e 's/^;\?php_admin_value\[memory_limit\].*/php_admin_value[memory_limit] = 172M/' \ + -e 's/^;\?request_terminate_timeout.*/request_terminate_timeout = 70m/' \ + -i /etc/php/7.3/fpm/pool.d/www.conf \ + && sed -e 's/^;\?session.gc_maxlifetime.*/session.gc_maxlifetime = 14400/g' \ + -e 's|^;\?date.timezone.*|date.timezone = UTC|g' \ + -e 's|^;\?sys_temp_dir.*|sys_temp_dir = /tmp|g' \ + -e 's|^;\?disable_functions.*|disable_functions = exec,passthru,shell_exec,system,proc_open,popen|g' \ + -e 's|^;\?max_execution_time \?=.*|max_execution_time = 90|g' \ + -e 's|^;\?upload_max_filesize \?=.*|upload_max_filesize = 64M|g' \ + -e 's|^;\?post_max_size \?=.*|post_max_size = 65M|g' \ + -e 's|^;\?max_input_vars \?=.*|max_input_vars = 2000|g' \ + -e 's|^;\?zlib.output_compression \?=.*|zlib.output_compression = On|g' \ + -e 's|^;\?opcache.validate_timestamps \?=.*|opcache.validate_timestamps=0|g' \ + -i /etc/php/7.3/fpm/php.ini \ + && sed -e 's|^;\?date.timezone.*|date.timezone = UTC|g' \ + -e 's|^;\?sys_temp_dir.*|sys_temp_dir = /tmp|g' \ + -i /etc/php/7.3/cli/php.ini \ + && mkdir -p /run/php \ + # send logs to stderr to be viewed by docker logs + && ln -s /dev/stderr /var/log/php7.3-fpm.log \ + # install tools to build EGroupware + && apt-get install -y rsync npm zip curl sudo cron patch \ + && npm install -g grunt-cli \ + && bash -c \ +'EXPECTED_SIGNATURE=$(curl https://composer.github.io/installer.sig); \ +curl https://getcomposer.org/installer > composer-setup.php; \ +ACTUAL_SIGNATURE=$(php -r "echo hash_file(\"sha384\", \"composer-setup.php\");"); \ +if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]; \ +then \ + >&2 echo "ERROR: Invalid Composer installer signature"; \ + RESULT=1; \ +else \ + php composer-setup.php --quiet --install-dir /usr/local/bin; \ + RESULT=$?; \ +fi; \ +rm composer-setup.php; \ +exit $RESULT' \ + # build EGroupware + && cd /usr/share \ + && composer.phar create-project --prefer-dist --no-scripts egroupware/egroupware:$VERSION \ + && cd egroupware \ + && npm install \ + && grunt \ + # clean up and remove caches + && composer.phar clear-cache \ + && rm -f /usr/local/bin/composer.phar \ + && npm uninstall -g grunt-cli \ + && npm cache clear \ + && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false npm zip \ + && apt-get clean \ + # create data directory + && mkdir -p /var/lib/egroupware/default/files/sqlfs \ + && mkdir -p /var/lib/egroupware/default/backup \ + && chown -R www-data:www-data /var/lib/egroupware \ + && chmod 700 /var/lib/egroupware/ \ + && ln -s /var/lib/egroupware/header.inc.php /usr/share/egroupware \ + # install cron-job and disable fallback async service and ability to switch them off in admin + && sed 's/apache/www-data/' doc/rpm-build/egroupware.cron > /etc/cron.d/egroupware \ + && patch -p1 < doc/rpm-build/asyncservice.patch \ + # disable certificate checks for LDAP as most LDAP and AD servers have no "valid" cert + && echo "TLS_REQCERT never" >> /etc/ldap/ldap.conf \ + # mv sources to a different directory so entrypoint can rsync them to volumn for both nginx and fpm + && mv /usr/share/egroupware /usr/share/egroupware-sources + +VOLUME /usr/share/egroupware +VOLUME /var/lib/egroupware + +EXPOSE 9000 + +ADD entrypoint.sh / + +CMD ["php-fpm7.3", "--nodaemonize"] +ENTRYPOINT ["/entrypoint.sh"] diff --git a/doc/docker/fpm/build.sh b/doc/docker/fpm/build.sh new file mode 100755 index 0000000000..ac65370dbf --- /dev/null +++ b/doc/docker/fpm/build.sh @@ -0,0 +1,36 @@ +#!/bin/bash -x + +TAG=${1:-dev-master} +VERSION=$TAG + +[ $VERSION = "dev-master" ] && { + cd ~/egroupware + grep self.version composer.json | while read pack version; do composer update $(echo $pack|cut -d'"' -f2); done + git status composer.lock|grep composer.lock && { + git stash; git pull --rebase; git stash pop + git commit -m 'updating composer.lock with latest commit hashed for egroupware/* packages' composer.lock + VERSION="$VERSION#$(git push|grep master|cut -c4-10)" + } +} + +cd $(dirname $0) + +docker pull ubuntu:18.04 +docker build --no-cache --build-arg "VERSION=$VERSION" -t egroupware/egroupware:$TAG . && { + docker push egroupware/egroupware:$TAG + # tag only stable releases as latest + [ $TAG != "dev-master" ] && \ + { + docker tag egroupware/egroupware:$TAG egroupware/egroupware:latest + docker push egroupware/egroupware:latest + } + BRANCH=$(echo $VERSION|sed 's/\.[0-9]\{8\}$//') + [ "$BRANCH" != $VERSION -a "dev-$BRANCH" != $VERSION ] && { + docker tag egroupware/egroupware:$VERSION egroupware/egroupware:$BRANCH + docker push egroupware/egroupware:$BRANCH + } + [ $VERSION != "dev-master" ] && { + docker tag egroupware/egroupware:$VERSION egroupware/egroupware:latest + docker push egroupware/egroupware:latest + } +} diff --git a/doc/docker/fpm/entrypoint.sh b/doc/docker/fpm/entrypoint.sh new file mode 100755 index 0000000000..3c78789aec --- /dev/null +++ b/doc/docker/fpm/entrypoint.sh @@ -0,0 +1,48 @@ +#!/bin/bash +set -e +set -x + +# ToDo check version before copy +rsync -a --delete /usr/share/egroupware-sources/ /usr/share/egroupware/ + +# sources of extra apps merged into our sources (--ignore-existing to NOT overwrite any regular sources!) +test -d /usr/share/egroupware-extra && \ + rsync -a --ignore-existing /usr/share/egroupware-extra/ /usr/share/egroupware/ + +# check and if necessary change ownership of /var/lib/egroupware +test $(stat -c '%U' /var/lib/egroupware) = "www-data" || \ + chown -R www-data:www-data /var/lib/egroupware + +# write install-log in /var/lib/egroupware (only readable by root!) +LOG=/var/lib/egroupware/egroupware-docker-install.log +touch $LOG +chmod 600 $LOG + +max_retries=10 +try=0 +until php /usr/share/egroupware/doc/rpm-build/post_install.php \ + --start_webserver "" --autostart_webserver "" \ + --start_db "" --autostart_db "" \ + --db_type "${EGW_DB_TYPE:-mysqli}" \ + --db_host "${EGW_DB_HOST:-localhost}" \ + --db_grant_host "${EGW_DB_GRANT_HOST:-%}" \ + --db_root "${EGW_DB_ROOT:-root}" \ + --db_root_pw "${EGW_DB_ROOT_PW:-}" \ + --db_name "${EGW_DB_NAME:-egroupware}" \ + --db_user "${EGW_DB_USER:-egroupware}" \ + --db_pass "${EGW_DB_PASS:-}" || [ "$try" -gt "$max_retries" ] +do + echo "Retrying EGroupware installation in 3 seconds ..." + try=$((try+1)) + sleep 3s +done 2>&1 | tee -a $LOG + +if [ "$try" -gt "$max_retries" ]; then + echo "Installing of EGroupware failed!" | tee -a $LOG + exit 1 +fi + +# to run async jobs +service cron start + +exec "$@" \ No newline at end of file diff --git a/doc/docker/nginx.conf b/doc/docker/nginx.conf new file mode 100644 index 0000000000..333f38e910 --- /dev/null +++ b/doc/docker/nginx.conf @@ -0,0 +1,115 @@ +# stuff for http block +client_max_body_size 1g; +# fix error: upstream sent too big header while reading response header from upstream +fastcgi_buffers 16 16k; +fastcgi_buffer_size 32k; + +upstream fpm { + server egroupware:9000; +} + +server { + access_log off; + + listen 80 default_server; + + # ssl config (enable following line plus either include or ssl_certificate* line) + #listen 443 ssl http2 default_server; + #include snippets/snakeoil.conf; # requires ssl-certs package installed! + # concatenate private key, certificate and intermediate certs to /etc/ssl/private/certificate.pem + #ssl_certificate /etc/ssl/private/certificate.pem; + #ssl_certificate_key /etc/ssl/private/certificate.pem; + # HTTP Strict-Transport-Security header (start with a short max-age!) + #add_header Strict-Transport-Security max-age=31536000; # 31536000sec=1year + + server_name _; + root /var/www/html; + + index index.php index.nginx-debian.html index.html index.htm; + + # other settings + client_max_body_size 65M; + + # EGroupware installed in /usr/share/egroupware + location ^~ /egroupware { + alias /usr/share/egroupware/; + try_files $uri $uri/ =404; + location ~ ^/egroupware(/(?U).+\.php) { + alias /usr/share/egroupware; + fastcgi_pass fpm; + # added to support WebDAV/CalDAV/CardDAV + fastcgi_read_timeout 60m; + fastcgi_index index.php; + fastcgi_split_path_info ^((?U).+\.php)(.*)$; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; + # standard Nginx + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/share/egroupware$1; + fastcgi_param DOCUMENT_ROOT /var/www/html; + } + location ~ (?i)\.(ico|jpe?g|gif|png|svg|xet|xml|js|css|html|map|swf)$ { + access_log off; + expires 10d; + add_header Pragma public; + add_header Cache-Control "public"; + location ~ ^/egroupware(/.*)$ { + alias /usr/share/egroupware/; + try_files $1 =404; + } + } + } + + # PHP in docroot + #location ~ \.php { + # fastcgi_pass fpm; + # include fastcgi_params; + #} + + # phpmyadmin in /usr/share/phpmyadmin + #location /phpmyadmin { + # alias /usr/share/phpmyadmin/; + # try_files $uri $uri/ =404; + # location ~ ^/phpmyadmin(/(?U).+\.php) { + # alias /usr/share/phpmyadmin; + # fastcgi_pass fpm; + # fastcgi_index index.php; + # fastcgi_split_path_info ^((?U).+\.php)(.*)$; + # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + # fastcgi_param PATH_INFO $fastcgi_path_info; + # fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; + # # standard Nginx + # include fastcgi_params; + # fastcgi_param DOCUMENT_ROOT /var/www/html; + # fastcgi_param SCRIPT_FILENAME /usr/share/phpmyadmin$1; + # } + #} + + # ActiveSync support + location /Microsoft-Server-ActiveSync { + fastcgi_pass fpm; + # added to support WebDAV/CalDAV/CardDAV + fastcgi_read_timeout 60m; + fastcgi_index index.php; + fastcgi_split_path_info ^((?U).+\.php)(.*)$; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/share/egroupware/activesync/index.php; + } + # CalDAV & CardDAV autoconfig + location ~ ^/.well-known/(caldav|carddav)$ { + return 301 $scheme://$host/egroupware/groupdav.php/; + } + location ~ ^(/principals/users/.*)$ { + return 301 $scheme://$host/egroupware/groupdav.php$1; + } + # Nginx does NOT use index for OPTIONS requests breakng WebDAV + # for Windows, which sends OPTIONS / and stalls on Nginx 405 response! + # This also redirects all requests to root to EGroupware. + location = / { + return 301 $scheme://$host/egroupware/index.php; + } +}