diff --git a/matrix.yml b/matrix.yml new file mode 100644 index 0000000..e113966 --- /dev/null +++ b/matrix.yml @@ -0,0 +1,436 @@ +--- +- name: matrix + hosts: all + tasks: + + - name: Create /home/docker/matrix.{{inventory_hostname}} dir + ansible.builtin.file: + path: /home/docker/matrix.{{inventory_hostname}} + owner: root + group: docker + state: directory + mode: '0550' + + - name: Gen initial passwords if not exists + ansible.builtin.shell: docker run --rm -v ./data:/data -e SYNAPSE_SERVER_NAME=matrix.{{inventory_hostname}} -e SYNAPSE_HTTP_PORT=8008 -e SYNAPSE_REPORT_STATS=no matrixdotorg/synapse:latest generate + args: + chdir: /home/docker/matrix.{{inventory_hostname}} + creates: /home/docker/matrix.{{inventory_hostname}}/data/homeserver.yaml + + - name: Edit Matrix/Synapse config + blockinfile: + path: /home/docker/matrix.{{inventory_hostname}}/data/homeserver.yaml + create: yes + mode: 0444 + owner: root + group: docker + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + public_baseurl: https://matrix.{{inventory_hostname}}/ + enable_registration: false + max_upload_size: 2048M + retention: + enabled: true + federation_ip_range_blacklist: + - '127.0.0.0/8' + - '10.0.0.0/8' + - '172.16.0.0/12' + - '192.168.0.0/16' + - '100.64.0.0/10' + - '169.254.0.0/16' + - '::1/128' + - 'fe80::/64' + - 'fc00::/7' + #server_notices: + ## system_mxid_localpart: mx-admin + # system_mxid_display_name: "Server Notices" + # system_mxid_avatar_url: "mxc://server.com/xumMIlgDBLYFaPVkEsdrNVLW" + # room_name: "Server Notices" + web_client_location: https://matrix-web.{{inventory_hostname}}/ + trusted_key_servers: + - server_name: "matrix.org" + redis: + enabled: true + host: matrix.{{inventory_hostname}}--redis + port: 6379 + backup: yes + notify: Restart matrix + + - name: /home/docker/matrix.{{inventory_hostname}}/genpw.sh (generate Random PW for Nextcloud and DB) + blockinfile: + path: /home/docker/matrix.{{inventory_hostname}}/genpw.sh + create: yes + mode: 0550 + owner: root + group: docker + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + cd /home/docker/matrix.{{inventory_hostname}} + postgresqluser=$(pwgen -s 32 1) + postgresqlpassword=$(pwgen -s 32 1) + matrixadminpassword=$(pwgen -s 32 1) + + [ -f env ] || echo "POSTGRES_USER=!POSTGRESUSER! + POSTGRES_PASSWORD=!POSTGRESPASSWORD! + MATRIX_ADMIN_PASSWORD=!MATRIX_ADMIN_PASSWORD! + " >env + + + [ -f env.db ] || echo "POSTGRES_USER=!POSTGRESUSER! + POSTGRES_PASSWORD=!POSTGRESPASSWORD! + " >env.db + + chmod 440 env env.db + chown root:docker env env.db + sed -i "s/\!MATRIX_ADMIN_PASSWORD\!/$matrixadminpassword/g" env + sed -i "s/\!POSTGRESUSER\!/$postgresqluser/g" env env.db + sed -i "s/\!POSTGRESPASSWORD\!/$postgresqlpassword/g" env env.db + + if ! grep -q "name: psycopg2" data/homeserver.yaml + then + # Remove sqlite config + sed -i '/database:/,/database: \/data\/homeserver.d/d' data/homeserver.yaml + # add postgres config + echo " + database: + name: psycopg2 + args: + user: $postgresqluser + password: $postgresqlpassword + database: synapse + host: matrix.{{inventory_hostname}}--db + cp_min: 5 + cp_max: 10 + " >>data/homeserver.yaml + fi + backup: yes + validate: /bin/bash -n %s + notify: run genpw.sh + + - name: /home/docker/matrix.{{inventory_hostname}}/genpw.sh shebang + lineinfile: + path: /home/docker/matrix.{{inventory_hostname}}/genpw.sh + insertbefore: BOF + line: "#!/bin/bash -e" + + - name: Gen initial passwords if not exists + ansible.builtin.shell: ./genpw.sh + args: + chdir: /home/docker/matrix.{{inventory_hostname}} + creates: /home/docker/matrix.{{inventory_hostname}}/env + + - name: /home/docker/matrix.{{inventory_hostname}}/turnserver.conf + blockinfile: + path: /home/docker/matrix.{{inventory_hostname}}/turnserver.conf + mode: "0400" + owner: root + group: root + create: yes + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + syslog + listening-port=3478 + fingerprint + use-auth-secret + static-auth-secret= + realm=matrix.{{inventory_hostname}} + total-quota=100 + bps-capacity=0 + stale-nonce + no-multicast-peers + backup: yes + + - name: Element Web configuration + copy: + dest: /home/docker/matrix.{{inventory_hostname}}/element-web-config.json + owner: root + group: root + mode: 0444 + content: | + { + "default_server_config": { + "m.homeserver": { + "base_url": "https://matrix.{{inventory_hostname}}", + "server_name": "matrix.{{inventory_hostname}}" + }, + "m.identity_server": { + "base_url": "https://vector.im" + } + }, + "disable_custom_urls": true, + "disable_guests": true, + "disable_login_language_selector": true, + "disable_3pid_login": true, + "brand": "Element", + "integrations_ui_url": "https://scalar.vector.im/", + "integrations_rest_url": "https://scalar.vector.im/api", + "integrations_widgets_urls": [ + "https://scalar.vector.im/_matrix/integrations/v1", + "https://scalar.vector.im/api", + "https://scalar-staging.vector.im/_matrix/integrations/v1", + "https://scalar-staging.vector.im/api", + "https://scalar-staging.riot.im/scalar/api" + ], + "default_country_code": "DE", + "show_labs_settings": false, + "features": {}, + "default_federate": true, + "default_theme": "dark", + "default_device_display_name" : "Matrix" + "room_directory": { + "servers": ["matrix.{{inventory_hostname}}", "matrix.org"] + }, + "enable_presence_by_hs_url": { + "https://matrix.org": false, + "https://matrix-client.matrix.org": false + }, + "setting_defaults": { + "breadcrumbs": false + }, + "jitsi": { + "preferred_domain": "meet.element.io" + }, + "element_call": { + "url": "https://call.element.io", + "participant_limit": 8, + "brand": "Element Call" + }, + "map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx" + } + backup: yes + + - name: /home/docker/matrix.{{inventory_hostname}}/docker-compose.yml Container Configuration + blockinfile: + path: /home/docker/matrix.{{inventory_hostname}}/docker-compose.yml + create: yes + mode: 0440 + owner: root + group: docker + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + version: '3.6' + services: + matrix.{{inventory_hostname}}: + image: docker.io/matrixdotorg/synapse:latest + restart: unless-stopped + user: 3000:3000 + volumes: + - ./data:/data + - /etc/localtime:/etc/localtime:ro + depends_on: + - matrix.{{inventory_hostname}}--db + networks: + - matrix.{{inventory_hostname}}--network + - traefik + environment: + SYNAPSE_HTTP_PORT: 8008 + SYNAPSE_SERVER_NAME: "matrix.{{inventory_hostname}}" + SYNAPSE_REPORT_STATS: "no" + labels: + - traefik.enable=true + # HTTPS + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}.rule=Host(`matrix.{{ ansible_facts['nodename'] }}`) + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}.entrypoints=https + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}.tls=true + # Proxy to service-port + - traefik.http.services.matrix-{{ ansible_facts['hostname'] }}.loadbalancer.server.port=8008 + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}.service=matrix-{{ ansible_facts['hostname'] }} + # cert via letsencrypt + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}.tls.certresolver=letsencrypt + # Traefik network + - traefik.docker.network=traefik + # activate secHeaders@file and .well.known + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}.middlewares=secHeaders@file + + matrix.{{inventory_hostname}}--db: + image: docker.io/postgres:latest + restart: unless-stopped + volumes: + - ./matrixdb-data:/var/lib/postgresql/data + - /etc/localtime:/etc/localtime:ro + env_file: env.db + environment: + - POSTGRES_INITDB_ARGS=--encoding='UTF8' --lc-collate='C' --lc-ctype='C' + - POSTGRES_DB=synapse + networks: + - matrix.{{inventory_hostname}}--network + + matrix.{{inventory_hostname}}--coturn: + image: coturn/coturn:latest + restart: unless-stopped + volumes: + - /etc/localtime:/etc/localtime:ro + - ./turnserver.conf:/etc/coturn/turnserver.conf + networks: + - matrix.{{inventory_hostname}}--network + - traefik + ports: + - 3479:3478 + - 3479:3478/udp + + matrix.{{inventory_hostname}}--redis: + image: redis:latest + restart: unless-stopped + volumes: + - /etc/localtime:/etc/localtime:ro + networks: + - matrix.{{inventory_hostname}}--network + + matrix.{{inventory_hostname}}--admin: + image: awesometechnologies/synapse-admin:latest + restart: unless-stopped + networks: + - matrix.{{inventory_hostname}}--network + - traefik + environment: + - REACT_APP_SERVER=https://matrix.defiant.dedyn.io + labels: + - traefik.enable=true + # HTTPS + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-admin.rule=Host(`matrix-admin.{{ ansible_facts['nodename'] }}`) + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-admin.entrypoints=https + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-admin.tls=true + # Proxy to service-port + - traefik.http.services.matrix-{{ ansible_facts['hostname'] }}-admin.loadbalancer.server.port=80 + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-admin.service=matrix-{{ ansible_facts['hostname'] }}-admin + # cert via letsencrypt + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-admin.tls.certresolver=letsencrypt + # Traefik network + - traefik.docker.network=traefik + # activate secHeaders@file and .well.known + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-admin.middlewares=secHeaders@file + + + matrix.{{inventory_hostname}}--web: + image: vectorim/element-web:latest + restart: unless-stopped + volumes: + - /etc/localtime:/etc/localtime:ro + - ./element-web-config.json:/app/config.json:ro + networks: + - matrix.{{inventory_hostname}}--network + - traefik + labels: + - traefik.enable=true + # HTTPS + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-web.rule=Host(`matrix-web.{{ ansible_facts['nodename'] }}`) + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-web.entrypoints=https + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-web.tls=true + # Proxy to service-port + - traefik.http.services.matrix-{{ ansible_facts['hostname'] }}-web.loadbalancer.server.port=80 + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-web.service=matrix-{{ ansible_facts['hostname'] }}-web + # cert via letsencrypt + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-web.tls.certresolver=letsencrypt + # Traefik network + - traefik.docker.network=traefik + # activate secHeaders@file and .well.known + - traefik.http.routers.matrix-{{ ansible_facts['hostname'] }}-web.middlewares=secHeaders@file + + networks: + matrix.{{inventory_hostname}}--network: + driver: bridge + driver_opts: + com.docker.network.bridge.name: br-matrix + traefik: + external: true + + backup: yes + notify: Restart matrix + + - name: Start matrix + ansible.builtin.shell: docker-compose up -d + args: + chdir: /home/docker/matrix.{{inventory_hostname}} + creates: /home/docker/matrix.{{inventory_hostname}}/matrixdb-data/postmaster.pid + + - name: Wait until matrix install is finished + wait_for: + path: /home/docker/matrix.{{inventory_hostname}}/matrixdb-data/base + + - name: /home/docker/matrix.{{inventory_hostname}}/matrix.init.sh + blockinfile: + path: /home/docker/matrix.{{inventory_hostname}}/matrix.init.sh + mode: "0500" + owner: root + group: root + create: yes + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + # matrix + sleep 120 + cd /home/docker/matrix.{{inventory_hostname}} || exit 1 + . ./env + docker compose exec matrix.defiant.dedyn.io register_new_matrix_user -c /data/homeserver.yaml -a -u mx-admin -p $MATRIX_ADMIN_PASSWORD http://localhost:8008 >matrix.init.log 2>&1 + backup: yes + validate: /bin/bash -n %s +# notify: run matrix.init + + - name: Run matrix.init after install + ansible.builtin.shell: bash /home/docker/matrix.{{inventory_hostname}}/matrix.init.sh + args: + chdir: /home/docker/matrix.{{inventory_hostname}} + creates: /home/docker/matrix.{{inventory_hostname}}/matrix.init.log + +# - name: /usr/local/sbin/autoupdate.d/matrix.update +# blockinfile: +# path: /usr/local/sbin/autoupdate.d/matrix.update +# mode: "0400" +# owner: root +# group: root +# create: yes +# marker: "# {mark} ANSIBLE MANAGED BLOCK" +# block: | +# # Nextcloud maintenance and app-update +# cd /home/docker/matrix.{{inventory_hostname}} || continue +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ db:add-missing-columns +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ db:add-missing-indices +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ db:add-missing-primary-keys +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ app:update --all +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ dav:sync-birthday-calendar +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ trashbin:cleanup --all-users +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ files:cleanup +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ files:scan --all +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ maps:scan-photos +# docker-compose exec -T -u www-data matrix.{{inventory_hostname}} ./occ db:convert-filecache-bigint -n +# backup: yes +# validate: /bin/bash -n %s +# notify: run matrix.update + + - name: Allow turn for audio/video tcp + community.general.ufw: + rule: allow + port: '3479' + proto: tcp + + - name: Allow turn for audio/video udp + community.general.ufw: + rule: allow + port: '3479' + proto: udp + +# - name: Port 8448 needen by matrix federation +# community.general.ufw: +# rule: allow +# port: '8448' +# proto: tcp + + + + handlers: + - name: run genpw.sh + ansible.builtin.shell: ./genpw.sh + args: + chdir: /home/docker/matrix.{{inventory_hostname}} + notify: Restart matrix + +# - name: run matrix.update +# ansible.builtin.shell: bash /usr/local/sbin/autoupdate.d/matrix.update +# +# - name: run matrix.init +# ansible.builtin.shell: bash /home/docker/matrix.{{inventory_hostname}}/matrix.init.sh + + - name: Restart matrix + ansible.builtin.shell: docker-compose up -d + args: + chdir: /home/docker/matrix.{{inventory_hostname}} +