diff --git a/docker-compose.yml b/docker-compose.yml index 552aaea5..4f3c55c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,203 +1,168 @@ version: '3' services: coturn: build: context: ./docker/coturn/ container_name: kolab-coturn environment: - - DB_NAME=${OPENVIDU_COTURN_REDIS_DATABASE} - - DB_PASSWORD=${OPENVIDU_COTURN_REDIS_PASSWORD} - - REDIS_IP=${OPENVIDU_COTURN_REDIS_IP} - - TURN_PUBLIC_IP=${OPENVIDU_COTURN_IP} + - REDIS_DBNAME=${COTURN_REDIS_DATABASE} + - REDIS_PASSWORD=${COTURN_REDIS_PASSWORD} + - REDIS_IP=${COTURN_REDIS_IP} + - TURN_PUBLIC_IP=${COTURN_PUBLIC_IP} - TURN_LISTEN_PORT=3478 hostname: sturn.mgmt.com image: kolab-coturn network_mode: host restart: on-failure tty: true kolab: build: context: ./docker/kolab/ container_name: kolab depends_on: - mariadb extra_hosts: - "kolab.mgmt.com:127.0.0.1" environment: - DB_HOST=${DB_HOST} - DB_ROOT_PASSWORD=Welcome2KolabSystems healthcheck: interval: 10s test: test -f /tmp/kolab-init.done timeout: 5s retries: 30 hostname: kolab.mgmt.com image: kolab network_mode: host tmpfs: - /run - /tmp - /var/run - /var/tmp tty: true volumes: - /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:/etc/pki/tls/certs/kolab.hosted.com.cert - ./docker/certs/kolab.hosted.com.key:/etc/pki/tls/certs/kolab.hosted.com.key - ./docker/certs/kolab.mgmt.com.cert:/etc/pki/tls/certs/kolab.mgmt.com.cert - ./docker/certs/kolab.mgmt.com.key:/etc/pki/tls/certs/kolab.mgmt.com.key - ./docker/kolab/utils:/root/utils:ro - ./src/.env:/.dockerenv:ro - /sys/fs/cgroup:/sys/fs/cgroup:ro - # kurento-media-server: - # build: - # context: ./docker/kurento-media-server/ - # container_name: kolab-kurento-media-server - # environment: - # - GST_DEBUG=3,Kurento*:4,kms*:4,sdp*:4,webrtc*:4,*rtpendpoint:4,rtp*handler:4,rtpsynchronizer:4,agnosticbin:4 - # hostname: kurento-media-server.hosted.com - # image: apheleia/kurento-media-server:6.15.0 - # network_mode: host mariadb: container_name: kolab-mariadb environment: MYSQL_ROOT_PASSWORD: Welcome2KolabSystems TZ: "+02:00" healthcheck: interval: 10s test: test -e /var/run/mysqld/mysqld.sock timeout: 5s retries: 30 image: mariadb network_mode: host nginx: build: context: ./docker/nginx/ args: APP_WEBSITE_DOMAIN: ${APP_WEBSITE_DOMAIN:?err} container_name: kolab-nginx hostname: nginx.hosted.com image: kolab-nginx network_mode: host tmpfs: - /run - /tmp - /var/run - /var/tmp tty: true volumes: - ./docker/certs/imap.hosted.com.cert:/etc/pki/tls/certs/imap.hosted.com.cert - ./docker/certs/imap.hosted.com.key:/etc/pki/tls/private/imap.hosted.com.key - # openvidu: - # build: - # context: ./docker/openvidu/ - # container_name: kolab-openvidu - # depends_on: - # - kurento-media-server - # environment: - # - APP_DOMAIN=${APP_DOMAIN} - # - CERTIFICATE_TYPE=letsencrypt - # - COTURN_IP=${OPENVIDU_COTURN_IP} - # - COTURN_REDIS_DBNAME=${OPENVIDU_COTURN_REDIS_DATABASE} - # - COTURN_REDIS_PASSWORD=${OPENVIDU_COTURN_REDIS_PASSWORD} - # - COTURN_REDIS_IP=${OPENVIDU_COTURN_REDIS_IP} - # - DOMAIN_OR_PUBLIC_IP=${OPENVIDU_PUBLIC_IP} - # - SERVER_PORT=${OPENVIDU_SERVER_PORT} - # - KMS_STUN_IP=${OPENVIDU_COTURN_IP} - # - KMS_STUN_PORT=3478 - # - KMS_URIS=["ws://localhost:8888/kurento", "ws://localhost:8889/kurento"] - # - OPENVIDU_SECRET=${OPENVIDU_API_PASSWORD} - # - OPENVIDU_WEBHOOK=${OPENVIDU_WEBHOOK} - # - OPENVIDU_WEBHOOK_ENDPOINT=${OPENVIDU_WEBHOOK_ENDPOINT} - # - SERVER_SSL_ENABLED=false - # hostname: openvidu.hosted.com - # image: apheleia/openvidu:2.18.0 - # network_mode: host - # tmpfs: - # - /run - # - /tmp - # - /var/run - # - /var/tmp - # tty: true - # volumes: - # - /etc/letsencrypt/:/etc/letsencrypt/:ro pdns-sql: build: context: ./docker/pdns-sql/ container_name: kolab-pdns-sql depends_on: - mariadb hostname: pdns-sql image: apheleia/kolab-pdns-sql network_mode: host tmpfs: - /run - /tmp - /var/run - /var/tmp tty: true volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro proxy: build: context: ./docker/proxy/ container_name: kolab-proxy hostname: kanarip.internet-box.ch image: kolab-proxy network_mode: host tmpfs: - /run - /tmp - /var/run - /var/tmp tty: true volumes: - ./docker/certs/:/etc/certs/:ro - /etc/letsencrypt/:/etc/letsencrypt/:ro - /sys/fs/cgroup:/sys/fs/cgroup:ro redis: build: context: ./docker/redis/ container_name: kolab-redis hostname: redis image: redis network_mode: host volumes: - ./docker/redis/redis.conf:/usr/local/etc/redis/redis.conf:ro swoole: build: context: ./docker/swoole/ container_name: kolab-swoole image: apheleia/swoole:4.6.x worker: build: context: ./docker/worker/ container_name: kolab-worker depends_on: - kolab hostname: worker image: kolab-worker network_mode: host tmpfs: - /run - /tmp - /var/run - /var/tmp tty: true volumes: - ./src:/home/worker/src.orig:ro - /sys/fs/cgroup:/sys/fs/cgroup:ro meet: build: context: ./docker/meet/ + environment: + - REDIS_IP=${MEET_REDIS_IP} + - REDIS_PORT=${MEET_REDIS_PORT} + - REDIS_DBNAME=${MEET_REDIS_DATABASE} + - REDIS_PASSWORD=${MEET_REDIS_PASSWORD} + - PUBLIC_IP=${MEET_PUBLIC_IP} + - TURN_SERVER=${MEET_TURN_SERVER} network_mode: host container_name: kolab-meet image: kolab-meet volumes: - /etc/letsencrypt/:/etc/letsencrypt/:ro - ./meet/server:/src/meet/:ro - ./docker/meet/build/node_modules:/root/node_modules - ./docker/certs/kolab.hosted.com.cert:/etc/pki/tls/certs/kolab.hosted.com.cert - ./docker/certs/kolab.hosted.com.key:/etc/pki/tls/certs/kolab.hosted.com.key diff --git a/docker/coturn/rootfs/usr/local/bin/coturn.sh b/docker/coturn/rootfs/usr/local/bin/coturn.sh index 2878f1b4..8af7612f 100755 --- a/docker/coturn/rootfs/usr/local/bin/coturn.sh +++ b/docker/coturn/rootfs/usr/local/bin/coturn.sh @@ -1,28 +1,28 @@ #!/bin/bash cd /tmp/ cat > ./turnserver.conf << EOF external-ip=${TURN_PUBLIC_IP:-127.0.0.1} listening-port=${TURN_LISTEN_PORT:-3478} fingerprint lt-cred-mech # Temporary for testing user=username1:password1 allow-loopback-peers cli-password=qwerty # Disabled by default to avoid DoS attacks. Logs all bind attempts in verbose log mode (useful for debugging) log-binding max-port=${MAX_PORT:-65535} min-port=${MIN_PORT:-40000} pidfile="$(pwd)/turnserver.pid" realm=kolabmeet log-file=stdout -redis-userdb="ip=${REDIS_IP:-127.0.0.1} dbname=${DB_NAME:-2} password=${DB_PASSWORD:-turn} connect_timeout=30" +redis-userdb="ip=${REDIS_IP:-127.0.0.1} dbname=${REDIS_DBNAME:-2} password=${REDIS_PASSWORD:-turn} connect_timeout=30" verbose EOF /usr/bin/turnserver -c ./turnserver.conf diff --git a/meet/server/config/config.js b/meet/server/config/config.js index 430cce63..a1f948b9 100644 --- a/meet/server/config/config.js +++ b/meet/server/config/config.js @@ -1,246 +1,247 @@ const os = require('os'); const userRoles = require('../userRoles'); const { BYPASS_ROOM_LOCK, BYPASS_LOBBY } = require('../access'); const { CHANGE_ROOM_LOCK, PROMOTE_PEER, MODIFY_ROLE, SEND_CHAT, MODERATE_CHAT, SHARE_AUDIO, SHARE_VIDEO, SHARE_SCREEN, EXTRA_VIDEO, SHARE_FILE, MODERATE_FILES, MODERATE_ROOM } = require('../permissions'); module.exports = { // URI and key for requesting geoip-based TURN server closest to the client // turnAPIKey : 'examplekey', // turnAPIURI : 'https://example.com/api/turn', // turnAPIparams : { // 'uri_schema' : 'turn', // 'transport' : 'tcp', // 'ip_ver' : 'ipv4', // 'servercount' : '2' // }, // turnAPITimeout : 2 * 1000, // Backup turnservers if REST fails or is not configured backupTurnServers : [ { urls : [ - 'turn:127.0.0.1:3478?transport=tcp', + process.env.TURN_SERVER || 'turn:127.0.0.1:3478?transport=tcp' ], + //FIXME we use hardcoded credentials for now username : 'username1', credential : 'password1' } ], // redis server options used for session storage redisOptions : { - host: '127.0.0.1', //REDIS_IP - port: '6379', //REDIS_PORT - db: '3' + host: process.env.REDIS_IP || '127.0.0.1', + port: process.env.REDIS_PORT || 6379, + db: process.env.REDIS_DB || '3', + password: process.env.REDIS_PASSWORD }, // session cookie secret cookieSecret : 'T0P-S3cR3t_cook!e', cookieName : 'edumeet.sid', // if you use encrypted private key the set the passphrase tls : { //cert : `${__dirname}/../certs/mediasoup-demo.localhost.cert.pem`, // passphrase: 'key_password' //key : `${__dirname}/../certs/mediasoup-demo.localhost.key.pem` cert : `/etc/pki/tls/certs/kolab.hosted.com.cert`, key : `/etc/pki/tls/certs/kolab.hosted.com.key`, }, // listening Host or IP // If omitted listens on every IP. ("0.0.0.0" and "::") //listeningHost: 'localhost', // Listening port for https server. listeningPort : 12443, // Any http request is redirected to https. // Listening port for http server. listeningRedirectPort : 12080, // Listens only on http, only on listeningPort // listeningRedirectPort disabled // use case: loadbalancer backend httpOnly : true, // WebServer/Express trust proxy config for httpOnly mode // You can find more info: // - https://expressjs.com/en/guide/behind-proxies.html // - https://www.npmjs.com/package/proxy-addr // use case: loadbalancer backend trustProxy : '', accessFromRoles : { // The role(s) will gain access to the room // even if it is locked (!) [BYPASS_ROOM_LOCK] : [ userRoles.ADMIN ], // The role(s) will gain access to the room without // going into the lobby. If you want to restrict access to your // server to only directly allow authenticated users, you could // add the userRoles.AUTHENTICATED to the user in the userMapping // function, and change to BYPASS_LOBBY : [ userRoles.AUTHENTICATED ] [BYPASS_LOBBY] : [ userRoles.NORMAL ] }, permissionsFromRoles : { // The role(s) have permission to lock/unlock a room [CHANGE_ROOM_LOCK] : [ userRoles.MODERATOR ], // The role(s) have permission to promote a peer from the lobby [PROMOTE_PEER] : [ userRoles.NORMAL ], // The role(s) have permission to give/remove other peers roles [MODIFY_ROLE] : [ userRoles.NORMAL ], // The role(s) have permission to send chat messages [SEND_CHAT] : [ userRoles.NORMAL ], // The role(s) have permission to moderate chat [MODERATE_CHAT] : [ userRoles.MODERATOR ], // The role(s) have permission to share audio [SHARE_AUDIO] : [ userRoles.NORMAL ], // The role(s) have permission to share video [SHARE_VIDEO] : [ userRoles.NORMAL ], // The role(s) have permission to share screen [SHARE_SCREEN] : [ userRoles.NORMAL ], // The role(s) have permission to produce extra video [EXTRA_VIDEO] : [ userRoles.NORMAL ], // The role(s) have permission to share files [SHARE_FILE] : [ userRoles.NORMAL ], // The role(s) have permission to moderate files [MODERATE_FILES] : [ userRoles.MODERATOR ], // The role(s) have permission to moderate room (e.g. kick user) [MODERATE_ROOM] : [ userRoles.MODERATOR ] }, // Array of permissions. If no peer with the permission in question // is in the room, all peers are permitted to do the action. The peers // that are allowed because of this rule will not be able to do this // action as soon as a peer with the permission joins. In this example // everyone will be able to lock/unlock room until a MODERATOR joins. allowWhenRoleMissing : [ CHANGE_ROOM_LOCK ], // When truthy, the room will be open to all users when as long as there // are allready users in the room activateOnHostJoin : true, // When set, maxUsersPerRoom defines how many users can join // a single room. If not set, there is no limit. // maxUsersPerRoom : 20, // Room size before spreading to new router routerScaleSize : 40, // Socket timout value requestTimeout : 20000, // Socket retries when timeout requestRetries : 3, // Mediasoup settings mediasoup : { numWorkers : Object.keys(os.cpus()).length, // mediasoup Worker settings. worker : { logLevel : 'warn', logTags : [ 'info', 'ice', 'dtls', 'rtp', 'srtp', 'rtcp' ], rtcMinPort : 40000, rtcMaxPort : 49999 }, // mediasoup Router settings. router : { // Router media codecs. mediaCodecs : [ { kind : 'audio', mimeType : 'audio/opus', clockRate : 48000, channels : 2 }, { kind : 'video', mimeType : 'video/VP8', clockRate : 90000, parameters : { 'x-google-start-bitrate' : 1000 } }, { kind : 'video', mimeType : 'video/VP9', clockRate : 90000, parameters : { 'profile-id' : 2, 'x-google-start-bitrate' : 1000 } }, { kind : 'video', mimeType : 'video/h264', clockRate : 90000, parameters : { 'packetization-mode' : 1, 'profile-level-id' : '4d0032', 'level-asymmetry-allowed' : 1, 'x-google-start-bitrate' : 1000 } }, { kind : 'video', mimeType : 'video/h264', clockRate : 90000, parameters : { 'packetization-mode' : 1, 'profile-level-id' : '42e01f', 'level-asymmetry-allowed' : 1, 'x-google-start-bitrate' : 1000 } } ] }, // mediasoup WebRtcTransport settings. webRtcTransport : { listenIps : [ - // change 192.0.2.1 IPv4 to your server's IPv4 address!! - { ip: '192.168.1.81', announcedIp: null } + { ip: process.env.PUBLIC_IP || '127.0.0.1', announcedIp: null } // Can have multiple listening interfaces // change 2001:DB8::1 IPv6 to your server's IPv6 address!! // { ip: '2001:DB8::1', announcedIp: null } ], initialAvailableOutgoingBitrate : 1000000, minimumAvailableOutgoingBitrate : 600000, // Additional options that are not part of WebRtcTransportOptions. maxIncomingBitrate : 1500000 } } /* , // Prometheus exporter prometheus : { deidentify : false, // deidentify IP addresses // listen : 'localhost', // exporter listens on this address numeric : false, // show numeric IP addresses port : 8889, // allocated port quiet : false // include fewer labels } */ }; diff --git a/src/.env.example b/src/.env.example index 6ddebff4..ec041c81 100644 --- a/src/.env.example +++ b/src/.env.example @@ -1,167 +1,165 @@ APP_NAME=Kolab APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=http://127.0.0.1:8000 #APP_PASSPHRASE= APP_PUBLIC_URL= APP_DOMAIN=kolabnow.com APP_WEBSITE_DOMAIN=kolabnow.com APP_THEME=default APP_TENANT_ID=5 APP_LOCALE=en APP_LOCALES= APP_WITH_ADMIN=1 APP_WITH_RESELLER=1 APP_WITH_SERVICES=1 ASSET_URL=http://127.0.0.1:8000 WEBMAIL_URL=/apps SUPPORT_URL=/support SUPPORT_EMAIL= LOG_CHANNEL=stack LOG_SLOW_REQUESTS=5 DB_CONNECTION=mysql DB_DATABASE=kolabdev DB_HOST=127.0.0.1 DB_PASSWORD=kolab 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:Welcome2KolabSystems@127.0.0.1/roundcube MFA_TOTP_DIGITS=6 MFA_TOTP_INTERVAL=30 MFA_TOTP_DIGEST=sha1 IMAP_URI=ssl://127.0.0.1:11993 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=127.0.0.1 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" -OPENVIDU_API_PASSWORD=MY_SECRET -OPENVIDU_API_URL=http://localhost:12443/api/ -OPENVIDU_API_USERNAME=OPENVIDUAPP -OPENVIDU_API_VERIFY_TLS=true -OPENVIDU_COTURN_IP=127.0.0.1 -OPENVIDU_COTURN_REDIS_DATABASE=2 -OPENVIDU_COTURN_REDIS_IP=127.0.0.1 -OPENVIDU_COTURN_REDIS_PASSWORD=turn -# Used as COTURN_IP, TURN_PUBLIC_IP, for KMS_TURN_URL -OPENVIDU_PUBLIC_IP=127.0.0.1 -OPENVIDU_PUBLIC_PORT=3478 -OPENVIDU_SERVER_PORT=8080 -OPENVIDU_WEBHOOK=true -OPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:8000/webhooks/meet/openvidu +COTURN_REDIS_IP=127.0.0.1 +COTURN_REDIS_PORT=6379 +COTURN_REDIS_DATABASE=3 +COTURN_REDIS_PASSWORD=0 +COTURN_PUBLIC_IP=127.0.0.1 + +MEET_REDIS_IP=127.0.0.1 +MEET_REDIS_PORT=6379 +MEET_REDIS_DATABASE=3 +MEET_REDIS_PASSWORD=0 +MEET_PUBLIC_IP=127.0.0.1 +MEET_TURN_SERVER='turn:127.0.0.1:3478?transport=tcp' # "CDR" events, see https://docs.openvidu.io/en/2.13.0/reference-docs/openvidu-server-cdr/ #OPENVIDU_WEBHOOK_EVENTS=[sessionCreated,sessionDestroyed,participantJoined,participantLeft,webrtcConnectionCreated,webrtcConnectionDestroyed,recordingStatusChanged,filterEventDispatched,mediaNodeStatusChanged] #OPENVIDU_WEBHOOK_HEADERS=[\"Authorization:\ Basic\ SOMETHING\"] PGP_ENABLED= PGP_BINARY= PGP_AGENT= PGP_GPGCONF= PGP_LENGTH= REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 SWOOLE_HOT_RELOAD_ENABLE=true SWOOLE_HTTP_ACCESS_LOG=true SWOOLE_HTTP_HOST=127.0.0.1 SWOOLE_HTTP_PORT=8000 SWOOLE_HTTP_REACTOR_NUM=1 SWOOLE_HTTP_WEBSOCKET=true SWOOLE_HTTP_WORKER_NUM=1 SWOOLE_OB_OUTPUT=true PAYMENT_PROVIDER= MOLLIE_KEY= STRIPE_KEY= STRIPE_PUBLIC_KEY= STRIPE_WEBHOOK_SECRET= MAIL_DRIVER=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 AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= 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}" # Generate with ./artisan passport:client --password #PASSPORT_PROXY_OAUTH_CLIENT_ID= #PASSPORT_PROXY_OAUTH_CLIENT_SECRET= PASSPORT_PRIVATE_KEY= PASSPORT_PUBLIC_KEY= COMPANY_NAME= COMPANY_ADDRESS= COMPANY_DETAILS= COMPANY_EMAIL= COMPANY_LOGO= COMPANY_FOOTER= VAT_COUNTRIES=CH,LI VAT_RATE=7.7 KB_ACCOUNT_DELETE= KB_ACCOUNT_SUSPENDED=