diff --git a/ci/env b/ci/env index 6e37996f..def08b6c 100644 --- a/ci/env +++ b/ci/env @@ -1,181 +1,177 @@ APP_NAME=Kolab APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=https://kolab.local APP_PUBLIC_URL=https://kolab.local APP_DOMAIN=kolab.local APP_WEBSITE_DOMAIN=kolab.local 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=1 APP_WITH_SIGNUP=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://kolab.local 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=127.0.0.1 DB_PASSWORD=simple123 DB_ROOT_PASSWORD=simple123 DB_PORT=3306 DB_USERNAME=kolabdev BROADCAST_DRIVER=redis CACHE_DRIVER=redis QUEUE_CONNECTION=redis SESSION_DRIVER=file SESSION_LIFETIME=120 MFA_DSN=mysql://roundcube:simple123@127.0.0.1/roundcube MFA_TOTP_DIGITS=6 MFA_TOTP_INTERVAL=30 MFA_TOTP_DIGEST=sha1 IMAP_URI=localhost:11143 IMAP_HOST=localhost IMAP_PORT=11143 IMAP_GUAM_PORT=11143 IMAP_ADMIN_LOGIN=cyrus-admin IMAP_ADMIN_PASSWORD=simple123 IMAP_VERIFY_HOST=false IMAP_VERIFY_PEER=false IMAP_WITH_GROUPWARE_DEFAULT_FOLDERS=false SMTP_HOST=localhost SMTP_PORT=10587 -COTURN_PUBLIC_IP='172.18.0.1' - -MEET_SERVER_URLS=https://kolab.local/meetmedia/api/ +MEET_SERVER_URLS=https://127.0.0.1:6443/meetmedia/api/ MEET_SERVER_VERIFY_TLS=false -MEET_WEBRTC_LISTEN_IP='172.18.0.1' +MEET_WEBRTC_LISTEN_IP='127.0.0.1' MEET_PUBLIC_DOMAIN=kolab.local -MEET_TURN_SERVER='turn:172.18.0.1:3478' -MEET_LISTENING_HOST=172.18.0.1 +MEET_LISTENING_HOST=127.0.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=localhost REDIS_PASSWORD=null REDIS_PORT=6379 OCTANE_HTTP_HOST=kolab.local SWOOLE_PACKAGE_MAX_LENGTH=10485760 MAIL_MAILER=smtp MAIL_HOST=localhost MAIL_PORT=587 MAIL_USERNAME="noreply@kolab.local" MAIL_PASSWORD="simple123" MAIL_ENCRYPTION=starttls MAIL_FROM_ADDRESS="noreply@kolab.local" MAIL_FROM_NAME="kolab.local" MAIL_REPLYTO_ADDRESS="noreply@kolab.local" MAIL_REPLYTO_NAME=null MAIL_VERIFY_PEER='false' RATELIMIT_WHITELIST="noreply@kolab.local" 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/certs/kolab.hosted.com.cert KOLAB_SSL_CERTIFICATE_FULLCHAIN=/etc/certs/kolab.hosted.com.chain.pem KOLAB_SSL_CERTIFICATE_KEY=/etc/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= FIREBASE_API_KEY= MINIO_ENDPOINT=http://localhost:9000 MINIO_USER=minio MINIO_PASSWORD=simple123 MINIO_BUCKET=kolab FILESYSTEM_DISK=minio TRUSTED_PROXIES="172.18.0.7/8,127.0.0.1/8" MOLLIE_KEY= STRIPE_KEY= STRIPE_PUBLIC_KEY= STRIPE_WEBHOOK_SECRET= APP_PASSPHRASE=simple123 -COTURN_STATIC_SECRET=23436d70545a9c5a26f863b3e2d176033c79254036280acc7cc978c21e181fc8 -MEET_WEBHOOK_TOKEN=7d2bdcc94f42adc4e0a31e5a0274fc22b5f9401f122f446f8f8cbb30f3143bd2 -MEET_SERVER_TOKEN=0288a77f5455b726f1f4854b1e0cec090a9312746d12454582252969e8e048d6 +MEET_WEBHOOK_TOKEN=simple123 +MEET_SERVER_TOKEN=simple123 APP_KEY=base64:EFXja/fHF01EMKiXW200b5zWOynbPzAHfUM78bOp+28= PASSPORT_PROXY_OAUTH_CLIENT_ID=5909ca4f-df7e-45fe-b355-e7c195aef117 PASSPORT_PROXY_OAUTH_CLIENT_SECRET=3URb+3JGJM9wPuDnlUSTPOw2mqmHsoOV8NXanx9xwQM= DES_KEY=kBxUM/53N9p9abusAoT0ZEAxwI2pxFz/ KOLAB_GIT_REF=dev/mollekopf KOLAB_GIT_REMOTE=https://git.kolab.org/source/kolab GIT_REF_ROUNDCUBEMAIL=dev/kolab-1.5 GIT_REMOTE_ROUNDCUBEMAIL=https://git.kolab.org/source/roundcubemail.git GIT_REF_ROUNDCUBEMAIL_PLUGINS=master GIT_REMOTE_ROUNDCUBEMAIL_PLUGINS=https://git.kolab.org/diffusion/RPK/roundcubemail-plugins-kolab.git GIT_REF_CHWALA=dev/mollekopf GIT_REMOTE_CHWALA=https://git.kolab.org/diffusion/C/chwala.git GIT_REF_SYNCROTON=master GIT_REMOTE_SYNCROTON=https://git.kolab.org/diffusion/S/syncroton.git GIT_REF_AUTOCONF=master GIT_REMOTE_AUTOCONF=https://git.kolab.org/diffusion/AC/autoconf.git GIT_REF_IRONY=master GIT_REMOTE_IRONY=https://git.kolab.org/source/iRony.git GIT_REF_FREEBUSY=master GIT_REMOTE_FREEBUSY=https://git.kolab.org/diffusion/F/freebusy.git IMAP_GIT_REF=dev/mollekopf IMAP_GIT_REMOTE=https://git.kolab.org/source/cyrus-imapd diff --git a/ci/testctl b/ci/testctl index 1df1e06a..62486d59 100755 --- a/ci/testctl +++ b/ci/testctl @@ -1,370 +1,460 @@ #!/bin/bash base_dir="$(dirname $(realpath "$0"))" pushd "${base_dir}" +pushd .. set -e set -x PASSPORT_PRIVATE_KEY="-----BEGIN PRIVATE KEY----- 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 bakhie7hJBP7BoOup+dD5NQPlXBQ434= -----END PRIVATE KEY-----" PASSPORT_PUBLIC_KEY="-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApmHkae115z3vMF9IjiUa XrJH1Ljifxqs+XbDCFhQenz2iOf/bZDBMqfrwhBe3hVywa13kIuhf1TZlcJ/nRhE IZIbg6BF6/GeHN998Cx/IjhBeFkG7f1hdxEXY5ibd7yq8vAfzizZpnCu4+LM/NvI ei9mU+hj3GxrDbpMQTHCDDqX5aNEix8uFU4XaOm9UOJw9ivz19cqcnxWqJ49znxw XUlS5k4Hewbwf2s2BWFhz+CDWPHMpWViLQ17qj5QRklNn39sUymP1kXKP3Y76zvW zNVniPvFt+hHixxEa7tUEaTdtk4FgkNnWy0bFa7DIPC8ukjHvHHg10LeQiygDduI xbdVJwYK/qitU68ZAbbufldlj2FoVLwSyP9qpxUIdRoljCop1kDu6xQiAq0VHEAV LtgMpZhtD/6D4z644QJ8atx4Ljp/HEtTngaTh+/vLc9AnhHclX0/JmlbP1VkWWxG 9FIxS0TVPolRBs8948kLioTif9lrltJicxd6T0OuA5fny8l6hdSlzaD3pnr5pkYw mVn5FgBAFnd/skX6DsRs+eb2lNahkvNZZ15z9UeU2Rl6J9uBx0vbkcB7eiSCPhRM IKq/CtkyEgz8ce4kG18fJHDFDASRvGjaBu91lV5h7NLmhFLFzMvb7XoHrv/yD6TV E5W47J/DrfrevJkzS1GV++MCAwEAAQ== -----END PUBLIC KEY-----" KOLAB_GIT_REF=dev/mollekopf KOLAB_GIT_REMOTE=https://git.kolab.org/source/kolab GIT_REF_ROUNDCUBEMAIL=dev/kolab-1.5 GIT_REMOTE_ROUNDCUBEMAIL=https://git.kolab.org/source/roundcubemail.git GIT_REF_ROUNDCUBEMAIL_PLUGINS=master GIT_REMOTE_ROUNDCUBEMAIL_PLUGINS=https://git.kolab.org/diffusion/RPK/roundcubemail-plugins-kolab.git GIT_REF_CHWALA=dev/mollekopf GIT_REMOTE_CHWALA=https://git.kolab.org/diffusion/C/chwala.git GIT_REF_SYNCROTON=master GIT_REMOTE_SYNCROTON=https://git.kolab.org/diffusion/S/syncroton.git GIT_REF_AUTOCONF=master GIT_REMOTE_AUTOCONF=https://git.kolab.org/diffusion/AC/autoconf.git GIT_REF_IRONY=master GIT_REMOTE_IRONY=https://git.kolab.org/source/iRony.git GIT_REF_FREEBUSY=master GIT_REMOTE_FREEBUSY=https://git.kolab.org/diffusion/F/freebusy.git IMAP_GIT_REF=dev/mollekopf IMAP_GIT_REMOTE=https://git.kolab.org/source/cyrus-imapd PODMAN="podman" # Teardown the currently running environment kolab__teardown() { $PODMAN pod rm --force tests + $PODMAN pod rm --force dev } # Build all containers required for testing kolab__build() { pushd .. $PODMAN build docker/base/ -f almalinux9 -t apheleia/almalinux9 $PODMAN build docker/swoole/ -t apheleia/swoole $PODMAN build --ulimit nofile=65535:65535 docker/webapp -t kolab-webapp $PODMAN build docker/imap -t kolab-imap $PODMAN build docker/mariadb -t mariadb $PODMAN build docker/redis -t redis $PODMAN build docker/proxy -t proxy $PODMAN build --ulimit nofile=65535:65535 docker/tests -t kolab-tests $PODMAN build --ulimit nofile=65535:65535 docker/roundcube -t roundcube popd } # Setup the test environment kolab__setup() { kolab__teardown echo "Build" kolab__build echo "Setup" pushd .. - # Create the pod first - $PODMAN pod create --name tests + POD=tests - # Mariadb - $PODMAN run -dt --pod tests --name mariadb \ - --mount=type=tmpfs,tmpfs-size=512M,destination=/var/lib/mysql,U=true \ - -e MYSQL_ROOT_PASSWORD=simple123 \ - -e TZ="+02:00" \ - -e DB_HKCCP_DATABASE=kolabdev \ - -e DB_HKCCP_USERNAME=kolabdev \ - -e DB_HKCCP_PASSWORD=simple123 \ - -e DB_KOLAB_DATABASE=kolab \ - -e DB_KOLAB_USERNAME=kolab \ - -e DB_KOLAB_PASSWORD=simple123 \ - -e DB_RC_DATABASE=roundcube \ - -e DB_RC_USERNAME=roundcube \ - -e DB_RC_PASSWORD=simple123 \ - --health-cmd "mysqladmin -u root ping && test -e /tmp/initialized" \ - mariadb:latest + # Create the pod first + $PODMAN pod create --name $POD - # redis - $PODMAN run -dt --pod tests --name redis \ - --mount=type=tmpfs,tmpfs-size=128M,destination=/var/lib/redis,U=true \ - --health-cmd "redis-cli ping || exit 1" \ - redis:latest + podman__run_mariadb + podman__run_redis - echo "Waiting for dependencies" podman__healthcheck mariadb redis - # We run with a fixed config.demo overlay and override the environment with ci/env - $PODMAN run -dt --pod tests --name webapp \ - --env-file=ci/env \ - -v ./src:/src/kolabsrc.orig:ro \ - -v ./config.demo/src:/src/overlay:ro \ - -e NOENVFILE=true \ - -e APP_SERVICES_ALLOWED_DOMAINS="webapp,localhost" \ - -e PASSPORT_PRIVATE_KEY="$PASSPORT_PRIVATE_KEY" \ - -e PASSPORT_PUBLIC_KEY="$PASSPORT_PUBLIC_KEY" \ - --health-cmd "./artisan octane:status || exit 1" \ - kolab-webapp:latest - echo "Wait for webapp" + podman__run_webapp podman__healthcheck webapp - # IMAP - $PODMAN run -dt --pod tests --name imap --replace \ - --mount=type=tmpfs,tmpfs-size=128M,tmpfs-mode=777,destination=/var/spool/imap,U=true,notmpcopyup \ - --mount=type=tmpfs,tmpfs-size=128M,tmpfs-mode=777,destination=/var/lib/imap,U=true,notmpcopyup \ - -e APP_SERVICES_DOMAIN="localhost" \ - -e SERVICES_PORT=8000 \ - -e IMAP_ADMIN_LOGIN=cyrus-admin \ - -e IMAP_ADMIN_PASSWORD=simple123 \ - --health-cmd "test -e /run/saslauthd/mux && kill -0 \$(cat /var/run/master.pid)" \ - kolab-imap:latest - echo "Waiting for dependencies" + podman__run_imap podman__healthcheck imap # Ensure all commands are processed echo "Flushing work queue" $PODMAN exec -ti webapp ./artisan queue:work --stop-when-empty - # minio - $PODMAN run -dt --pod tests --name minio --replace \ - --mount=type=tmpfs,tmpfs-size=128M,destination=/data,U=true \ - -e MINIO_ROOT_USER=minio \ - -e MINIO_ROOT_PASSWORD=simple123 \ - --health-cmd "mc ready local || exit 1" \ - --entrypoint sh \ - quay.io/minio/minio:latest -c 'mkdir -p /data/kolab && minio server /data --console-address ":9001"' - echo "Waiting for dependencies" + podman__run_minio podman__healthcheck minio popd # Validate the test environment kolab__validate } # "testsuite" # "quicktest" # "tests/Feature/Jobs/WalletCheckTest.php" kolab__test() { pushd .. $PODMAN run -ti --pod tests --name kolab-tests --replace \ --env-file=ci/env \ -v ./src:/src/kolabsrc.orig:ro \ -e APP_SERVICES_DOMAINS="localhost" \ -e PASSPORT_PRIVATE_KEY="$PASSPORT_PRIVATE_KEY" \ -e PASSPORT_PUBLIC_KEY="$PASSPORT_PUBLIC_KEY" \ kolab-tests:latest /init.sh $@ popd } kolab__proxytest() { pushd .. $PODMAN run -ti --pod tests --name proxy-tests --replace \ -v ./docker/certs/:/etc/certs/:ro \ --env-file=ci/env \ -e SSL_CERTIFICATE=/etc/certs/imap.hosted.com.cert \ -e SSL_CERTIFICATE_KEY=/etc/certs/imap.hosted.com.key \ proxy:latest /init.sh validate popd } kolab__lint() { pushd .. kolab__test lint } # Setup the test environment and run a complete testsuite kolab__testrun() { echo "Setup" kolab__setup echo "Test" kolab__test testsuite } # Setup the test environment and run all testsuites kolab__testrun_complete() { echo "Setup" kolab__setup echo "Test" kolab__test lint kolab__test testsuite kolab__rctest syncroton lint kolab__rctest syncroton testsuite kolab__rctest irony lint # kolab__rctest irony testsuite kolab__rctest roundcubemail-plugins-kolab lint # kolab__rctest roundcubemail-plugins-kolab testsuite } # Get a shell inside the test container to run/debug tests kolab__shell() { kolab__test shell } # Run the roundcube testsuite kolab__rctest() { pushd .. $PODMAN run -t --pod tests --name roundcube --replace \ -v ./ext:/src.orig:ro \ -e APP_DOMAIN=kolab.test \ -e DES_KEY=kBxUM/53N9p9abusAoT0ZEAxwI2pxFz/ \ -e DB_HOST=127.0.0.1 \ -e DB_RC_DATABASE=roundcube \ -e DB_RC_USERNAME=roundcube \ -e DB_RC_PASSWORD=simple123 \ -e IMAP_HOST=localhost \ -e IMAP_PORT=11143 \ -e IMAP_ADMIN_LOGIN=cyrus-admin \ -e IMAP_ADMIN_PASSWORD=simple123 \ -e MAIL_HOST=localhost \ -e MAIL_PORT=10587 \ -e FILEAPI_WOPI_OFFICE=https://kolab.local \ -e CALENDAR_CALDAV_SERVER=http://imap:11080/dav \ -e KOLAB_ADDRESSBOOK_CARDDAV_SERVER=http://imap:11080/dav \ roundcube:latest ./init.sh $@ popd } # Get a shell inside the roundcube test container to run/debug tests kolab__rcshell() { pushd .. $PODMAN run -ti --pod tests --name roundcube --replace \ -v ./ext:/src.orig:ro \ -e APP_DOMAIN=kolab.test \ -e DES_KEY=kBxUM/53N9p9abusAoT0ZEAxwI2pxFz/ \ -e DB_HOST=127.0.0.1 \ -e DB_RC_DATABASE=roundcube \ -e DB_RC_USERNAME=roundcube \ -e DB_RC_PASSWORD=simple123 \ -e IMAP_HOST=localhost \ -e IMAP_PORT=11143 \ -e IMAP_ADMIN_LOGIN=cyrus-admin \ -e IMAP_ADMIN_PASSWORD=simple123 \ -e MAIL_HOST=localhost \ -e MAIL_PORT=10587 \ -e FILEAPI_WOPI_OFFICE=https://kolab.local \ -e CALENDAR_CALDAV_SERVER=http://localhost:11080/dav \ -e KOLAB_ADDRESSBOOK_CARDDAV_SERVER=http://localhost:11080/dav \ roundcube:latest ./init.sh shell popd } kolab__validate() { $PODMAN exec imap testsaslauthd -u cyrus-admin -p simple123 $PODMAN exec imap testsaslauthd -u "john@kolab.org" -p simple123 # Ensure the inbox is created FOUND=false for i in {1..60}; do if $PODMAN exec imap bash -c 'echo "lm" | cyradm --auth PLAIN -u cyrus-admin -w simple123 --port 11143 localhost | grep "user/john@kolab.org"'; then echo "Found mailbox"; FOUND=true break else echo "Waiting for mailbox"; sleep 1; fi done if ! $FOUND; then echo "Failed to find the inbox for john@kolab.org" exit 1 fi } podman__healthcheck() { for CONTAINER in $@; do echo "Waiting for ${CONTAINER} become healthy " while [ $(podman healthcheck run ${CONTAINER}) ]; do echo -n "."; sleep 5; done done } +podman__run_proxy() { + $PODMAN run -dt --pod $POD --name proxy --replace \ + -v ./docker/certs:/etc/certs:ro \ + -e APP_WEBSITE_DOMAIN="kolab.local" \ + -e SSL_CERTIFICATE="/etc/certs/imap.hosted.com.cert" \ + -e SSL_CERTIFICATE_KEY="/etc/certs/imap.hosted.com.key" \ + -e WEBAPP_BACKEND="http://localhost:8000" \ + -e MEET_BACKEND="https://localhost:12443" \ + -e ROUNDCUBE_BACKEND="http://localhost:8080" \ + -e DAV_BACKEND="http://localhost:11080/dav" \ + -e COLLABORA_BACKEND="http://localhost:9980" \ + kolab-proxy:latest +} + +podman__run_mariadb() { + $PODMAN run -dt --pod $POD --name mariadb --replace \ + --mount=type=tmpfs,tmpfs-size=512M,destination=/var/lib/mysql,U=true \ + -e MYSQL_ROOT_PASSWORD=simple123 \ + -e TZ="+02:00" \ + -e DB_HKCCP_DATABASE=kolabdev \ + -e DB_HKCCP_USERNAME=kolabdev \ + -e DB_HKCCP_PASSWORD=simple123 \ + -e DB_KOLAB_DATABASE=kolab \ + -e DB_KOLAB_USERNAME=kolab \ + -e DB_KOLAB_PASSWORD=simple123 \ + -e DB_RC_DATABASE=roundcube \ + -e DB_RC_USERNAME=roundcube \ + -e DB_RC_PASSWORD=simple123 \ + --health-cmd "mysqladmin -u root ping && test -e /tmp/initialized" \ + mariadb:latest +} + +podman__run_redis() { + $PODMAN run -dt --pod $POD --name redis --replace \ + --mount=type=tmpfs,tmpfs-size=128M,destination=/var/lib/redis,U=true \ + --health-cmd "redis-cli ping || exit 1" \ + redis:latest +} + +podman__run_minio() { + $PODMAN run -dt --pod $POD --name minio --replace \ + --mount=type=tmpfs,tmpfs-size=128M,destination=/data,U=true \ + -e MINIO_ROOT_USER=minio \ + -e MINIO_ROOT_PASSWORD=simple123 \ + --health-cmd "mc ready local || exit 1" \ + --entrypoint sh \ + quay.io/minio/minio:latest -c 'mkdir -p /data/kolab && minio server /data --console-address ":9001"' +} + +podman__run_webapp() { + # We run with a fixed config.demo overlay and override the environment with ci/env + $PODMAN run -dt --pod $POD --name webapp --replace \ + --env-file=ci/env \ + -v ./src:/src/kolabsrc.orig:ro \ + -v ./config.prod/src:/src/overlay:ro \ + -e NOENVFILE=true \ + -e APP_SERVICES_ALLOWED_DOMAINS="webapp,localhost" \ + -e PASSPORT_PRIVATE_KEY="$PASSPORT_PRIVATE_KEY" \ + -e PASSPORT_PUBLIC_KEY="$PASSPORT_PUBLIC_KEY" \ + --health-cmd "./artisan octane:status || exit 1" \ + kolab-webapp:latest +} + +podman__run_imap() { + $PODMAN run -dt --pod $POD --name imap --replace \ + --mount=type=tmpfs,tmpfs-size=128M,tmpfs-mode=777,destination=/var/spool/imap,U=true,notmpcopyup \ + --mount=type=tmpfs,tmpfs-size=128M,tmpfs-mode=777,destination=/var/lib/imap,U=true,notmpcopyup \ + -e APP_SERVICES_DOMAIN="localhost" \ + -e SERVICES_PORT=8000 \ + -e IMAP_ADMIN_LOGIN=cyrus-admin \ + -e IMAP_ADMIN_PASSWORD=simple123 \ + --health-cmd "test -e /run/saslauthd/mux && kill -0 \$(cat /var/run/master.pid)" \ + kolab-imap:latest +} + +podman__run_meet() { + $PODMAN run -dt --pod $POD --name meet --replace \ + -v ./meet/server:/src/meet:ro \ + -v ./docker/certs/meet.kolab.local.cert:/etc/pki/tls/certs/meet.kolab.local.cert \ + -v ./docker/certs/meet.kolab.local.key:/etc/pki/tls/private/meet.kolab.local.key \ + -e WEBRTC_LISTEN_IP=127.0.0.1 \ + -e WEBRTC_ANNOUNCED_ADDRESS=127.0.0.1 \ + -e PUBLIC_DOMAIN=kolab.local \ + -e LISTENING_HOST=127.0.0.1 \ + -e LISTENING_PORT=12443 \ + -e DEBUG="*" \ + -e TURN_SERVER=none \ + -e AUTH_TOKEN=simple123 \ + -e WEBHOOK_TOKEN=simple123 \ + -e WEBHOOK_URL=kolab.local/api/webhooks/meet \ + -e SSL_CERT=/etc/pki/tls/certs/meet.kolab.local.cert \ + -e SSL_KEY=/etc/pki/tls/private/meet.kolab.local.key \ + kolab-meet:latest +} + +kolab__deploy() { + POD=dev + # Create the pod first + $PODMAN pod create \ + --replace \ + --publish "443:6443" \ + --publish "465:6465" \ + --publish "587:6587" \ + --publish "143:6143" \ + --publish "993:6993" \ + --publish "44444:44444/udp" \ + --publish "44444:44444/tcp" \ + --name $POD + + podman__run_mariadb + podman__run_redis + + podman__healthcheck mariadb redis + + podman__run_webapp + podman__healthcheck webapp + + podman__run_imap + podman__healthcheck imap + + # Ensure all commands are processed + echo "Flushing work queue" + $PODMAN exec -ti webapp ./artisan queue:work --stop-when-empty + + $PODMAN exec webapp ./artisan user:password "admin@kolab.local" "simple123" + + podman__run_minio + podman__healthcheck minio + + podman__run_meet + podman__healthcheck meet + + podman__run_proxy +} + kolab__help() { cat </dev/null 2>&1; then "kolab__$cmdname" "${@:1}" else echo "Function $cmdname not recognized" >&2 kolab__help exit 1 fi diff --git a/docker/proxy/rootfs/etc/nginx/nginx.conf b/docker/proxy/rootfs/etc/nginx/nginx.conf index 1cf24a6a..e91c6e8f 100644 --- a/docker/proxy/rootfs/etc/nginx/nginx.conf +++ b/docker/proxy/rootfs/etc/nginx/nginx.conf @@ -1,324 +1,324 @@ # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ worker_processes auto; error_log stderr info; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /dev/stdout main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; map $http_upgrade $connection_upgrade { default upgrade; '' close; } # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 6080; listen 6443 default_server ssl; listen [::]:6443 ssl ipv6only=on; ssl_certificate SSL_CERTIFICATE_CERT; ssl_certificate_key SSL_CERTIFICATE_KEY; server_name APP_WEBSITE_DOMAIN; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass WEBAPP_BACKEND; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_no_cache 1; proxy_cache_bypass 1; # Mostly for files, swoole has a 10MB limit client_max_body_size 11m; } location /meetmedia { proxy_pass MEET_BACKEND; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; } location /meetmedia/api { proxy_pass MEET_BACKEND; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_no_cache 1; proxy_cache_bypass 1; } location WEBMAIL_PATH { proxy_pass ROUNDCUBE_BACKEND; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_no_cache 1; proxy_cache_bypass 1; } location /chwala { proxy_pass ROUNDCUBE_BACKEND; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_no_cache 1; proxy_cache_bypass 1; } location /Microsoft-Server-ActiveSync { auth_request /auth; #auth_request_set $auth_status $upstream_status; proxy_pass ROUNDCUBE_BACKEND; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_send_timeout 910s; proxy_read_timeout 910s; fastcgi_send_timeout 910s; fastcgi_read_timeout 910s; } location ~* ^/\\.well-known/autoconfig { proxy_pass ROUNDCUBE_BACKEND; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~* ^/\\autodiscover/autodiscover.xml { proxy_pass ROUNDCUBE_BACKEND; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~ ^/\\.well-known/(caldav|carddav)(.*)$ { proxy_pass ROUNDCUBE_BACKEND; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /dav { #auth_request_set $auth_status $upstream_status; proxy_pass DAV_BACKEND; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # static files location ^~ /browser { proxy_pass COLLABORA_BACKEND; proxy_set_header Host $http_host; } # WOPI discovery URL location ^~ /hosting/discovery { proxy_pass COLLABORA_BACKEND; proxy_set_header Host $http_host; } # Capabilities location ^~ /hosting/capabilities { proxy_pass COLLABORA_BACKEND; proxy_set_header Host $http_host; } # main websocket location ~ ^/cool/(.*)/ws$ { proxy_pass COLLABORA_BACKEND; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $http_host; proxy_read_timeout 36000s; } # download, presentation and image upload location ~ ^/(c|l)ool { proxy_pass COLLABORA_BACKEND; proxy_set_header Host $http_host; } # Admin Console websocket location ^~ /cool/adminws { proxy_pass COLLABORA_BACKEND; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $http_host; proxy_read_timeout 36000s; } location = /auth { internal; proxy_pass WEBAPP_BACKEND/api/webhooks/nginx-httpauth; proxy_pass_request_body off; proxy_set_header Host services.APP_WEBSITE_DOMAIN; proxy_set_header Content-Length ""; proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /healthz { auth_basic off; allow all; return 200; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } } mail { server_name APP_WEBSITE_DOMAIN; auth_http WEBAPP_BACKEND/api/webhooks/nginx; auth_http_header Host services.APP_WEBSITE_DOMAIN; proxy_pass_error_message on; proxy_smtp_auth on; xclient off; server { listen 6143; protocol imap; proxy on; starttls on; ssl_certificate SSL_CERTIFICATE_CERT; ssl_certificate_key SSL_CERTIFICATE_KEY; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } # Roundcube specific imap endpoint with proxy-protocol enabled server { listen 6144 proxy_protocol; protocol imap; auth_http WEBAPP_BACKEND/api/webhooks/nginx-roundcube; proxy on; starttls on; ssl_certificate SSL_CERTIFICATE_CERT; ssl_certificate_key SSL_CERTIFICATE_KEY; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } server { listen 6465 ssl; protocol smtp; proxy on; ssl_certificate SSL_CERTIFICATE_CERT; ssl_certificate_key SSL_CERTIFICATE_KEY; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } server { listen 6587; protocol smtp; proxy on; starttls on; ssl_certificate SSL_CERTIFICATE_CERT; ssl_certificate_key SSL_CERTIFICATE_KEY; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } server { listen 6993 ssl; protocol imap; proxy on; ssl_certificate SSL_CERTIFICATE_CERT; ssl_certificate_key SSL_CERTIFICATE_KEY; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } } stream { server { - listen 4190 ssl; + listen 6190 ssl; ssl_certificate SSL_CERTIFICATE_CERT; ssl_certificate_key SSL_CERTIFICATE_KEY; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; proxy_pass imap:4190; } } diff --git a/kolabctl b/kolabctl index f79e0d9a..d087b55f 100755 --- a/kolabctl +++ b/kolabctl @@ -1,99 +1,101 @@ #!/bin/bash +set -e + CONFIG=${CONFIG:-"config.prod"} HOST=${HOST:-"kolab.local"} BRANCH=${BRANCH:-"master"} kolab__deploy() { echo "Please enter your new admin password for the admin@$HOST user:" read -r ADMIN_PASSWORD echo "Deploying $CONFIG from branch $BRANCH on $HOST" command env KOLAB_GIT_REF=$BRANCH HOST=$HOST ADMIN_PASSWORD="$ADMIN_PASSWORD" bin/configure.sh "$CONFIG" command env ADMIN_PASSWORD="$ADMIN_PASSWORD" bin/deploy.sh } kolab__start() { command bin/start.sh } kolab__stop() { command bin/stop.sh } kolab__update() { command bin/update.sh } kolab__backup() { command bin/backup.sh } kolab__restore() { command bin/restore.sh } kolab__selfcheck() { command bin/selfcheck.sh } kolab__ps() { command docker compose ps } kolab__exec() { command docker compose exec -ti $@ } kolab__run() { command docker compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.build.yml run --rm -ti $@ } kolab__build() { command docker compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.build.yml build $@ } kolab__cyradm() { # command docker compose exec -ti imap cyradm --auth PLAIN -u admin@kolab.local -w simple123 --port 11143 localhost if [[ "$@" ]]; then command docker compose exec -ti imap echo "$@" | cyradm --auth PLAIN -u $(grep IMAP_ADMIN_LOGIN .env | cut -d '=' -f 2 ) -w $(grep IMAP_ADMIN_PASSWORD .env | cut -d '=' -f 2 ) --port 11143 localhost else command docker compose exec -ti imap cyradm --auth PLAIN -u $(grep IMAP_ADMIN_LOGIN .env | cut -d '=' -f 2 ) -w $(grep IMAP_ADMIN_PASSWORD .env | cut -d '=' -f 2 ) --port 11143 localhost fi } kolab__shell() { command docker compose exec -ti $1 /bin/bash } kolab__logs() { command docker compose logs -f $1 } kolab__help() { cat </dev/null 2>&1; then "kolab__$cmdname" "${@:1}" else echo "Function $cmdname not recognized" >&2 kolab__help exit 1 fi