diff --git a/ansible/Makefile b/ansible/Makefile new file mode 100644 index 00000000..55869f2d --- /dev/null +++ b/ansible/Makefile @@ -0,0 +1,10 @@ +OX_API_KEY= +FIREBASE_API_KEY= +HOSTNAME= +PUBLIC_IP= +GIT_BRANCH=beta-release + +setup: + touch ./hosts + echo "${HOSTNAME}" > ./hosts + ansible-playbook -v --inventory=./hosts --extra-vars="hostname=${HOSTNAME} openexchangerates_api_key=${OX_API_KEY} firebase_api_key=${FIREBASE_API_KEY} public_ip=${PUBLIC_IP} git_branch=${GIT_BRANCH}" setup.yml diff --git a/ansible/README.md b/ansible/README.md new file mode 100644 index 00000000..62ff098e --- /dev/null +++ b/ansible/README.md @@ -0,0 +1,13 @@ +# Setup a new node with a kolab deployment. + +* Make sure you're running on cgroupv1 for docker to work (needs a kernel option and reboot if not already done, see bin/quickstart.sh). +* Set secrets in makefile +* Set host in hosts file +* Run "make setup" to execute ansible-playbook to install packages and fetch things +* ssh into system: +** sudo certbot certonly --standalone -d $hostname +** sudo chmod 755 -R /etc/letsencrypt/ +** run bin/quickstart.sh +** ./artisan user:assign john@kolab.org meet +** ./artisan user:assign john@kolab.org beta + diff --git a/ansible/build-swoole.sh b/ansible/build-swoole.sh new file mode 100755 index 00000000..dc26899b --- /dev/null +++ b/ansible/build-swoole.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +yes | pecl install swoole + +echo "extension=swoole.so" >> /etc/php.d/swoole.ini +php -m 2>&1 | grep -q swoole diff --git a/ansible/env.local b/ansible/env.local new file mode 100644 index 00000000..af4eb44e --- /dev/null +++ b/ansible/env.local @@ -0,0 +1,36 @@ +MFA_DSN=mysql://root:Welcome2KolabSystems@127.0.0.1/roundcube +APP_DOMAIN={{ host }} +APP_WEBSITE_DOMAIN={{ host }} +APP_KEY=base64:FG6ECzyAMSmyX+eYwO/FW3bwnarbKkBhqtO65vlMb1E= +APP_PUBLIC_URL=https://{{ host }} +COTURN_STATIC_SECRET=uzYguvIl9tpZFMuQOE78DpOi6Jc7VFSD0UAnvgMsg5n4e74MgIf6vQvbc6LWzZjz +COTURN_PUBLIC_IP='{{ public_ip }}' +MEET_TURN_SERVER='turn:{{ public_ip }}:3478' +MEET_WEBRTC_LISTEN_IP='{{ public_ip }}' +MEET_PUBLIC_DOMAIN={{ host }} +MEET_SERVER_URLS=https://{{ host }}/meetmedia/api/ +WEBMAIL_URL=/roundcubemail +APP_URL=https://{{ host }} +ASSET_URL=https://{{ host }} + +MOLLIE_KEY= +STRIPE_KEY= +STRIPE_PUBLIC_KEY= +STRIPE_WEBHOOK_SECRET= + +OCTANE_HTTP_HOST={{ host }} +OPENEXCHANGERATES_API_KEY={{ openexchangerates_api_key }} +FIREBASE_API_KEY={{ firebase_api_key }} + +#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 + +#Generated by php artisan passport:client --password, but can be left hardcoded (the seeder will pick it up) +PASSPORT_COMPANIONAPP_OAUTH_CLIENT_ID=9566e018-f05d-425c-9915-420cdb9258bb +PASSPORT_COMPANIONAPP_OAUTH_CLIENT_SECRET=XjgV6SU9shO0QFKaU6pQPRC5rJpyRezDJTSoGLgz + +APP_TENANT_ID=42 +APP_PASSPHRASE=simple123 + +MAIL_DRIVER=log diff --git a/ansible/hosts b/ansible/hosts new file mode 100644 index 00000000..171e2191 --- /dev/null +++ b/ansible/hosts @@ -0,0 +1 @@ +kolab1.mkpf.ch diff --git a/ansible/packages.yml b/ansible/packages.yml new file mode 100644 index 00000000..80923f72 --- /dev/null +++ b/ansible/packages.yml @@ -0,0 +1,28 @@ +--- +- name: Install list of required packages + package: name={{ item }} state=installed + with_items: + - git + - tig + - tmux + - docker + - docker-compose + - composer + - npm + - php-ldap + - php-mysqlnd + - diffutils + - file + - make + - openssl-devel + - patch + - php-cli + - php-common + - php-devel + - php-ldap + - php-opcache + - php-pecl-apcu + - php-mysqlnd + - re2c + - php-pear + - certbot diff --git a/ansible/setup.yml b/ansible/setup.yml new file mode 100755 index 00000000..0a9ba3dc --- /dev/null +++ b/ansible/setup.yml @@ -0,0 +1,113 @@ +#!/usr/bin/ansible-playbook +- name: Setup kolab deployment on fedora server + hosts: "{{ hostname }}" + remote_user: root + tasks: + - name: Set hostname + ansible.builtin.hostname: + name: "{{ hostname }}" + + - import_tasks: packages.yml + + - name: Setup user kolab + ansible.builtin.user: + name: kolab + shell: /bin/bash + groups: wheel, audio, docker + append: yes + + - name: sudo without password + ansible.builtin.lineinfile: + path: /etc/sudoers + state: present + regexp: '^%wheel\s' + line: '%wheel ALL=(ALL) NOPASSWD: ALL' + + - name: Start service docker, if not started + ansible.builtin.service: + name: docker + state: started + + - name: Build swoole + ansible.builtin.script: build-swoole.sh + args: + creates: /usr/lib64/php/modules/swoole.so + + - name: get kolab git repo + become: true + become_user: kolab + git: + repo: https://git.kolab.org/source/kolab.git + dest: /home/kolab/kolab + version: "{{ git_branch }}" + force: yes + + - name: "kolab env.local" + vars: + host: "{{ hostname }}" + openexchangerates_api_key: "{{ openexchangerates_api_key }}" + firebase_api_key: "{{ firebase_api_key }}" + public_ip: "{{ public_ip }}" + ansible.builtin.template: + src: env.local + dest: /home/kolab/kolab/src/env.local + owner: kolab + group: kolab + mode: '0766' + + - name: Permit receiving mail + firewalld: + port: 25/tcp + permanent: yes + state: enabled + zone: FedoraServer + + - name: Permit http traffic + firewalld: + port: 80/tcp + permanent: yes + state: enabled + zone: FedoraServer + + - name: Permit https traffic + firewalld: + port: 443/tcp + permanent: yes + state: enabled + zone: FedoraServer + + - name: Permit TCP trafic for coturn + firewalld: + port: 3478/tcp + permanent: yes + state: enabled + zone: FedoraServer + + - name: Permit TCP trafic for coturn + firewalld: + port: 5349/tcp + permanent: yes + state: enabled + zone: FedoraServer + + - name: Permit UDP trafic for coturn + firewalld: + port: 3478/udp + permanent: yes + state: enabled + zone: FedoraServer + + - name: Permit UDP trafic for coturn + firewalld: + port: 5349/udp + permanent: yes + state: enabled + zone: FedoraServer + + # Not a great idea since it never exits + # - name: Run bin/quickstart + # become: true + # become_user: kolab + # ansible.builtin.command: bin/quickstart.sh + # args: + # chdir: /home/kolab/kolab diff --git a/docker-compose.yml b/docker-compose.yml index 641c0337..ffa63e91 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,196 +1,202 @@ 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 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 + - IMAP_HOST=127.0.0.1 + - IMAP_PORT=11993 + - MAIL_HOST=127.0.0.1 + - MAIL_PORT=10587 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: - ./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:/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 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} healthcheck: interval: 10s test: ["CMD-SHELL", "curl -so /dev/null http://localhost/ || exit 1"] timeout: 5s retries: 30 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 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/ + args: + APP_WEBSITE_DOMAIN: ${APP_WEBSITE_DOMAIN:?err} healthcheck: interval: 10s test: ["CMD-SHELL", "curl -so /dev/null http://localhost/ || exit 1"] timeout: 5s retries: 30 container_name: kolab-proxy - hostname: kanarip.internet-box.ch + hostname: ${APP_WEBSITE_DOMAIN:?err} 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/ healthcheck: interval: 10s test: "redis-cli ping || exit 1" timeout: 5s retries: 30 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.8.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/ healthcheck: interval: 10s test: "curl --insecure -H 'X-AUTH-TOKEN: ${MEET_SERVER_TOKEN}' --fail https://localhost:12443/meetmedia/api/health || exit 1" timeout: 5s retries: 30 environment: - WEBRTC_LISTEN_IP=${MEET_WEBRTC_LISTEN_IP:?err} - PUBLIC_DOMAIN=${MEET_PUBLIC_DOMAIN:?err} - LISTENING_HOST=0.0.0.0 - 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/meet/build/node_modules:/root/node_modules - ./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 diff --git a/docker/kolab/utils/04-reset-mysql-kolab-password.sh b/docker/kolab/utils/04-reset-mysql-kolab-password.sh index 431e4f1b..5f6e768b 100755 --- a/docker/kolab/utils/04-reset-mysql-kolab-password.sh +++ b/docker/kolab/utils/04-reset-mysql-kolab-password.sh @@ -1,15 +1,15 @@ #!/bin/bash sqlpw=$(grep ^sql_uri /etc/kolab/kolab.conf | awk -F':' '{print $3}' | awk -F'@' '{print $1}') mysql -h ${DB_HOST:-127.0.0.1} -u root --password=${DB_ROOT_PASSWORD:-Welcome2KolabSystems} \ -e "SET PASSWORD FOR '${DB_HKCCP_USERNAME:-kolabdev}'@'%' = PASSWORD('${DB_HKCCP_PASSWORD:-kolab}');" mysql -h ${DB_HOST:-127.0.0.1} -u root --password=${DB_ROOT_PASSWORD:-Welcome2KolabSystems} \ -e "SET PASSWORD FOR '${DB_KOLAB_USERNAME:-kolab}'@'%' = PASSWORD('${DB_KOLAB_PASSWORD:=$sqlpw}');" mysql -h ${DB_HOST:-127.0.0.1} -u root --password=${DB_ROOT_PASSWORD:-Welcome2KolabSystems} \ -e "SET PASSWORD FOR '${DB_RC_USERNAME:-roundcube}'@'%' = PASSWORD('${DB_RC_PASSWORD:-Welcome2KolabSystems}');" -mysql -h ${DB_HOST} -u root --password=${DB_ROOT_PASSWORD} +mysql -h ${DB_HOST:-127.0.0.1} -u root --password=${DB_ROOT_PASSWORD:-Welcome2KolabSystems} \ -e "CREATE USER '${DB_RC_USERNAME:-roundcube}'@'%' IDENTIFIED BY '${DB_RC_PASSWORD:-Welcome2KolabSystems}'; FLUSH PRIVILEGES;" diff --git a/docker/kolab/utils/05-replace-localhost.sh b/docker/kolab/utils/05-replace-localhost.sh index dccff4db..f987423f 100755 --- a/docker/kolab/utils/05-replace-localhost.sh +++ b/docker/kolab/utils/05-replace-localhost.sh @@ -1,28 +1,30 @@ #!/bin/bash if [[ ${DB_HOST} == "localhost" || ${DB_HOST} == "127.0.0.1" ]]; then mysql -h ${DB_HOST:-127.0.0.1} -u root --password=${DB_ROOT_PASSWORD:-Welcome2KolabSystems} \ -e "UPDATE mysql.db SET Host = '127.0.0.1' WHERE Host = 'localhost';" mysql -h ${DB_HOST:-127.0.0.1} -u root --password=${DB_ROOT_PASSWORD:-Welcome2KolabSystems} \ -e "FLUSH PRIVILEGES;" fi sed -i -e "s#^ldap_servers:.*#ldap_servers: ldap://${LDAP_HOST:-127.0.0.1}:389#" /etc/imapd.conf sed -i -e "/hosts/s/localhost/${LDAP_HOST:-127.0.0.1}/" /etc/iRony/dav.inc.php sed -i -e "s#^ldap_uri.*#ldap_uri = ldap://${LDAP_HOST:-127.0.0.1}:389#" \ -e "s#^cache_uri.*mysql://\(.*\):\(.*\)@\(.*\)\/\(.*\)#cache_uri = mysql://${DB_KOLAB_USERNAME:-\1}:${DB_KOLAB_PASSWORD:-\2}@${DB_HOST:-127.0.0.1}/${DB_KOLAB_DATABASE:-\4}#" \ -e "s#^sql_uri.*mysql://\(.*\):\(.*\)@\(.*\)\/\(.*\)#sql_uri = mysql://${DB_KOLAB_USERNAME:-\1}:${DB_KOLAB_PASSWORD:-\2}@${DB_HOST:-127.0.0.1}/${DB_KOLAB_DATABASE:-\4}#" \ - -e "s#^uri.*#uri = imaps://${IMAP_HOST:-127.0.0.1}:993#" /etc/kolab/kolab.conf + -e "s#^uri.*#uri = imaps://${IMAP_HOST:-127.0.0.1}:11993#" /etc/kolab/kolab.conf sed -i -e "/host/s/localhost/${LDAP_HOST:-127.0.0.1}/g" \ -e "/fbsource/s/localhost/${IMAP_HOST:-127.0.0.1}/g" /etc/kolab-freebusy/config.ini -sed -i -e "s/server_host.*/server_host = ${LDAP_HOST:-127.0.0.1}/g" /etc/postfix/ldap/* +#sed -i -e "s/server_host.*/server_host = ${LDAP_HOST:-127.0.0.1}/g" /etc/postfix/ldap/* sed -i -e "/password_ldap_host/s/localhost/${LDAP_HOST:-127.0.0.1}/" /etc/roundcubemail/password.inc.php sed -i -e "/hosts/s/localhost/${LDAP_HOST:-127.0.0.1}/" /etc/roundcubemail/kolab_auth.inc.php sed -i -e "s#.*db_dsnw.*# \$config['db_dsnw'] = 'mysql://${DB_RC_USERNAME:-roundcube}:${DB_RC_PASSWORD:-Welcome2KolabSystems}@${DB_HOST:-127.0.0.1}/${DB_RC_DATABASE:-roundcube}';#" \ - -e "/default_host/s/localhost/${IMAP_HOST:-127.0.0.1}/" \ - -e "/smtp_server/s/localhost/${MAIL_HOST:-127.0.0.1}/" \ + -e "/default_host/s|= .*$|= 'ssl://${IMAP_HOST:-127.0.0.1}';|" \ + -e "/default_port/s|= .*$|= ${IMAP_PORT:-11993};|" \ + -e "/smtp_server/s|= .*$|= 'tls://${MAIL_HOST:-127.0.0.1}';|" \ + -e "/smtp_port/s/= .*$/= ${MAIL_PORT:-10587};/" \ -e "/hosts/s/localhost/${LDAP_HOST:-127.0.0.1}/" /etc/roundcubemail/config.inc.php sed -i -e "/hosts/s/localhost/${LDAP_HOST:-127.0.0.1}/" /etc/roundcubemail/calendar.inc.php systemctl restart cyrus-imapd postfix diff --git a/docker/kolab/utils/07-adjust-base-dns.sh b/docker/kolab/utils/07-adjust-base-dns.sh index b8894906..30b1b759 100755 --- a/docker/kolab/utils/07-adjust-base-dns.sh +++ b/docker/kolab/utils/07-adjust-base-dns.sh @@ -1,26 +1,30 @@ #!/bin/bash . ./settings.sh echo "ldap_domain_base_dn: ${domain_base_dn}" >> /etc/imapd.conf +sed -i -r \ + -e "s/^ldap_base: .*$/ldap_base: ${hosted_domain_rootdn}/g" \ + /etc/imapd.conf + sed -i -r \ -e "s/(\s+)base => '.*',$/\1base => '${hosted_domain_rootdn}',/g" \ -e "/\\\$mydomain = / a\ \$myhostname = '${HOSTNAME:-kolab}.${DOMAIN:-mgmt.com}';" \ -e "s/^base_dn = .*$/base_dn = ${hosted_domain_rootdn}/g" \ -e "s/^search_base = .*$/search_base = ${hosted_domain_rootdn}/g" \ -e "s/(\s+)'base_dn'(\s+)=> '.*',/\1'base_dn'\2=> '${hosted_domain_rootdn}',/g" \ -e "s/(\s+)'search_base_dn'(\s+)=> '.*',/\1'search_base_dn'\2=> '${hosted_domain_rootdn}',/g" \ -e "s/(\s+)'user_specific'(\s+)=> false,/\1'user_specific'\2=> true,/g" \ /etc/amavisd/amavisd.conf \ /etc/kolab-freebusy/config.ini \ /etc/postfix/ldap/*.cf \ /etc/roundcubemail/config.inc.php \ /etc/roundcubemail/kolab_auth.inc.php sed -i -r \ -e "s/^search_base = .*$/search_base = ${domain_base_dn}/g" \ /etc/postfix/ldap/mydestination.cf systemctl restart cyrus-imapd postfix diff --git a/docker/kolab/utils/10-change-port-numbers.sh b/docker/kolab/utils/10-change-port-numbers.sh index 7646d5a2..b62615fc 100755 --- a/docker/kolab/utils/10-change-port-numbers.sh +++ b/docker/kolab/utils/10-change-port-numbers.sh @@ -1,143 +1,145 @@ #!/bin/bash sed -i -r \ -e '/allowplaintext/ a\ guam_allowplaintext: yes' \ -e '/allowplaintext/ a\ nginx_allowplaintext: yes' \ /etc/imapd.conf sed -i \ -e '/SERVICES/ a\ nginx cmd="imapd" listen=127.0.0.1:12143 prefork=1' \ -e '/SERVICES/ a\ guam cmd="imapd" listen=127.0.0.1:13143 prefork=1' \ -e '/SERVICES/ a\ imap cmd="imapd" listen=127.0.0.1:11143 prefork=1' \ -e 's/listen="127.0.0.1:9993"/listen=127.0.0.1:11993/g' \ /etc/cyrus.conf systemctl restart cyrus-imapd -sed -i -e '/submission/,10d' /etc/postfix/master.cf +# Remove the submission block, by matching from submission until the next empty line +sed -i -e '/submission inet/,/^$/d' /etc/postfix/master.cf +# Insert a new submission block with a modified port cat >> /etc/postfix/master.cf << EOF 127.0.0.1:10587 inet n - n - - smtpd -o cleanup_service_name=cleanup_submission -o syslog_name=postfix/submission #-o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_authenticated_header=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_data_restrictions=\$submission_data_restrictions -o smtpd_recipient_restrictions=\$submission_recipient_restrictions -o smtpd_sender_restrictions=\$submission_sender_restrictions 127.0.0.1:10465 inet n - n - - smtpd -o cleanup_service_name=cleanup_submission -o rewrite_service_name=rewrite_submission -o syslog_name=postfix/smtps -o mydestination= -o local_recipient_maps= -o relay_domains= -o relay_recipient_maps= #-o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_authenticated_header=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_sender_restrictions=\$submission_sender_restrictions -o smtpd_recipient_restrictions=\$submission_recipient_restrictions -o smtpd_data_restrictions=\$submission_data_restrictions EOF systemctl restart postfix cat > /etc/guam/sys.config << EOF %% Example configuration for Guam. [ { kolab_guam, [ { imap_servers, [ { imap, [ { host, "127.0.0.1" }, { port, 13143 }, { tls, no } ] }, { imaps, [ { host, "127.0.0.1" }, { port, 11993 }, { tls, true } ] } ] }, { listeners, [ { imap, [ { port, 9143 }, { imap_server, imap }, { rules, [ { filter_groupware, [] } ] }, { tls_config, [ { certfile, "/etc/pki/cyrus-imapd/cyrus-imapd.pem" } ] } ] }, { imaps, [ { port, 9993 }, { implicit_tls, true }, { imap_server, imaps }, { rules, [ { filter_groupware, [] } ] }, { tls_config, [ { certfile, "/etc/pki/cyrus-imapd/cyrus-imapd.pem" } ] } ] } ] } ] }, { lager, [ { handlers, [ { lager_console_backend, warning }, { lager_file_backend, [ { file, "log/error.log"}, { level, error } ] }, { lager_file_backend, [ { file, "log/console.log"}, { level, info } ] } ] } ] }, %% SASL config { sasl, [ { sasl_error_logger, { file, "log/sasl-error.log" } }, { errlog_type, error }, { error_logger_mf_dir, "log/sasl" }, % Log directory { error_logger_mf_maxbytes, 10485760 }, % 10 MB max file size { error_logger_mf_maxfiles, 5 } % 5 files max ] } ]. EOF systemctl restart guam diff --git a/docker/kolab/utils/15-create-hosted-domain.sh b/docker/kolab/utils/15-create-hosted-domain.sh index 96647adb..d8ea455c 100755 --- a/docker/kolab/utils/15-create-hosted-domain.sh +++ b/docker/kolab/utils/15-create-hosted-domain.sh @@ -1,99 +1,110 @@ #!/bin/bash . ./settings.sh ( echo "dn: associateddomain=${hosted_domain},${domain_base_dn}" echo "objectclass: top" echo "objectclass: domainrelatedobject" echo "objectclass: inetdomain" echo "inetdomainstatus: active" echo "associateddomain: ${hosted_domain}" echo "inetdomainbasedn: ${hosted_domain_rootdn}" echo "" echo "dn: cn=$(echo ${hosted_domain_rootdn} | sed -e 's/=/\\3D/g' -e 's/,/\\2D/g'),cn=mapping tree,cn=config" echo "objectClass: top" echo "objectClass: extensibleObject" echo "objectClass: nsMappingTree" echo "nsslapd-state: backend" echo "cn: ${hosted_domain_rootdn}" echo "nsslapd-backend: $(echo ${hosted_domain} | sed -e 's/\./_/g')" echo "" echo "dn: cn=$(echo ${hosted_domain} | sed -e 's/\./_/g'),cn=ldbm database,cn=plugins,cn=config" echo "objectClass: top" echo "objectClass: extensibleobject" echo "objectClass: nsbackendinstance" echo "cn: $(echo ${hosted_domain} | sed -e 's/\./_/g')" echo "nsslapd-suffix: ${hosted_domain_rootdn}" echo "nsslapd-cachesize: -1" echo "nsslapd-cachememsize: 10485760" echo "nsslapd-readonly: off" echo "nsslapd-require-index: off" echo "nsslapd-directory: /var/lib/dirsrv/slapd-${DS_INSTANCE_NAME:-$(hostname -s)}/db/$(echo ${hosted_domain} | sed -e 's/\./_/g')" echo "nsslapd-dncachememsize: 10485760" echo "" ) | ldapadd -x -h ${ldap_host} -D "${ldap_binddn}" -w "${ldap_bindpw}" ( echo "dn: ${hosted_domain_rootdn}" echo "aci: (targetattr=\"carLicense || description || displayName || facsimileTelephoneNumber || homePhone || homePostalAddress || initials || jpegPhoto || labeledURI || mobile || pager || photo || postOfficeBox || postalAddress || postalCode || preferredDeliveryMethod || preferredLanguage || registeredAddress || roomNumber || secretary || seeAlso || st || street || telephoneNumber || telexNumber || title || userCertificate || userPassword || userSMIMECertificate || x500UniqueIdentifier\")(version 3.0; acl \"Enable self write for common attributes\"; allow (write) userdn=\"ldap:///self\";)" echo "aci: (targetattr =\"*\")(version 3.0;acl \"Directory Administrators Group\";allow (all) (groupdn=\"ldap:///cn=Directory Administrators,${hosted_domain_rootdn}\" or roledn=\"ldap:///cn=kolab-admin,${hosted_domain_rootdn}\");)" echo "aci: (targetattr=\"*\")(version 3.0; acl \"Configuration Administrators Group\"; allow (all) groupdn=\"ldap:///cn=Configuration Administrators,ou=Groups,ou=TopologyManagement,o=NetscapeRoot\";)" echo "aci: (targetattr=\"*\")(version 3.0; acl \"Configuration Administrator\"; allow (all) userdn=\"ldap:///uid=admin,ou=Administrators,ou=TopologyManagement,o=NetscapeRoot\";)" echo "aci: (targetattr = \"*\")(version 3.0; acl \"SIE Group\"; allow (all) groupdn = \"ldap:///cn=slapd-$(hostname -s),cn=389 Directory Server,cn=Server Group,cn=$(hostname -f),ou=${domain},o=NetscapeRoot\";)" echo "aci: (targetattr = \"*\") (version 3.0;acl \"Search Access\";allow (read,compare,search)(userdn = \"ldap:///${hosted_domain_rootdn}??sub?(objectclass=*)\");)" echo "aci: (targetattr = \"*\") (version 3.0;acl \"Service Search Access\";allow (read,compare,search)(userdn = \"ldap:///uid=kolab-service,ou=Special Users,${rootdn}\");)" echo "objectClass: top" echo "objectClass: domain" echo "dc: $(echo ${hosted_domain} | cut -d'.' -f 1)" echo "" ) | ldapadd -x -h ${ldap_host} -D "${ldap_binddn}" -w "${ldap_bindpw}" ( for role in "2fa-user" "activesync-user" "imap-user"; do echo "dn: cn=${role},${hosted_domain_rootdn}" echo "cn: ${role}" echo "description: ${role} role" echo "objectclass: top" echo "objectclass: ldapsubentry" echo "objectclass: nsmanagedroledefinition" echo "objectclass: nsroledefinition" echo "objectclass: nssimpleroledefinition" echo "" done echo "dn: ou=Groups,${hosted_domain_rootdn}" echo "ou: Groups" echo "objectClass: top" echo "objectClass: organizationalunit" echo "" echo "dn: ou=People,${hosted_domain_rootdn}" echo "aci: (targetattr = \"*\") (version 3.0;acl \"Hosted Kolab Services\";allow (all)(userdn = \"ldap:///uid=hosted-kolab-service,ou=Special Users,${rootdn}\");)" echo "ou: People" echo "objectClass: top" echo "objectClass: organizationalunit" echo "" echo "dn: ou=Special Users,${hosted_domain_rootdn}" echo "ou: Special Users" echo "objectClass: top" echo "objectClass: organizationalunit" echo "" echo "dn: ou=Resources,${hosted_domain_rootdn}" echo "ou: Resources" echo "objectClass: top" echo "objectClass: organizationalunit" echo "" echo "dn: ou=Shared Folders,${hosted_domain_rootdn}" echo "ou: Shared Folders" echo "objectClass: top" echo "objectClass: organizationalunit" echo "" + echo "dn: uid=cyrus-admin,ou=Special Users,${hosted_domain_rootdn}" + echo "sn: Administrator" + echo "uid: cyrus-admin" + echo "objectClass: top" + echo "objectClass: person" + echo "objectClass: inetorgperson" + echo "objectClass: organizationalperson" + echo "givenName: Cyrus" + echo "cn: Cyrus Administrator" + echo "" + ) | ldapadd -x -h ${ldap_host} -D "${ldap_binddn}" -w "${ldap_bindpw}" diff --git a/docker/kolab/utils/18-adjust-kolab-conf.sh b/docker/kolab/utils/18-adjust-kolab-conf.sh index 8a1c9115..8a5275b3 100755 --- a/docker/kolab/utils/18-adjust-kolab-conf.sh +++ b/docker/kolab/utils/18-adjust-kolab-conf.sh @@ -1,24 +1,30 @@ #!/bin/bash . ./settings.sh sed -r -i \ + -e "s/^base_dn.*$/base_dn = ${rootdn}/g" \ -e "s/^domain_base_dn.*$/domain_base_dn = ${domain_base_dn}/g" \ + -e "s/^user_base_dn.*$/user_base_dn = ${hosted_domain_rootdn}/g" \ + -e "s/^kolab_user_base_dn.*$/kolab_user_base_dn = ${hosted_domain_rootdn}/g" \ + -e "s/^group_base_dn.*$/group_base_dn = ${hosted_domain_rootdn}/g" \ + -e "s/^sharedfolder_base_dn.*$/sharedfolder_base_dn = ${hosted_domain_rootdn}/g" \ + -e "s/^resource_base_dn.*$/resource_base_dn = ${hosted_domain_rootdn}/g" \ -e '/^primary_mail/ a\ daemon_rcpt_policy = False' \ -e '/^primary_mail/d' \ -e '/secondary_mail/,+10d' \ -e '/autocreate_folders/,+77d' \ -e "/^\[kolab_wap\]/ a\ mgmt_root_dn = ${rootdn}" \ -e "/^\[kolab_wap\]/ a\ -hosted_root_dn = ${hosted_root_dn}" \ +hosted_root_dn = ${hosted_domain_rootdn}" \ -e "/^\[kolab_wap\]/ a\ -api_url = http://127.0.0.1/kolab-webadmin/api" \ +api_url = http://127.0.0.1:9080/kolab-webadmin/api" \ -e 's/^auth_attributes.*$/auth_attributes = mail, uid/g' \ -e 's|^uri = imaps.*$|uri = imaps://127.0.0.1:11993|g' \ /etc/kolab/kolab.conf service kolabd restart service kolab-saslauthd restart diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index a0069aac..956644fb 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -1,25 +1,25 @@ FROM fedora:35 MAINTAINER Jeroen van Meeuwen ENV container docker RUN dnf -y install \ --setopt 'tsflags=nodocs' \ nginx \ nginx-mod-mail && \ dnf clean all COPY nginx.conf /etc/nginx/nginx.conf ARG APP_WEBSITE_DOMAIN -RUN sed -i -r -e "s|^.*auth_http_header.*$| auth_http_header Host services.$APP_WEBSITE_DOMAIN;|g" /etc/nginx/nginx.conf +RUN sed -i -r -e "s|APP_WEBSITE_DOMAIN|$APP_WEBSITE_DOMAIN|g" /etc/nginx/nginx.conf # Forward request logs to Docker log collector RUN ln -sf /dev/stdout /var/log/nginx/access.log \ && ln -sf /dev/stderr /var/log/nginx/error.log STOPSIGNAL SIGTERM CMD ["nginx", "-g", "daemon off;"] EXPOSE 110/tcp 143/tcp 993/tcp 995/tcp diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf index cc288816..8d61df45 100644 --- a/docker/nginx/nginx.conf +++ b/docker/nginx/nginx.conf @@ -1,73 +1,73 @@ user nginx; worker_processes auto; error_log /var/log/nginx/error.log debug; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } mail { server_name imap.hosted.com; auth_http 127.0.0.1:8000/api/webhooks/nginx; - auth_http_header Host 127.0.0.1; + auth_http_header Host services.APP_WEBSITE_DOMAIN; proxy_pass_error_message on; server { listen 143; protocol imap; proxy on; starttls on; ssl_certificate /etc/pki/tls/certs/imap.hosted.com.cert; ssl_certificate_key /etc/pki/tls/private/imap.hosted.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } server { listen 465 ssl; protocol smtp; proxy on; ssl_certificate /etc/pki/tls/certs/imap.hosted.com.cert; ssl_certificate_key /etc/pki/tls/private/imap.hosted.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } server { listen 587; protocol smtp; proxy on; starttls on; ssl_certificate /etc/pki/tls/certs/imap.hosted.com.cert; ssl_certificate_key /etc/pki/tls/private/imap.hosted.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } server { listen 993 ssl; protocol imap; proxy on; ssl_certificate /etc/pki/tls/certs/imap.hosted.com.cert; ssl_certificate_key /etc/pki/tls/private/imap.hosted.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; } } diff --git a/docker/proxy/Dockerfile b/docker/proxy/Dockerfile index 61281386..3ec5caef 100644 --- a/docker/proxy/Dockerfile +++ b/docker/proxy/Dockerfile @@ -1,46 +1,24 @@ FROM fedora:35 MAINTAINER Jeroen van Meeuwen ENV container docker -ENV SYSTEMD_PAGER='' RUN dnf -y install \ --setopt 'tsflags=nodocs' \ - bash-completion \ - bind-utils \ - certbot \ - curl \ - dhcp-client \ - git \ - iproute \ - iptraf-ng \ - iputils \ - less \ - lsof \ - mtr \ - net-tools \ - NetworkManager \ - NetworkManager-tui \ - network-scripts \ - nginx \ - nmap-ncat \ - openssh-clients \ - openssh-server \ - procps-ng \ - python3-certbot-nginx \ - strace \ - systemd-udev \ - tcpdump \ - telnet \ - traceroute \ - vim-enhanced \ - wget && \ + nginx && \ dnf clean all COPY rootfs/ / +ARG APP_WEBSITE_DOMAIN +RUN sed -i -r -e "s|APP_WEBSITE_DOMAIN|$APP_WEBSITE_DOMAIN|g" /etc/nginx/nginx.conf -RUN systemctl enable nginx +# Forward request logs to Docker log collector +RUN ln -sf /dev/stdout /var/log/nginx/access.log \ + && ln -sf /dev/stderr /var/log/nginx/error.log -CMD ["/lib/systemd/systemd", "--system"] -ENTRYPOINT "/lib/systemd/systemd" +STOPSIGNAL SIGTERM + +CMD ["nginx", "-g", "daemon off;"] + +EXPOSE 80/tcp 443/tcp diff --git a/docker/proxy/rootfs/etc/nginx/nginx.conf b/docker/proxy/rootfs/etc/nginx/nginx.conf index a47cbac3..252dcd80 100644 --- a/docker/proxy/rootfs/etc/nginx/nginx.conf +++ b/docker/proxy/rootfs/etc/nginx/nginx.conf @@ -1,165 +1,165 @@ # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; 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 /var/log/nginx/access.log 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 [::]:443 ssl ipv6only=on; listen 443 ssl; ssl_certificate /etc/letsencrypt/live/$server_name/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$server_name/privkey.pem; - server_name kanarip.internet-box.ch; + 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 http://127.0.0.1:8000; + proxy_pass http://127.0.0.1:8000; 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 /meetmedia { proxy_pass https://127.0.0.1:12443; 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 https://127.0.0.1:12443; 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 /roundcubemail { proxy_pass http://127.0.0.1:9080; 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 /kolab-webadmin { proxy_pass http://127.0.0.1:9080; 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 http://127.0.0.1:9080; 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/(caldav|carddav) { proxy_pass http://127.0.0.1:9080; 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 /iRony { auth_request /auth; #auth_request_set $auth_status $upstream_status; proxy_pass http://127.0.0.1:9080; 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 = /auth { internal; proxy_pass http://127.0.0.1:8000/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; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } }