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');
?>