diff --git a/docker-compose.yml b/docker-compose.yml index 72498163..a540aa50 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,371 +1,372 @@ 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_ADMIN_LOGIN=${IMAP_ADMIN_LOGIN} - IMAP_ADMIN_PASSWORD=${IMAP_ADMIN_PASSWORD} - MAIL_HOST=tls://kolab - 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 00116be4..ea93674f 100644 --- a/docker/roundcube/rootfs/etc/roundcubemail/config.inc.php +++ b/docker/roundcube/rootfs/etc/roundcubemail/config.inc.php @@ -1,255 +1,255 @@ = 5.6 $config['imap_conn_options'] = [ 'ssl' => [ 'verify_peer_name' => false, 'verify_peer' => false, 'allow_self_signed' => true ], - 'proxy_protocol' => 2 + 'proxy_protocol' => getenv('IMAP_PROXY_PROTOCOL') ]; $config['proxy_whitelist'] = ['127.0.0.1', '172.18.0.7']; // 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 ) ); // 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'] = 'file'; $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'] = false; $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'); ?>