diff --git a/ansible/.env.local b/ansible/.env.local new file mode 100644 --- /dev/null +++ b/ansible/.env.local @@ -0,0 +1,37 @@ +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= + +SWOOLE_HOT_RELOAD_ENABLE=true +SWOOLE_HTTP_HOST={{ host }} +SWOOLE_HTTP_PORT=8000 +#SWOOLE_HTTP_ACCESS_LOG=true +SWOOLE_HTTP_REACTOR_NUM=8 +SWOOLE_HTTP_WORKER_NUM=32 +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 + +APP_TENANT_ID=42 +APP_PASSPHRASE=simple123 + +MAIL_DRIVER=log diff --git a/ansible/Makefile b/ansible/Makefile new file mode 100644 --- /dev/null +++ b/ansible/Makefile @@ -0,0 +1,9 @@ +OX_API_KEY= +FIREBASE_API_KEY= +HOSTNAME= +PUBLIC_IP= + +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}" setup.yml diff --git a/ansible/README.md b/ansible/README.md new file mode 100644 --- /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 --- /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/hosts b/ansible/hosts new file mode 100644 --- /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 --- /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 --- /dev/null +++ b/ansible/setup.yml @@ -0,0 +1,106 @@ +#!/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: dev/linode + 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 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 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,10 @@ 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 @@ -99,8 +103,10 @@ proxy: build: context: ./docker/proxy/ + args: + APP_WEBSITE_DOMAIN: ${APP_WEBSITE_DOMAIN:?err} container_name: kolab-proxy - hostname: kanarip.internet-box.ch + hostname: ${APP_WEBSITE_DOMAIN:?err} image: kolab-proxy network_mode: host tmpfs: diff --git a/docker/kolab/utils/04-reset-mysql-kolab-password.sh b/docker/kolab/utils/04-reset-mysql-kolab-password.sh --- a/docker/kolab/utils/04-reset-mysql-kolab-password.sh +++ b/docker/kolab/utils/04-reset-mysql-kolab-password.sh @@ -11,5 +11,5 @@ 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 --- a/docker/kolab/utils/05-replace-localhost.sh +++ b/docker/kolab/utils/05-replace-localhost.sh @@ -13,15 +13,17 @@ 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 diff --git a/docker/kolab/utils/07-adjust-base-dns.sh b/docker/kolab/utils/07-adjust-base-dns.sh --- a/docker/kolab/utils/07-adjust-base-dns.sh +++ b/docker/kolab/utils/07-adjust-base-dns.sh @@ -4,6 +4,10 @@ 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\ diff --git a/docker/kolab/utils/10-change-port-numbers.sh b/docker/kolab/utils/10-change-port-numbers.sh --- a/docker/kolab/utils/10-change-port-numbers.sh +++ b/docker/kolab/utils/10-change-port-numbers.sh @@ -19,8 +19,10 @@ 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 -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 diff --git a/docker/kolab/utils/15-create-hosted-domain.sh b/docker/kolab/utils/15-create-hosted-domain.sh --- a/docker/kolab/utils/15-create-hosted-domain.sh +++ b/docker/kolab/utils/15-create-hosted-domain.sh @@ -96,4 +96,15 @@ 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 --- a/docker/kolab/utils/18-adjust-kolab-conf.sh +++ b/docker/kolab/utils/18-adjust-kolab-conf.sh @@ -3,7 +3,13 @@ . ./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' \ @@ -12,9 +18,9 @@ -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 diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -12,7 +12,7 @@ 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 \ diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf --- a/docker/nginx/nginx.conf +++ b/docker/nginx/nginx.conf @@ -13,7 +13,7 @@ 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; diff --git a/docker/proxy/Dockerfile b/docker/proxy/Dockerfile --- a/docker/proxy/Dockerfile +++ b/docker/proxy/Dockerfile @@ -1,46 +1,24 @@ -FROM fedora:31 +FROM fedora:34 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 --- a/docker/proxy/rootfs/etc/nginx/nginx.conf +++ b/docker/proxy/rootfs/etc/nginx/nginx.conf @@ -47,14 +47,14 @@ 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;