diff --git a/bin/quickstart.sh b/bin/quickstart.sh index 565eb97d..79acbabf 100755 --- a/bin/quickstart.sh +++ b/bin/quickstart.sh @@ -1,133 +1,157 @@ #!/bin/bash set -e +set -x function die() { echo "$1" exit 1 } rpm -qv docker-compose >/dev/null 2>&1 || \ test ! -z "$(which docker-compose 2>/dev/null)" || \ die "Is docker-compose installed?" test ! -z "$(grep 'systemd.unified_cgroup_hierarchy=0' /proc/cmdline)" || \ die "systemd containers only work with cgroupv1 (use 'grubby --update-kernel=ALL --args=\"systemd.unified_cgroup_hierarchy=0\"' and a reboot to fix)" base_dir=$(dirname $(dirname $0)) export DOCKER_BUILDKIT=0 docker-compose down -t 1 --remove-orphans docker volume rm kolab_mariadb || : docker volume rm kolab_imap || : docker volume rm kolab_ldap || : docker volume rm kolab_minio || : # We can't use the following artisan commands because it will just block if redis is unavailable: # src/artisan octane:stop >/dev/null 2>&1 || : # src/artisan horizon:terminate >/dev/null 2>&1 || : # we therefore just kill all artisan processes running. pkill -9 -f artisan || : pkill -9 -f swoole || : bin/regen-certs -docker-compose build coturn ldap kolab mariadb meet pdns proxy redis haproxy roundcube -docker-compose up -d coturn ldap kolab mariadb meet pdns redis roundcube minio + +docker-compose build + +if grep -q "ldap" docker-compose.override.yml; then + docker-compose up -d ldap +fi +# We grep for something that is unique to the container +if grep -q "kolab-init" docker-compose.override.yml; then + docker-compose up -d kolab +fi +if grep -q "imap" docker-compose.override.yml; then + docker-compose up -d imap +fi +if grep -q "postfix" docker-compose.override.yml; then + docker-compose up -d postfix +fi +docker-compose up -d coturn mariadb meet pdns redis roundcube minio # Workaround until we have docker-compose --wait (https://github.com/docker/compose/pull/8777) function wait_for_container { container_id="$1" container_name="$(docker inspect "${container_id}" --format '{{ .Name }}')" echo "Waiting for container: ${container_name} [${container_id}]" waiting_done="false" while [[ "${waiting_done}" != "true" ]]; do container_state="$(docker inspect "${container_id}" --format '{{ .State.Status }}')" if [[ "${container_state}" == "running" ]]; then health_status="$(docker inspect "${container_id}" --format '{{ .State.Health.Status }}')" echo "${container_name}: container_state=${container_state}, health_status=${health_status}" if [[ ${health_status} == "healthy" ]]; then waiting_done="true" fi else echo "${container_name}: container_state=${container_state}" waiting_done="true" fi sleep 1; done; } if [ "$1" == "--nodev" ]; then echo "starting everything in containers" docker-compose -f docker-compose.build.yml build swoole docker-compose build webapp docker-compose up -d webapp wait_for_container 'kolab-webapp' - docker-compose up --no-deps -d proxy haproxy + if grep -q "haproxy" docker-compose.override.yml; then + docker-compose up --no-deps -d haproxy + fi + docker-compose up --no-deps -d proxy exit 0 fi echo "Starting the development environment" rpm -qv composer >/dev/null 2>&1 || \ test ! -z "$(which composer 2>/dev/null)" || \ die "Is composer installed?" rpm -qv npm >/dev/null 2>&1 || \ test ! -z "$(which npm 2>/dev/null)" || \ die "Is npm installed?" rpm -qv php >/dev/null 2>&1 || \ test ! -z "$(which php 2>/dev/null)" || \ die "Is php installed?" rpm -qv php-ldap >/dev/null 2>&1 || \ test ! -z "$(php --ini | grep ldap)" || \ die "Is php-ldap installed?" rpm -qv php-mysqlnd >/dev/null 2>&1 || \ test ! -z "$(php --ini | grep mysql)" || \ die "Is php-mysqlnd installed?" test ! -z "$(php --modules | grep swoole)" || \ die "Is swoole installed?" -# Ensure the containers we depend on are fully started -wait_for_container 'kolab' +# We grep for something that is unique to the container +if grep -q "kolab-init" docker-compose.override.yml; then + wait_for_container 'kolab' +fi wait_for_container 'kolab-redis' pushd ${base_dir}/src/ rm -rf vendor/ composer.lock php -dmemory_limit=-1 $(which composer) install npm install find bootstrap/cache/ -type f ! -name ".gitignore" -delete ./artisan key:generate ./artisan clear-compiled ./artisan cache:clear ./artisan horizon:install if rpm -qv chromium 2>/dev/null; then chver=$(rpmquery --queryformat="%{VERSION}" chromium | awk -F'.' '{print $1}') ./artisan dusk:chrome-driver ${chver} fi if [ ! -f 'resources/countries.php' ]; then ./artisan data:countries fi npm run dev popd pushd ${base_dir}/src/ rm -rf database/database.sqlite ./artisan db:ping --wait php -dmemory_limit=512M ./artisan migrate:refresh --seed ./artisan data:import || : nohup ./artisan octane:start --host=$(grep OCTANE_HTTP_HOST .env | tail -n1 | sed "s/OCTANE_HTTP_HOST=//") > octane.out & nohup ./artisan horizon > horizon.out & popd -docker-compose up --no-deps -d proxy haproxy +if grep -q "haproxy" docker-compose.override.yml; then + docker-compose up --no-deps -d haproxy +fi +docker-compose up --no-deps -d proxy diff --git a/config.demo/docker-compose.override.yml b/config.demo/docker-compose.override.yml index a0bf1c18..a8f03d84 100644 --- a/config.demo/docker-compose.override.yml +++ b/config.demo/docker-compose.override.yml @@ -1,48 +1,128 @@ version: '3' services: - haproxy: - depends_on: - proxy: - condition: service_healthy proxy: depends_on: - kolab: + imap: + condition: service_healthy + postfix: condition: service_healthy webapp: condition: service_healthy build: context: ./docker/proxy/ args: APP_WEBSITE_DOMAIN: ${APP_WEBSITE_DOMAIN:?err} SSL_CERTIFICATE: ${PROXY_SSL_CERTIFICATE:?err} SSL_CERTIFICATE_KEY: ${PROXY_SSL_CERTIFICATE_KEY:?err} healthcheck: interval: 10s test: "kill -0 $$(cat /run/nginx.pid)" timeout: 5s retries: 30 container_name: kolab-proxy restart: on-failure hostname: proxy image: kolab-proxy extra_hosts: - "meet:${MEET_LISTENING_HOST}" networks: kolab: ipv4_address: 172.18.0.7 tmpfs: - /run - /tmp - /var/run - /var/tmp tty: true volumes: - ./docker/certs/:/etc/certs/:ro - /etc/letsencrypt/:/etc/letsencrypt/:ro ports: + # - "25:25" # - "80:80" - "443:443" - "465:465" - "587:587" - "143:143" - "993:993" + imap: + build: + context: ./docker/imap/ + environment: + - APP_DOMAIN=${APP_DOMAIN} + - IMAP_ADMIN_LOGIN=${IMAP_ADMIN_LOGIN} + - IMAP_ADMIN_PASSWORD=${IMAP_ADMIN_PASSWORD} + healthcheck: + interval: 10s + test: "kill -0 1" + timeout: 5s + retries: 30 + container_name: kolab-imap + restart: on-failure + hostname: imap + image: kolab-imap + networks: + kolab: + ipv4_address: 172.18.0.12 + extra_hosts: + - "kolab.mgmt.com:127.0.0.1" + - "services.${APP_DOMAIN}:172.18.0.4" + tmpfs: + - /run + - /tmp + - /var/run + - /var/tmp + tty: true + volumes: + - ./docker/certs/:/etc/certs/:ro + - /etc/letsencrypt/:/etc/letsencrypt/:ro + - imap-spool:/var/spool/imap + - imap-lib:/var/lib/imap + ports: + - "11080:11080" + - "11143:11143" + - "11024:11024" + postfix: + build: + context: ./docker/postfix/ + healthcheck: + interval: 10s + test: "kill -0 1" + timeout: 5s + retries: 30 + environment: + - APP_DOMAIN=${APP_DOMAIN} + - DB_HOST=mariadb + - DB_USERNAME=${DB_USERNAME} + - DB_PASSWORD=${DB_PASSWORD} + - DB_DATABASE=${DB_DATABASE} + - LMTP_DESTINATION="imap:11024" + container_name: kolab-postfix + restart: on-failure + hostname: postfix + image: kolab-postfix + networks: + kolab: + ipv4_address: 172.18.0.13 + extra_hosts: + - "kolab.mgmt.com:127.0.0.1" + - "services.${APP_DOMAIN}:172.18.0.4" + tmpfs: + - /run + - /tmp + - /var/run + - /var/tmp + tty: true + volumes: + - ./docker/certs/:/etc/certs/:ro + - /etc/letsencrypt/:/etc/letsencrypt/:ro + - postfix-spool:/var/spool/postfix + - postfix-lib:/var/lib/postfix + ports: + - "10587:10587" + - "10025:10025" +volumes: + postfix-spool: + postfix-lib: + imap-spool: + imap-lib: diff --git a/config.demo/src/.env b/config.demo/src/.env index 2a56740b..6941bdc9 100644 --- a/config.demo/src/.env +++ b/config.demo/src/.env @@ -1,200 +1,200 @@ APP_NAME=Kolab APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=https://{{ host }} APP_PASSPHRASE=simple123 APP_PUBLIC_URL=https://{{ host }} APP_DOMAIN={{ host }} APP_WEBSITE_DOMAIN={{ host }} APP_THEME=default APP_TENANT_ID=5 APP_LOCALE=en APP_LOCALES= APP_WITH_ADMIN=1 APP_WITH_RESELLER=1 APP_WITH_SERVICES=1 APP_WITH_FILES=1 APP_LDAP=1 APP_IMAP=1 APP_HEADER_CSP="connect-src 'self'; child-src 'self'; font-src 'self'; form-action 'self' data:; frame-ancestors 'self'; img-src blob: data: 'self' *; media-src 'self'; object-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-eval' 'unsafe-inline'; default-src 'self';" APP_HEADER_XFO=sameorigin SIGNUP_LIMIT_EMAIL=0 SIGNUP_LIMIT_IP=0 ASSET_URL=https://{{ host }} WEBMAIL_URL=/roundcubemail/ SUPPORT_URL=/support SUPPORT_EMAIL=support@example.com LOG_CHANNEL=stdout LOG_SLOW_REQUESTS=5 LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=mysql DB_DATABASE=kolabdev DB_HOST=mariadb DB_PASSWORD=kolab DB_ROOT_PASSWORD=Welcome2KolabSystems DB_PORT=3306 DB_USERNAME=kolabdev BROADCAST_DRIVER=redis CACHE_DRIVER=redis QUEUE_CONNECTION=redis SESSION_DRIVER=file SESSION_LIFETIME=120 OPENEXCHANGERATES_API_KEY="from openexchangerates.org" MFA_DSN=mysql://roundcube:kolab@mariadb/roundcube MFA_TOTP_DIGITS=6 MFA_TOTP_INTERVAL=30 MFA_TOTP_DIGEST=sha1 -IMAP_URI=ssl://kolab:11993 -IMAP_HOST=172.18.0.5 +IMAP_URI=imap:10143 +IMAP_HOST=172.18.0.12 IMAP_ADMIN_LOGIN=cyrus-admin IMAP_ADMIN_PASSWORD=Welcome2KolabSystems IMAP_VERIFY_HOST=false IMAP_VERIFY_PEER=false LDAP_BASE_DN="dc=mgmt,dc=com" LDAP_DOMAIN_BASE_DN="ou=Domains,dc=mgmt,dc=com" LDAP_HOSTS=ldap LDAP_PORT=389 LDAP_SERVICE_BIND_DN="uid=kolab-service,ou=Special Users,dc=mgmt,dc=com" LDAP_SERVICE_BIND_PW="Welcome2KolabSystems" LDAP_USE_SSL=false LDAP_USE_TLS=false # Administrative LDAP_ADMIN_BIND_DN="cn=Directory Manager" LDAP_ADMIN_BIND_PW="Welcome2KolabSystems" LDAP_ADMIN_ROOT_DN="dc=mgmt,dc=com" # Hosted (public registration) LDAP_HOSTED_BIND_DN="uid=hosted-kolab-service,ou=Special Users,dc=mgmt,dc=com" LDAP_HOSTED_BIND_PW="Welcome2KolabSystems" LDAP_HOSTED_ROOT_DN="dc=hosted,dc=com" COTURN_PUBLIC_IP='{{ public_ip }}' COTURN_STATIC_SECRET="Welcome2KolabSystems" MEET_WEBHOOK_TOKEN=Welcome2KolabSystems MEET_SERVER_TOKEN=Welcome2KolabSystems MEET_SERVER_URLS=https://{{ host }}/meetmedia/api/ MEET_SERVER_VERIFY_TLS=false MEET_WEBRTC_LISTEN_IP='172.18.0.1' MEET_PUBLIC_DOMAIN={{ host }} MEET_TURN_SERVER='turn:172.18.0.1:3478' MEET_LISTENING_HOST=172.18.0.1 PGP_ENABLE=true PGP_BINARY=/usr/bin/gpg PGP_AGENT=/usr/bin/gpg-agent PGP_GPGCONF=/usr/bin/gpgconf PGP_LENGTH= # Set these to IP addresses you serve WOAT with. # Have the domain owner point _woat. NS RRs refer to ns0{1,2}. WOAT_NS1=ns01.domain.tld WOAT_NS2=ns02.domain.tld REDIS_HOST=redis REDIS_PASSWORD=null REDIS_PORT=6379 OCTANE_HTTP_HOST=0.0.0.0 SWOOLE_PACKAGE_MAX_LENGTH=10485760 PAYMENT_PROVIDER= MOLLIE_KEY= STRIPE_KEY= STRIPE_PUBLIC_KEY= STRIPE_WEBHOOK_SECRET= MAIL_DRIVER=log MAIL_MAILER=smtp -MAIL_HOST=smtp.mailtrap.io -MAIL_PORT=2525 +MAIL_HOST=172.18.0.13 +MAIL_PORT=10587 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS="noreply@example.com" MAIL_FROM_NAME="Example.com" MAIL_REPLYTO_ADDRESS="replyto@example.com" MAIL_REPLYTO_NAME=null DNS_TTL=3600 DNS_SPF="v=spf1 mx -all" DNS_STATIC="%s. MX 10 ext-mx01.mykolab.com." DNS_COPY_FROM=null AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= AWS_USE_PATH_STYLE_ENDPOINT=false PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1 MIX_ASSET_PATH='/' MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" PASSWORD_POLICY= COMPANY_NAME=kolab.org COMPANY_ADDRESS= COMPANY_DETAILS= COMPANY_EMAIL= COMPANY_LOGO= COMPANY_FOOTER= VAT_COUNTRIES=CH,LI VAT_RATE=7.7 KB_ACCOUNT_DELETE= KB_ACCOUNT_SUSPENDED= KB_PAYMENT_SYSTEM= KOLAB_SSL_CERTIFICATE=/etc/pki/tls/certs/kolab.hosted.com.cert KOLAB_SSL_CERTIFICATE_FULLCHAIN=/etc/pki/tls/certs/kolab.hosted.com.chain.pem KOLAB_SSL_CERTIFICATE_KEY=/etc/pki/tls/certs/kolab.hosted.com.key PROXY_SSL_CERTIFICATE=/etc/certs/imap.hosted.com.cert PROXY_SSL_CERTIFICATE_KEY=/etc/certs/imap.hosted.com.key APP_KEY=base64:FG6ECzyAMSmyX+eYwO/FW3bwnarbKkBhqtO65vlMb1E= COTURN_STATIC_SECRET=uzYguvIl9tpZFMuQOE78DpOi6Jc7VFSD0UAnvgMsg5n4e74MgIf6vQvbc6LWzZjz MOLLIE_KEY="from mollie" STRIPE_KEY="from stripe" STRIPE_PUBLIC_KEY="from stripe" STRIPE_WEBHOOK_SECRET="from stripe" OX_API_KEY="from openexchange" FIREBASE_API_KEY="from firebase" #Generated by php artisan passport:client --password, but can be left hardcoded (the seeder will pick it up) PASSPORT_PROXY_OAUTH_CLIENT_ID=942edef5-3dbd-4a14-8e3e-d5d59b727bee PASSPORT_PROXY_OAUTH_CLIENT_SECRET=L6L0n56ecvjjK0cJMjeeV1pPAeffUBO0YSSH63wf MINIO_USER=minio MINIO_PASSWORD=W3lcom32@ph3lia MINIO_BUCKET=kolab FILESYSTEM_DISK=minio diff --git a/config.prod/src/.env b/config.prod/src/.env index 4a8a7729..611206e2 100644 --- a/config.prod/src/.env +++ b/config.prod/src/.env @@ -1,158 +1,161 @@ APP_NAME=Kolab APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=https://{{ host }} APP_PUBLIC_URL=https://{{ host }} APP_DOMAIN={{ host }} APP_WEBSITE_DOMAIN={{ host }} APP_THEME=default APP_TENANT_ID=5 APP_LOCALE=en APP_LOCALES= APP_WITH_ADMIN=1 APP_WITH_RESELLER=1 APP_WITH_SERVICES=1 APP_WITH_FILES=1 APP_WITH_WALLET=0 APP_WITH_SIGNUP=0 -APP_LDAP=1 +APP_LDAP=0 APP_IMAP=1 APP_HEADER_CSP="connect-src 'self'; child-src 'self'; font-src 'self'; form-action 'self' data:; frame-ancestors 'self'; img-src blob: data: 'self' *; media-src 'self'; object-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-eval' 'unsafe-inline'; default-src 'self';" APP_HEADER_XFO=sameorigin ASSET_URL=https://{{ host }} WEBMAIL_URL=/roundcubemail/ SUPPORT_URL=/support LOG_CHANNEL=stdout LOG_SLOW_REQUESTS=5 LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=mysql DB_DATABASE=kolabdev DB_HOST=mariadb DB_PASSWORD={{ admin_password }} DB_ROOT_PASSWORD={{ admin_password }} DB_PORT=3306 DB_USERNAME=kolabdev BROADCAST_DRIVER=redis CACHE_DRIVER=redis QUEUE_CONNECTION=redis SESSION_DRIVER=file SESSION_LIFETIME=120 OPENEXCHANGERATES_API_KEY="from openexchangerates.org" MFA_DSN=mysql://roundcube:{{ admin_password }}@mariadb/roundcube MFA_TOTP_DIGITS=6 MFA_TOTP_INTERVAL=30 MFA_TOTP_DIGEST=sha1 -IMAP_URI=ssl://kolab:11993 -IMAP_HOST=172.18.0.5 +IMAP_URI=imap:11143 +IMAP_HOST=172.18.0.12 IMAP_ADMIN_LOGIN=cyrus-admin IMAP_ADMIN_PASSWORD={{ admin_password }} IMAP_VERIFY_HOST=false IMAP_VERIFY_PEER=false +SMTP_HOST=172.18.0.13 +SMTP_PORT=10587 + LDAP_BASE_DN="dc=mgmt,dc=com" LDAP_DOMAIN_BASE_DN="ou=Domains,dc=mgmt,dc=com" LDAP_HOSTS=ldap LDAP_PORT=389 LDAP_SERVICE_BIND_DN="uid=kolab-service,ou=Special Users,dc=mgmt,dc=com" LDAP_SERVICE_BIND_PW="{{ admin_password }}" LDAP_USE_SSL=false LDAP_USE_TLS=false # Administrative LDAP_ADMIN_BIND_DN="cn=Directory Manager" LDAP_ADMIN_BIND_PW="{{ admin_password }}" LDAP_ADMIN_ROOT_DN="dc=mgmt,dc=com" # Hosted (public registration) LDAP_HOSTED_BIND_DN="uid=hosted-kolab-service,ou=Special Users,dc=mgmt,dc=com" LDAP_HOSTED_BIND_PW="{{ admin_password }}" LDAP_HOSTED_ROOT_DN="dc=hosted,dc=com" COTURN_PUBLIC_IP='{{ public_ip }}' MEET_SERVER_URLS=https://{{ host }}/meetmedia/api/ MEET_SERVER_VERIFY_TLS=false MEET_WEBRTC_LISTEN_IP='172.18.0.1' MEET_PUBLIC_DOMAIN={{ host }} MEET_TURN_SERVER='turn:172.18.0.1:3478' MEET_LISTENING_HOST=172.18.0.1 PGP_ENABLE=true PGP_BINARY=/usr/bin/gpg PGP_AGENT=/usr/bin/gpg-agent PGP_GPGCONF=/usr/bin/gpgconf PGP_LENGTH= REDIS_HOST=redis REDIS_PASSWORD=null REDIS_PORT=6379 OCTANE_HTTP_HOST={{ host }} SWOOLE_PACKAGE_MAX_LENGTH=10485760 MAIL_DRIVER=log MAIL_MAILER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS="noreply@example.com" MAIL_FROM_NAME="Example.com" MAIL_REPLYTO_ADDRESS="replyto@example.com" MAIL_REPLYTO_NAME=null DNS_TTL=3600 DNS_SPF="v=spf1 mx -all" DNS_STATIC="%s. MX 10 ext-mx01.mykolab.com." DNS_COPY_FROM=null MIX_ASSET_PATH='/' PASSWORD_POLICY= COMPANY_NAME=kolab.org COMPANY_ADDRESS= COMPANY_DETAILS= COMPANY_EMAIL= COMPANY_LOGO= COMPANY_FOOTER= VAT_COUNTRIES=CH,LI VAT_RATE=7.7 KB_ACCOUNT_DELETE= KB_ACCOUNT_SUSPENDED= KB_PAYMENT_SYSTEM= KOLAB_SSL_CERTIFICATE=/etc/pki/tls/certs/kolab.hosted.com.cert KOLAB_SSL_CERTIFICATE_FULLCHAIN=/etc/pki/tls/certs/kolab.hosted.com.chain.pem KOLAB_SSL_CERTIFICATE_KEY=/etc/pki/tls/certs/kolab.hosted.com.key PROXY_SSL_CERTIFICATE=/etc/certs/imap.hosted.com.cert PROXY_SSL_CERTIFICATE_KEY=/etc/certs/imap.hosted.com.key OPENEXCHANGERATES_API_KEY={{ openexchangerates_api_key }} FIREBASE_API_KEY={{ firebase_api_key }} MINIO_USER=minio MINIO_PASSWORD=W3lcom32@ph3lia MINIO_BUCKET=kolab FILESYSTEM_DISK=minio diff --git a/docker-compose.yml b/docker-compose.yml index a540aa50..3897f1c0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,372 +1,218 @@ version: '3' services: coturn: build: context: ./docker/coturn/ container_name: kolab-coturn healthcheck: interval: 10s test: "kill -0 $$(cat /tmp/turnserver.pid)" timeout: 5s retries: 30 environment: - TURN_PUBLIC_IP=${COTURN_PUBLIC_IP} - TURN_LISTEN_PORT=3478 - TURN_STATIC_SECRET=${COTURN_STATIC_SECRET} hostname: sturn.mgmt.com image: kolab-coturn network_mode: host restart: on-failure - kolab: - build: - context: ./docker/kolab/ - args: - DB_KOLAB_DATABASE: kolab - DB_KOLAB_USERNAME: kolab - DB_KOLAB_PASSWORD: ${DB_PASSWORD:?"DB_PASSWORD is missing"} - LDAP_HOST: ldap - LDAP_ADMIN_BIND_DN: ${LDAP_ADMIN_BIND_DN} - LDAP_ADMIN_BIND_PW: ${LDAP_ADMIN_BIND_PW} - LDAP_SERVICE_BIND_PW: ${LDAP_SERVICE_BIND_PW} - IMAP_ADMIN_LOGIN: ${IMAP_ADMIN_LOGIN} - IMAP_ADMIN_PASSWORD: ${IMAP_ADMIN_PASSWORD} - container_name: kolab - privileged: true - restart: on-failure - tty: true - depends_on: - mariadb: - condition: service_healthy - pdns: - condition: service_healthy - ldap: - condition: service_healthy - extra_hosts: - - "kolab.mgmt.com:127.0.0.1" - - "services.${APP_DOMAIN}:172.18.0.4" - environment: - - APP_DOMAIN=${APP_DOMAIN} - - LDAP_HOST=ldap - - LDAP_ADMIN_BIND_DN=${LDAP_ADMIN_BIND_DN} - - LDAP_ADMIN_BIND_PW=${LDAP_ADMIN_BIND_PW} - - LDAP_SERVICE_BIND_PW=${LDAP_SERVICE_BIND_PW} - - DB_HOST=mariadb - - DB_ROOT_PASSWORD=${DB_ROOT_PASSWORD} - - DB_HKCCP_DATABASE=${DB_DATABASE} - - DB_HKCCP_USERNAME=${DB_USERNAME} - - DB_HKCCP_PASSWORD=${DB_PASSWORD:?"DB_PASSWORD is missing"} - - DB_KOLAB_DATABASE=kolab - - DB_KOLAB_USERNAME=kolab - - DB_KOLAB_PASSWORD=${DB_PASSWORD:?"DB_PASSWORD is missing"} - - SSL_CERTIFICATE=${KOLAB_SSL_CERTIFICATE:?"KOLAB_SSL_CERTIFICATE is missing"} - - SSL_CERTIFICATE_FULLCHAIN=${KOLAB_SSL_CERTIFICATE_FULLCHAIN:?"KOLAB_SSL_CERTIFICATE_FULLCHAIN is missing"} - - SSL_CERTIFICATE_KEY=${KOLAB_SSL_CERTIFICATE_KEY:?"KOLAB_SSL_CERTIFICATE_KEY is missing"} - - IMAP_HOST=127.0.0.1 - - IMAP_PORT=11993 - - IMAP_ADMIN_LOGIN=${IMAP_ADMIN_LOGIN} - - IMAP_ADMIN_PASSWORD=${IMAP_ADMIN_PASSWORD} - - MAIL_HOST=127.0.0.1 - - MAIL_PORT=10587 - healthcheck: - interval: 10s - test: "systemctl is-active kolab-init || exit 1" - timeout: 5s - retries: 30 - start_period: 5m - # This makes docker's dns, resolve via pdns for this container. - # Please note it does not affect /etc/resolv.conf - dns: 172.18.0.11 - hostname: kolab.mgmt.com - image: kolab - networks: - kolab: - ipv4_address: 172.18.0.5 - ports: - - "12143:12143" - tmpfs: - - /run - - /tmp - - /var/run - - /var/tmp - volumes: - - ./ext/:/src/:ro - - /etc/letsencrypt/:/etc/letsencrypt/:ro - - ./docker/certs/ca.cert:/etc/pki/tls/certs/ca.cert:ro - - ./docker/certs/ca.cert:/etc/pki/ca-trust/source/anchors/ca.cert:ro - - ./docker/certs/kolab.hosted.com.cert:${KOLAB_SSL_CERTIFICATE:?err} - - ./docker/certs/kolab.hosted.com.chain.pem:${KOLAB_SSL_CERTIFICATE_FULLCHAIN:?err} - - ./docker/certs/kolab.hosted.com.key:${KOLAB_SSL_CERTIFICATE_KEY:?err} - - ./docker/kolab/utils:/root/utils:ro - - /sys/fs/cgroup:/sys/fs/cgroup:ro - - imap:/imapdata - - ldap: - build: - context: ./docker/ldap/ - container_name: kolab-ldap - restart: on-failure - tty: true - hostname: ldap - privileged: true - environment: - - APP_DOMAIN=${APP_DOMAIN} - - LDAP_ADMIN_ROOT_DN=${LDAP_ADMIN_ROOT_DN} - - LDAP_ADMIN_BIND_DN=${LDAP_ADMIN_BIND_DN} - - LDAP_ADMIN_BIND_PW=${LDAP_ADMIN_BIND_PW} - - LDAP_SERVICE_BIND_PW=${LDAP_SERVICE_BIND_PW} - - LDAP_HOSTED_BIND_PW=${LDAP_HOSTED_BIND_PW} - - IMAP_ADMIN_PASSWORD=${IMAP_ADMIN_PASSWORD} - healthcheck: - interval: 10s - test: "systemctl status dirsrv@kolab || exit 1" - timeout: 5s - retries: 30 - start_period: 5m - image: kolab-ldap - networks: - kolab: - ipv4_address: 172.18.0.12 - tmpfs: - - /run - - /tmp - - /var/run - - /var/tmp - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:ro - - ldap:/ldapdata roundcube: build: context: ./docker/roundcube/ container_name: kolab-roundcube hostname: roundcube.hosted.com restart: on-failure depends_on: mariadb: condition: service_healthy pdns: condition: service_healthy - kolab: - condition: service_healthy environment: - APP_DOMAIN=${APP_DOMAIN} - - LDAP_HOST=ldap - - LDAP_ADMIN_BIND_DN=${LDAP_ADMIN_BIND_DN} - - LDAP_ADMIN_BIND_PW=${LDAP_ADMIN_BIND_PW} - - LDAP_SERVICE_BIND_PW=${LDAP_SERVICE_BIND_PW} - - LDAP_HOSTED_BIND_PW=${LDAP_HOSTED_BIND_PW} - DB_HOST=mariadb - DB_ROOT_PASSWORD=${DB_ROOT_PASSWORD} - DB_RC_DATABASE=roundcube - DB_RC_USERNAME=roundcube - DB_RC_PASSWORD=${DB_PASSWORD:?"DB_PASSWORD is missing"} - - IMAP_HOST=tls://haproxy - - IMAP_PORT=145 - - IMAP_PROXY_PROTOCOL=2 + - IMAP_HOST=imap + - IMAP_PORT=11143 - IMAP_ADMIN_LOGIN=${IMAP_ADMIN_LOGIN} - IMAP_ADMIN_PASSWORD=${IMAP_ADMIN_PASSWORD} - - MAIL_HOST=tls://kolab + - MAIL_HOST=postfix - MAIL_PORT=10587 healthcheck: interval: 10s test: "kill -0 $$(cat /run/httpd/httpd.pid)" timeout: 5s retries: 30 # This makes docker's dns, resolve via pdns for this container. # Please note it does not affect /etc/resolv.conf dns: 172.18.0.11 image: roundcube networks: kolab: ipv4_address: 172.18.0.9 ports: - "8080:8080" tmpfs: - /tmp - /var/tmp volumes: - ./ext/:/src.orig/:ro mariadb: container_name: kolab-mariadb restart: on-failure environment: - MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD} - TZ="+02:00" - DB_HKCCP_DATABASE=${DB_DATABASE} - DB_HKCCP_USERNAME=${DB_USERNAME} - DB_HKCCP_PASSWORD=${DB_PASSWORD} healthcheck: interval: 10s test: test -e /var/run/mysqld/mysqld.sock timeout: 5s retries: 30 image: mariadb:10.9 networks: kolab: ipv4_address: 172.18.0.3 volumes: - ./docker/mariadb/mysql-init/:/docker-entrypoint-initdb.d/ - mariadb:/var/lib/mysql - haproxy: - build: - context: ./docker/haproxy/ - healthcheck: - interval: 10s - test: "kill -0 $$(cat /var/run/haproxy.pid)" - timeout: 5s - retries: 30 - container_name: kolab-haproxy - restart: on-failure - hostname: haproxy.hosted.com - image: kolab-haproxy - networks: - kolab: - ipv4_address: 172.18.0.6 - tmpfs: - - /run - - /tmp - - /var/run - - /var/tmp - volumes: - - ./docker/certs/:/etc/certs/:ro - - /etc/letsencrypt/:/etc/letsencrypt/:ro pdns: build: context: ./docker/pdns/ args: DB_HOST: mariadb DB_DATABASE: ${DB_DATABASE:?DB_DATABASE} DB_USERNAME: ${DB_USERNAME:?DB_USERNAME} DB_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD} container_name: kolab-pdns restart: on-failure tty: true hostname: pdns depends_on: mariadb: condition: service_healthy healthcheck: interval: 10s test: "systemctl status pdns || exit 1" timeout: 5s retries: 30 image: kolab-pdns networks: kolab: ipv4_address: 172.18.0.11 tmpfs: - /run - /tmp - /var/run - /var/tmp volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro redis: build: context: ./docker/redis/ healthcheck: interval: 10s test: "redis-cli ping || exit 1" timeout: 5s retries: 30 container_name: kolab-redis restart: on-failure hostname: redis image: redis networks: - kolab volumes: - ./docker/redis/redis.conf:/usr/local/etc/redis/redis.conf:ro webapp: build: context: ./docker/webapp/ args: GIT_REF: ${KOLAB_GIT_REF:-master} container_name: kolab-webapp restart: on-failure image: kolab-webapp healthcheck: interval: 10s test: "/src/kolabsrc/artisan octane:status || exit 1" timeout: 5s retries: 30 start_period: 5m depends_on: - kolab: - condition: service_healthy redis: condition: service_healthy - roundcube: - condition: service_healthy networks: kolab: ipv4_address: 172.18.0.4 volumes: - ./src:/src/kolabsrc.orig:ro ports: - "8000:8000" meet: build: context: ./docker/meet/ args: GIT_REF: ${KOLAB_GIT_REF:-master} container_name: kolab-meet restart: on-failure healthcheck: interval: 10s test: "curl --insecure -H 'X-AUTH-TOKEN: ${MEET_SERVER_TOKEN}' --fail https://${MEET_LISTENING_HOST}:12443/meetmedia/api/health || exit 1" timeout: 5s retries: 30 start_period: 5m environment: - WEBRTC_LISTEN_IP=${MEET_WEBRTC_LISTEN_IP:?err} - PUBLIC_DOMAIN=${MEET_PUBLIC_DOMAIN:?err} - LISTENING_HOST=${MEET_LISTENING_HOST:?err} - LISTENING_PORT=12443 - TURN_SERVER=${MEET_TURN_SERVER} - TURN_STATIC_SECRET=${COTURN_STATIC_SECRET} - AUTH_TOKEN=${MEET_SERVER_TOKEN:?err} - WEBHOOK_TOKEN=${MEET_WEBHOOK_TOKEN:?err} - WEBHOOK_URL=${APP_PUBLIC_URL:?err}/api/webhooks/meet - SSL_CERT=/etc/pki/tls/certs/meet.${APP_WEBSITE_DOMAIN:?err}.cert - SSL_KEY=/etc/pki/tls/private/meet.${APP_WEBSITE_DOMAIN:?err}.key network_mode: host container_name: kolab-meet image: kolab-meet volumes: - ./meet/server:/src/meet/:ro - ./docker/certs/meet.${APP_WEBSITE_DOMAIN}.cert:/etc/pki/tls/certs/meet.${APP_WEBSITE_DOMAIN}.cert - ./docker/certs/meet.${APP_WEBSITE_DOMAIN}.key:/etc/pki/tls/private/meet.${APP_WEBSITE_DOMAIN}.key minio: container_name: kolab-minio restart: on-failure healthcheck: interval: 10s test: "curl -f http://127.0.0.1:9000/minio/health/live || exit 1" timeout: 5s retries: 30 start_period: 5m environment: - MINIO_ROOT_USER=${MINIO_USER} - MINIO_ROOT_PASSWORD=${MINIO_PASSWORD} image: minio/minio networks: kolab: ipv4_address: 172.18.0.14 ports: - "9000:9000" - "9001:9001" entrypoint: sh command: -c 'mkdir -p /data/${MINIO_BUCKET} && minio server /data --console-address ":9001"' volumes: - minio:/data networks: kolab: driver: bridge ipam: config: - subnet: "172.18.0.0/24" volumes: mariadb: - imap: - ldap: minio: diff --git a/docker/roundcube/rootfs/etc/roundcubemail/config.inc.php b/docker/roundcube/rootfs/etc/roundcubemail/config.inc.php index fe1a9271..d91a094d 100644 --- a/docker/roundcube/rootfs/etc/roundcubemail/config.inc.php +++ b/docker/roundcube/rootfs/etc/roundcubemail/config.inc.php @@ -1,261 +1,263 @@ = 5.6 - $config['imap_conn_options'] = [ - 'ssl' => [ - 'verify_peer_name' => false, - 'verify_peer' => false, - 'allow_self_signed' => true - ], - 'proxy_protocol' => getenv('IMAP_PROXY_PROTOCOL') - ]; - $config['proxy_whitelist'] = ['127.0.0.1', '172.18.0.7']; + // if (str_contains(getenv('IMAP_URI'), 'tls') || str_contains(getenv('IMAP_URI'), 'ssl')) { + // $config['imap_conn_options'] = [ + // 'ssl' => [ + // 'verify_peer_name' => false, + // 'verify_peer' => false, + // 'allow_self_signed' => true + // ], + // 'proxy_protocol' => getenv('IMAP_PROXY_PROTOCOL') + // ]; + // } + $config['proxy_whitelist'] = getenvlist('PROXY_WHITELIST'); // Caching and storage settings $config['imap_cache'] = 'db'; $config['imap_cache_ttl'] = '10d'; $config['messages_cache'] = 'db'; $config['message_cache_ttl'] = '10d'; $config['session_storage'] = 'db'; // SMTP Server Settings $config['smtp_server'] = getenv('MAIL_HOST'); $config['smtp_port'] = getenv('MAIL_PORT'); $config['smtp_user'] = '%u'; $config['smtp_pass'] = '%p'; $config['smtp_helo_host'] = $_SERVER["HTTP_HOST"] ?? null; - - // SMTP Connection TLS settings, adjust for Production - // Required for PHP >= 5.6 - $config['smtp_conn_options'] = Array( - 'ssl' => Array( - 'verify_peer_name' => false, - 'verify_peer' => false, - 'allow_self_signed' => true - ) - ); + // $config['smtp_conn_options'] = Array( + // 'ssl' => Array( + // 'verify_peer_name' => false, + // 'verify_peer' => false, + // 'allow_self_signed' => true + // ) + // ); // LDAP Settings $config['ldap_cache'] = 'db'; $config['ldap_cache_ttl'] = '1h'; // Kolab specific defaults $config['product_name'] = 'Kolab Groupware'; $config['quota_zero_as_unlimited'] = false; $config['login_lc'] = 2; $config['auto_create_user'] = true; $config['enable_installer'] = false; // The SMTP server does not allow empty identities $config['mdn_use_from'] = true; // Plugins $config['plugins'] = array( // 'kolab_auth', 'acl', 'archive', 'calendar', 'jqueryui', 'kolab_activesync', 'kolab_addressbook', 'kolab_config', //'kolab_delegation', 'kolab_files', 'kolab_folders', 'kolab_notes', 'kolab_tags', 'managesieve', 'newmail_notifier', 'odfviewer', 'password', 'redundant_attachments', 'tasklist', // contextmenu must be after kolab_addressbook (#444) 'contextmenu', 'enigma', ); // Do not show deleted messages, mark deleted messages as read, // and flag them as deleted instead of moving them to the Trash // folder. $config['skip_deleted'] = true; $config['read_when_deleted'] = true; $config['flag_for_deletion'] = true; $config['delete_always'] = true; $config['session_lifetime'] = 180; $config['password_charset'] = 'UTF-8'; $config['useragent'] = 'Kolab 16/Roundcube ' . RCUBE_VERSION; $config['message_sort_col'] = 'date'; $config['spellcheck_engine'] = 'pspell'; $config['spellcheck_dictionary'] = true; $config['spellcheck_ignore_caps'] = true; $config['spellcheck_ignore_nums'] = true; $config['spellcheck_ignore_syms'] = true; $config['spellcheck_languages'] = array( 'da' => 'Dansk', 'de' => 'Deutsch', 'en' => 'English', 'es' => 'Español', 'fr' => 'Français', 'it' => 'Italiano', 'nl' => 'Nederlands', 'pt' => 'Português', 'ru' => 'Русский', 'sv' => 'Svenska' ); $config['undo_timeout'] = 10; $config['upload_progress'] = 2; $config['address_template'] = '{street}
{locality} {zipcode}
{country} {region}'; $config['preview_pane'] = true; $config['preview_pane_mark_read'] = 0; $config['autoexpand_threads'] = 2; $config['top_posting'] = 0; $config['sig_above'] = false; $config['mdn_requests'] = 0; $config['mdn_default'] = false; $config['dsn_default'] = false; $config['reply_same_folder'] = false; if (file_exists(RCUBE_CONFIG_DIR . '/' . ($_SERVER["HTTP_HOST"] ?? null) . '/' . basename(__FILE__))) { include_once(RCUBE_CONFIG_DIR . '/' . ($_SERVER["HTTP_HOST"] ?? null) . '/' . basename(__FILE__)); } // Re-apply mandatory settings here. $config['debug_level'] = 1; $config['devel_mode'] = false; $config['log_driver'] = 'stdout'; $config['per_user_logging'] = true; $config['log_date_format'] = 'd-M-Y H:i:s,u O'; $config['syslog_id'] = 'roundcube'; $config['syslog_facility'] = LOG_USER; $config['smtp_log'] = false; $config['log_logins'] = true; $config['log_session'] = false; $config['sql_debug'] = false; $config['memcache_debug'] = false; $config['imap_debug'] = true; $config['ldap_debug'] = false; $config['smtp_debug'] = false; $config['skin'] = 'kolab'; $config['skin_include_php'] = false; $config['mime_magic'] = null; $config['im_identify_path'] = '/usr/bin/identify'; $config['im_convert_path'] = '/usr/bin/convert'; $config['log_dir'] = 'logs/'; #$config['temp_dir'] = '/var/lib/roundcubemail/'; // Some additional default folders (archive plugin) $config['archive_mbox'] = 'Archive'; // The Kolab daemon by default creates 'Spam' $config['junk_mbox'] = 'Spam'; $config['default_folders'] = array('INBOX', 'Drafts', 'Sent', 'Spam', 'Trash', 'Archive'); $config['address_book_type'] = 'ldap'; $config['autocomplete_min_length'] = 3; $config['autocomplete_threads'] = 0; $config['autocomplete_max'] = 15; $config['ldap_public'] = array( 'kolab_addressbook' => array( 'name' => 'Global Address Book', 'hosts' => Array(getenv('LDAP_HOST')), 'port' => 389, 'use_tls' => false, 'base_dn' => 'dc=hosted,dc=com', 'user_specific' => true, 'bind_dn' => '%dn', 'bind_pass' => '', 'search_base_dn' => 'dc=hosted,dc=com', 'search_bind_dn' => 'uid=kolab-service,ou=Special Users,dc=mgmt,dc=com', 'search_bind_pw' => getenv('LDAP_SERVICE_BIND_PW'), 'search_filter' => '(&(objectClass=inetorgperson)(mail=%fu))', 'writable' => false, 'LDAP_Object_Classes' => array("top", "inetorgperson"), 'required_fields' => array("cn", "sn", "mail"), 'LDAP_rdn' => 'uid', 'ldap_version' => 3, // using LDAPv3 'search_fields' => array('displayname', 'mail'), 'sort' => array('displayname', 'sn', 'givenname', 'cn'), 'scope' => 'sub', 'filter' => '(objectClass=inetorgperson)', 'vlv' => true, 'vlv_search' => true, 'fuzzy_search' => true, 'sizelimit' => '0', 'timelimit' => '0', 'fieldmap' => Array( // Roundcube => LDAP 'name' => 'displayName', 'surname' => 'sn', 'firstname' => 'givenName', 'middlename' => 'initials', 'email:primary' => 'mail', 'email:alias' => 'alias', 'email:personal' => 'mailalternateaddress', 'phone:main' => 'telephoneNumber', 'phone:work' => 'alternateTelephoneNumber', 'phone:mobile' => 'mobile', 'phone:work2' => 'blackberry', 'jobtitle' => 'title', 'manager' => 'manager', 'assistant' => 'secretary', 'photo' => 'jpegphoto' ), 'groups' => Array( 'base_dn' => 'dc=hosted,dc=com', 'filter' => '(&' . '(|(objectclass=groupofuniquenames)(objectclass=groupofurls))' . '(mail=*))', 'object_classes' => Array("top", "groupOfUniqueNames"), 'member_attr' => 'uniqueMember', ), ), ); $config['autocomplete_addressbooks'] = Array( 'kolab_addressbook' ); $config['autocomplete_single'] = true; $config['htmleditor'] = 0; $config['kolab_http_request'] = Array( 'ssl_verify_host' => false, 'ssl_verify_peer' => false, ); @include('kolab_syncroton.inc.php'); ?> diff --git a/docker/roundcube/rootfs/opt/app-root/src/init.sh b/docker/roundcube/rootfs/opt/app-root/src/init.sh index 46890c2f..daa34fc2 100755 --- a/docker/roundcube/rootfs/opt/app-root/src/init.sh +++ b/docker/roundcube/rootfs/opt/app-root/src/init.sh @@ -1,71 +1,75 @@ #!/bin/bash + +echo "Starting" set -e set -x +echo "push" pushd /opt/app-root/src/ +echo "..." # FIXME doesn't work in rootless # sed -i -r -e "s|service_bind_pw = .*$|service_bind_pw = $LDAP_SERVICE_BIND_PW|g" /etc/kolab/kolab.conf pushd roundcubemail ## Copy our configs over the default ones cp /etc/roundcubemail/* config/ DES_KEY=$(openssl rand -base64 24); sed -i -r -e "s|\$config\['des_key'\] = .*$|\$config['des_key'] = \"$DES_KEY\";|g" config/config.inc.php # Initialize the db cat > /tmp/kolab-setup-my.cnf << EOF [client] host=${DB_HOST} user=root password=${DB_ROOT_PASSWORD} EOF mysql --defaults-file=/tmp/kolab-setup-my.cnf </dev/null 2>&1 || : done fi done popd roundcubemail/bin/initdb.sh --dir syncroton/docs/SQL/ || : roundcubemail/bin/initdb.sh --dir chwala/doc/SQL/ || : echo "Updating tables..." roundcubemail/bin/updatedb.sh --dir syncroton/docs/SQL/ --package syncroton || : roundcubemail/bin/updatedb.sh --dir roundcubemail/SQL/ --package roundcube || : roundcubemail/bin/updatedb.sh --dir roundcubemail/plugins/libkolab/SQL/ --package libkolab || : roundcubemail/bin/updatedb.sh --dir roundcubemail/plugins/kolab-calendar/SQL/ --package calendar-kolab || : echo "" echo "Done, starting httpd..." /usr/sbin/php-fpm exec httpd -DFOREGROUND