diff --git a/matrix.yml b/matrix.yml
new file mode 100644
index 0000000..d662d21
--- /dev/null
+++ b/matrix.yml
@@ -0,0 +1,27 @@
+---
+
+# Infrastructure
+# Ansible instructions to deploy the infrastructure
+# Copyright (C) 2020 Saibotk
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+- hosts: matrix
+ roles:
+ - docker
+ - docker_compose
+ - docker_cleanup
+ - traefik
+ - matrix
+ environment:
+ PYTHONPATH: /opt/python2/ansible-dependencies/lib/python2.7/site-packages
diff --git a/roles/matrix/README.md b/roles/matrix/README.md
new file mode 100644
index 0000000..6719222
--- /dev/null
+++ b/roles/matrix/README.md
@@ -0,0 +1,36 @@
+Matrix
+=========
+
+This will setup a Matrix (Synapse) instance using their official docker container and traefik as a reverse proxy.
+Additionally this will setup an Element Web instance and the required delegation if needed.
+
+Requirements
+------------
+
+You will need to have docker, docker-compose and traefik installed or declared as dependencies with their respective roles.
+
+**This role assumes that you have setup traefik with an endpoint called `websecure`.**
+
+Role Variables
+--------------
+
+**Please look at the [defaults/main.yml](defaults/main.yml) for all available variables and their description.**
+
+**Note: Lines that are commented out via `#` are usually still valid/used variables, but they are not defined by default, so they might enable a feature, when uncommenting/defining them!**
+
+### Global variables, that are used:
+
+- `proxy_network`: Defined by the local traefik installation, this is the shared proxy network used by traefik to reach the containers. (optional)
+- `proxy_hiddenservice`: Defined by the local traefik installation, this is used to generate the alt-svc header for the alternative Tor domain. (optional)
+
+Dependencies
+------------
+
+- docker
+- docker-compose
+- traefik
+
+License
+-------
+
+GPL-3.0-only
diff --git a/roles/matrix/defaults/main.yml b/roles/matrix/defaults/main.yml
new file mode 100644
index 0000000..2923f47
--- /dev/null
+++ b/roles/matrix/defaults/main.yml
@@ -0,0 +1,81 @@
+---
+# Default variables for the matrix role
+
+# Infrastructure
+# Ansible instructions to deploy the infrastructure
+# Copyright (C) 2019-2020 Christoph (Sheogorath) Kern
+# Copyright (C) 2020 Saibotk
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+# The install location
+matrix_install_location: /srv/matrix
+
+# The container data volume mount locations
+matrix_data_location: "{{ matrix_install_location}}/data"
+matrix_database_location: "{{ matrix_install_location}}/database"
+matrix_elementweb_location: "{{ matrix_install_location}}/elementweb"
+
+# The certresolver that is used by traefik for this domain
+matrix_traefik_certresolver: letsencrypt_http
+
+# The domain that traefik will server synapse under
+matrix_synapse_servername: matrix.example.com
+matrix_synapse_domain: "{{ matrix_synapse_servername }}"
+
+# Additional synapse ENV options (keys will automatically be prefixed with SYNAPSE_) see https://github.com/matrix-org/synapse/tree/develop/docker#generating-a-configuration-file
+matrix_synapse_options: []
+
+# The database password to use
+matrix_database_password: "{{ lookup('passwordstore', matrix_synapse_domain + '/db create=true length=42') }}"
+
+# Container versions
+matrix_synapse_version: "1.20.1"
+matrix_database_version: "13.0"
+matrix_delegate_nginx_version: "1.19"
+matrix_elementweb_version: "1.7.7"
+
+# Container tag definitions
+matrix_synapse_image_version: "v{{ matrix_synapse_version }}"
+matrix_database_image_version: "{{ matrix_database_version }}-alpine"
+matrix_delegate_nginx_image_version: "{{ matrix_delegate_nginx_version }}-alpine"
+matrix_elementweb_image_version: "v{{ matrix_elementweb_version }}"
+
+# The domain that traefik will server element-web under
+matrix_elementweb_domain: element.example.com
+
+# The homeserver URL and display name
+matrix_elementweb_base_url: "https://{{ matrix_synapse_domain }}"
+matrix_elementweb_servername: "{{ matrix_synapse_servername }}"
+
+# Should the registration button on welcome page be shown?
+matrix_elementweb_registration_enabled: false
+
+# Controls whether Element shows the presence feature for all (empty list) or specific servers (key = value list with the key being the server url)
+matrix_elementweb_enable_presence_by_hs_url: []
+
+# Should users only be allowed to use this instance with the given matrix server?
+matrix_elementweb_disable_custom_urls: true
+
+# Should Element-Web disable guests? (without sign-in)
+matrix_elementweb_disable_guests: true
+
+# Integration Server URLs to use (see https://github.com/vector-im/element-web/blob/develop/docs/config.md)
+matrix_elementweb_integrations_ui_url: "https://scalar.vector.im/"
+matrix_elementweb_integrations_rest_url: "https://scalar.vector.im/api"
+matrix_elementweb_integrations_widgets_urls: ["https://scalar.vector.im/api"]
+matrix_elementweb_integrations_jitsi_widget_url: "https://scalar.vector.im/api/widgets/jitsi.html"
+
+# Element Web public room directory server(s)
+matrix_elementweb_roomdir_servers: ['matrix.org']
diff --git a/roles/matrix/handlers/main.yml b/roles/matrix/handlers/main.yml
new file mode 100644
index 0000000..d0278b2
--- /dev/null
+++ b/roles/matrix/handlers/main.yml
@@ -0,0 +1,31 @@
+---
+# Handlers file for the matrix role
+
+# Infrastructure
+# Ansible instructions to deploy the infrastructure
+# Copyright (C) 2019-2020 Alexander (w4tsn) Wellbrock
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+- name: restart matrix delegate nginx
+ docker_compose:
+ services:
+ - delegate
+ state: present
+ project_src: "{{ matrix_install_location }}"
+ restarted: yes
+ tags:
+ - docker
+ - matrix
+ become: true
diff --git a/roles/matrix/tasks/main.yml b/roles/matrix/tasks/main.yml
new file mode 100644
index 0000000..9eeff18
--- /dev/null
+++ b/roles/matrix/tasks/main.yml
@@ -0,0 +1,140 @@
+---
+# Tasks file for the matrix role
+
+# Infrastructure
+# Ansible instructions to deploy the infrastructure
+# Copyright (C) 2019-2020 Christoph (Sheogorath) Kern
+# Copyright (C) 2019-2020 Alexander (w4tsn) Wellbrock
+# Copyright (C) 2020 Saibotk
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+- name: Update default SELinux contexts
+ sefcontext:
+ target: '{{ item }}(/.*)?'
+ setype: "container_file_t"
+ state: present
+ with_items:
+ - "{{ matrix_database_location }}"
+ - "{{ matrix_data_location }}"
+ - "{{ matrix_elementweb_location }}"
+ become: true
+
+- name: Create install directory
+ file:
+ path: "{{ item }}"
+ state: directory
+ mode: '0700'
+ owner: 'root'
+ group: 'root'
+ with_items:
+ - "{{ matrix_install_location }}"
+ become: true
+
+- name: Create data directory
+ file: # noqa 208 # Container manages permissions on its own
+ path: "{{ item }}"
+ state: directory
+ setype: "container_file_t"
+ with_items:
+ - "{{ matrix_database_location }}"
+ - "{{ matrix_data_location }}"
+ - "{{ matrix_elementweb_location }}"
+ become: true
+
+- name: Deploy docker-compose.yml
+ template:
+ src: "docker-compose.yml"
+ dest: "{{ matrix_install_location }}/docker-compose.yml"
+ mode: '0600'
+ owner: 'root'
+ group: 'root'
+ validate: python2 -m compose -f %s config -q
+ tags:
+ - matrix
+ become: true
+
+- name: Deploy delegation config files
+ template:
+ src: "{{ item }}"
+ dest: "{{ matrix_install_location }}/{{ item }}"
+ setype: "container_file_t"
+ mode: 0644
+ owner: 'root'
+ group: 'root'
+ with_items:
+ - "server-delegation.json"
+ - "client-delegation.json"
+ tags:
+ - docker
+ - matrix
+ become: true
+
+- name: Deploy nginx delegate config
+ template:
+ src: "delegate-nginx.conf"
+ dest: "{{ matrix_install_location }}/nginx.conf"
+ setype: "container_file_t"
+ mode: 0600
+ owner: 'root'
+ group: 'root'
+ tags:
+ - docker
+ - matrix
+ notify: restart matrix delegate nginx
+ become: true
+
+- name: Deploy Element-Web config files
+ template:
+ src: "elementweb-config.json"
+ dest: "{{ matrix_elementweb_location }}/config.json"
+ setype: "container_file_t"
+ mode: '0644'
+ owner: '991'
+ group: '991'
+ tags:
+ - docker
+ - matrix
+ become: true
+
+- name: Check if homeserver.yaml (config) exists
+ stat: path="{{ matrix_data_location }}/homeserver.yaml"
+ register: matrix_synapse_homeserver_yaml
+ tags:
+ - docker
+ - matrix
+ become: true
+
+- name: Generate synapse config
+ command: 'python2 -m compose run -e "SYNAPSE_SERVER_NAME={{ matrix_synapse_servername }}" synapse generate'
+ args:
+ chdir: "{{ matrix_install_location }}"
+ creates: "{{ matrix_data_location }}/homeserver.yaml"
+ tags:
+ - docker
+ - matrix
+ become: true
+ when:
+ - not matrix_synapse_homeserver_yaml.stat.exists
+
+- name: Compose matrix
+ docker_compose:
+ state: present
+ project_src: "{{ matrix_install_location }}"
+ pull: yes
+ remove_orphans: yes
+ tags:
+ - docker
+ - matrix
+ become: true
diff --git a/roles/matrix/templates/client-delegation.json b/roles/matrix/templates/client-delegation.json
new file mode 100644
index 0000000..b88c12f
--- /dev/null
+++ b/roles/matrix/templates/client-delegation.json
@@ -0,0 +1,5 @@
+{
+ "m.homeserver": {
+ "base_url": "https://{{ matrix_synapse_domain }}"
+ }
+ }
diff --git a/roles/matrix/templates/delegate-nginx.conf b/roles/matrix/templates/delegate-nginx.conf
new file mode 100644
index 0000000..bdcc2dd
--- /dev/null
+++ b/roles/matrix/templates/delegate-nginx.conf
@@ -0,0 +1,74 @@
+{{ ansible_managed | comment }}
+
+# From https://git.shivering-isles.com/w4tsn/infrastructure/-/blob/2d8d03a025b833e11533fa8610cc77cff7a59bb9/roles/matrix/templates/delegate-nginx.conf.j2
+
+# Infrastructure
+# Ansible instructions to deploy the infrastructure
+# Copyright (C) 2019-2020 Alexander (w4tsn) Wellbrock
+# Copyright (C) 2020 Saibotk
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+worker_processes 1;
+
+error_log stderr;
+
+pid /tmp/nginx.pid;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ access_log off;
+
+ # Turn off the bloody buffering to temp files
+ proxy_buffering off;
+
+ sendfile on;
+ keepalive_timeout 120;
+
+ gzip on;
+ gzip_types text/plain application/json;
+
+ server_names_hash_bucket_size 128;
+
+ # These two should be the same or nginx will start writing
+ # large request bodies to temp files
+ client_body_buffer_size 10m;
+ client_max_body_size 10m;
+
+ server {
+ listen 80;
+ server_name localhost;
+ server_tokens off;
+ set_real_ip_from 10.0.0.0/8;
+ set_real_ip_from 172.16.0.0/12;
+
+ location /.well-known/matrix {
+ root /usr/share/nginx/html;
+ {#
+ A somewhat long expires value is used to prevent outages
+ in case this is unreachable due to network failure or
+ due to the base domain's server completely dying.
+ #}
+ expires 4h;
+ default_type application/json;
+ add_header Access-Control-Allow-Origin *;
+ }
+ }
+}
diff --git a/roles/matrix/templates/docker-compose.yml b/roles/matrix/templates/docker-compose.yml
new file mode 100644
index 0000000..2a82bc8
--- /dev/null
+++ b/roles/matrix/templates/docker-compose.yml
@@ -0,0 +1,173 @@
+---
+# Infrastructure
+# Ansible instructions to deploy the infrastructure
+# Copyright (C) 2019-2020 Christoph (Sheogorath) Kern
+# Copyright (C) 2019-2020 Alexander (w4tsn) Wellbrock
+# Copyright (C) 2020 Saibotk
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+version: '2'
+services:
+ synapse:
+ image: docker.io/matrixdotorg/synapse:{{ matrix_synapse_image_version }}
+ cpu_shares: 256
+ mem_limit: 1280mb
+ memswap_limit: 1536mb
+ read_only: true
+ restart: always
+ security_opt:
+ - no-new-privileges
+ tmpfs:
+ - "/tmp:size=64M"
+ - "/compiled:size=128K"
+ environment:
+{% for key, value in matrix_synapse_options.items() %}
+ - "SYNAPSE_{{ key }}={{ value }}"
+{% endfor %}
+
+ - "POSTGRES_HOST=database"
+ - "POSTGRES_PASSWORD={{ matrix_database_password }}"
+ volumes:
+ - "{{ matrix_data_location }}:/data"
+ depends_on:
+ - database
+ labels:
+ - "traefik.http.routers.matrix.rule=Host(`{{ matrix_synapse_servername }}`) && PathPrefix(`/_matrix/federation`) || Host(`{{ matrix_synapse_domain }}`) && PathPrefix(`/`)"
+ - "traefik.http.routers.matrix.entrypoints=websecure"
+ - "traefik.http.routers.matrix.tls.certresolver={{ matrix_traefik_certresolver }}"
+ - "traefik.http.routers.matrix.middlewares=matrix,compress"
+ - "traefik.http.routers.matrix.service=matrix"
+ - "traefik.http.services.matrix.loadbalancer.server.port=8008"
+ - "traefik.http.middlewares.matrix.headers.sslredirect=true"
+ - "traefik.http.middlewares.matrix.headers.stsSeconds=63072000"
+ - "traefik.http.middlewares.matrix.headers.referrerPolicy=no-referrer"
+
+ - "traefik.enable=true"
+{% if proxy_network is defined %}
+ - "traefik.docker.network={{ proxy_network }}"
+{% endif %}
+{% if proxy_hiddenservice is defined and proxy_hiddenservice.content is defined %}
+ - "traefik.http.middlewares.matrix.headers.customresponseheaders.alt-svc=h2={{ proxy_hiddenservice['content'] | b64decode | trim }}:443; ma=2592000"
+{% endif %}
+
+ networks:
+ database:
+{% if proxy_network is defined %}
+ {{ proxy_network }}:
+{% endif %}
+
+ database:
+ image: docker.io/postgres:{{ matrix_database_image_version }}
+ mem_limit: 512mb
+ memswap_limit: 768mb
+ read_only: true
+ security_opt:
+ - no-new-privileges
+ tmpfs:
+ - /run/postgresql:size=512K
+ - /tmp:size=128K
+ stop_grace_period: 2m
+ stop_signal: SIGINT
+ environment:
+ - "POSTGRES_USER=synapse"
+ - "POSTGRES_PASSWORD={{ matrix_database_password }}"
+ - "POSTGRES_INITDB_ARGS=--lc-collate C --lc-ctype C --encoding UTF8"
+ volumes:
+ - "{{ matrix_database_location }}:/var/lib/postgresql/data"
+ networks:
+ database:
+ restart: always
+
+ delegate:
+ image: docker.io/nginx:{{ matrix_delegate_nginx_image_version }}
+ mem_limit: 256mb
+ memswap_limit: 512mb
+ read_only: true
+ tmpfs:
+ - "/var/cache/nginx:size=10M"
+ - "/run/nginx:size=512K"
+ - "/tmp:size=128K"
+ security_opt:
+ - no-new-privileges
+ volumes:
+ - "{{ matrix_install_location }}/server-delegation.json:/usr/share/nginx/html/.well-known/matrix/server:ro"
+ - "{{ matrix_install_location }}/client-delegation.json:/usr/share/nginx/html/.well-known/matrix/client:ro"
+ - "{{ matrix_install_location }}/nginx.conf:/etc/nginx/nginx.conf:ro"
+ labels:
+ - "traefik.enable=true"
+
+ - "traefik.http.routers.matrix-delegate.rule=Host(`{{ matrix_synapse_servername }}`) && PathPrefix(`/.well-known/matrix`)"
+ - "traefik.http.routers.matrix-delegate.entrypoints=websecure"
+ - "traefik.http.routers.matrix-delegate.tls.certresolver={{ matrix_traefik_certresolver }}"
+ - "traefik.http.routers.matrix-delegate.middlewares=matrix-delegate,compress"
+ - "traefik.http.middlewares.matrix-delegate.headers.sslredirect=true"
+ - "traefik.http.middlewares.matrix-delegate.headers.stsSeconds=63072000"
+ - "traefik.http.middlewares.matrix-delegate.headers.referrerPolicy=no-referrer"
+
+{% if proxy_network is defined %}
+ - "traefik.docker.network={{ proxy_network }}"
+{% endif %}
+{% if proxy_hiddenservice['content'] is defined %}
+ - "traefik.http.middlewares.matrix-delegate.headers.customresponseheaders.alt-svc:h2={{ proxy_hiddenservice['content'] | b64decode | trim }}:443; ma=2592000"
+{% endif %}
+ restart: always
+{% if proxy_network is defined %}
+ networks:
+ {{ proxy_network }}:
+{% endif %}
+
+ elementweb:
+ image: docker.io/vectorim/riot-web:{{ matrix_elementweb_image_version }}
+ mem_limit: 512mb
+ memswap_limit: 768mb
+ read_only: true
+ security_opt:
+ - no-new-privileges
+ tmpfs:
+ - "/var/cache/nginx:size=10M"
+ - "/run:size=512K"
+ - "/tmp:rw,noexec,nosuid,size=10M"
+ labels:
+ - "traefik.enable=true"
+
+ - "traefik.http.routers.matrix-elementweb.rule=Host(`{{ matrix_elementweb_domain }}`) && PathPrefix(`/`)"
+ - "traefik.http.routers.matrix-elementweb.entrypoints=websecure"
+ - "traefik.http.routers.matrix-elementweb.tls.certresolver={{ matrix_traefik_certresolver }}"
+ - "traefik.http.routers.matrix-elementweb.middlewares=matrix-elementweb,compress"
+ - "traefik.http.middlewares.matrix-elementweb.headers.sslredirect=true"
+ - "traefik.http.middlewares.matrix-elementweb.headers.stsSeconds=63072000"
+ - "traefik.http.middlewares.matrix-elementweb.headers.referrerPolicy=no-referrer"
+
+{% if proxy_network is defined %}
+ - "traefik.docker.network={{ proxy_network }}"
+{% endif %}
+{% if proxy_hiddenservice['content'] is defined %}
+ - "traefik.http.middlewares.matrix-elementweb.headers.customresponseheaders.alt-svc:h2={{ proxy_hiddenservice['content'] | b64decode | trim }}:443; ma=2592000"
+{% endif %}
+ volumes:
+ - "{{ matrix_elementweb_location }}/config.json:/app/config.json:ro"
+{% if proxy_network is defined %}
+ networks:
+ {{ proxy_network }}:
+{% endif %}
+ restart: always
+
+networks:
+ database:
+ internal: true
+{% if proxy_network is defined %}
+ {{ proxy_network }}:
+ external: true
+{% endif %}
diff --git a/roles/matrix/templates/elementweb-config.json b/roles/matrix/templates/elementweb-config.json
new file mode 100644
index 0000000..c7f136d
--- /dev/null
+++ b/roles/matrix/templates/elementweb-config.json
@@ -0,0 +1,22 @@
+{
+ "default_server_config": {
+ "m.homeserver": {
+ "base_url": {{ matrix_elementweb_base_url | string | to_json }},
+ "server_name": {{ matrix_elementweb_servername | string | to_json }}
+ }
+ },
+ "disable_custom_urls": {{ matrix_elementweb_disable_custom_urls | to_json }},
+ "disable_guests": {{ matrix_elementweb_disable_guests | to_json }},
+ "integrations_ui_url": {{ matrix_elementweb_integrations_ui_url | string | to_json }},
+ "integrations_rest_url": {{ matrix_elementweb_integrations_rest_url | string | to_json }},
+ "integrations_widgets_urls": {{ matrix_elementweb_integrations_widgets_urls | to_json }},
+ "integrations_jitsi_widget_url": {{ matrix_elementweb_integrations_jitsi_widget_url | string | to_json }},
+ "bug_report_endpoint_url": "https://element.io/bugreports/submit",
+ "enableLabs": true,
+{% if matrix_elementweb_enable_presence_by_hs_url %}
+ "enable_presence_by_hs_url": {{ matrix_elementweb_enable_presence_by_hs_url | to_json }},
+{% endif %}
+ "roomDirectory": {
+ "servers": {{ matrix_elementweb_roomdir_servers | to_json }}
+ }
+}
diff --git a/roles/matrix/templates/server-delegation.json b/roles/matrix/templates/server-delegation.json
new file mode 100644
index 0000000..3163298
--- /dev/null
+++ b/roles/matrix/templates/server-delegation.json
@@ -0,0 +1,3 @@
+{
+ "m.server": "{{ matrix_synapse_domain }}:443"
+}