This commit is contained in:
Backslash 2024-10-23 16:14:39 +03:00 committed by GitHub
commit ee4762bd8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 1371 additions and 0 deletions

View File

@ -0,0 +1,71 @@
# Setting up Element Call (optional)
The playbook can install and configure [Element Call](https://github.com/vector-im/element-call) for you.
Element Call is a WebRTC-based video and voice calling platform that integrates with Matrix clients such as Element Web. It provides secure, decentralized communication with support for video calls, audio calls, and screen sharing.
See the project's [documentation](https://github.com/vector-im/element-call) to learn more.
## Decide on a domain and path
By default, Element Call is configured to be served on the Matrix domain (`call.DOMAIN`, controlled by the `matrix_element_call_hostname` variable).
This makes it easy to set it up, **without** having to adjust your DNS records manually.
If you'd like to run Element Call on another hostname or path, use the `matrix_element_call_hostname` and `matrix_element_call_path_prefix` variables.
## Adjusting DNS records
If you've changed the default hostname, **you may need to adjust your DNS** records accordingly to point to the correct server.
Ensure that the following DNS names have a public IP/FQDN:
- `call.DOMAIN`
- `sfu.DOMAIN`
- `sfu-jwt.DOMAIN`
## Adjusting the playbook configuration
NOTE: Element call is dependent on two other services for it to function as intended. In orter to utilise Element Call you need to also enable the [JWT Service](configuring-playbook-jwt-service.md) and [Livekit Server](configuring-playbook-livekit-server.md).
Add the following configuration to your `inventory/host_vars/matrix.DOMAIN/vars.yml` file:
```yaml
# Enable dependent services
keydb_enabled: true
matrix_element_call_enabled: true
matrix_livekit_server_enabled: true
matrix_jwt_service_enabled: true
# Set a secure key for LiveKit authentication
matrix_livekit_server_dev_key: 'your-secure-livekit-key'
```
## Installing
After potentially adjusting DNS records and configuring the playbook, run the installation command again:
```yaml
ansible-playbook -i inventory setup.yml
```
## Usage
Once installed, Element Call integrates seamlessly with Matrix clients like Element Web. When the Element Call service is installed, the `/.well-known/matrix/client` file is also updated. A new `org.matrix.msc4143.rtc_foci` section is added to point to your JWT service URL (e.g., `https://sfu-jwt.DOMAIN`).
Additionally, the `/.well-known/element/element.json` file is created to help Element clients discover the Element Call URL (e.g., `https://call.DOMAIN`).
## Required Firewall and Port Forwarding Rules
To ensure the services function correctly, the following firewall rules and port forwarding settings are required:
LiveKit:
• Forward UDP ports 50100:50200 to the Docker instance running LiveKit.
• Forward TCP port 7881 to the Docker instance running LiveKit.
Element Call:
• Forward TCP port 443 to the server running Traefik (for Element Call).
Ensure these ports are open and forwarded appropriately to allow traffic to flow correctly between the services.
## Additional Information
Refer to the Element Call documentation for more details on configuring and using Element Call.

View File

@ -0,0 +1,45 @@
# Setting up JWT Service (optional)
The playbook can install and configure [JWT Service](https://github.com/element-hq/lk-jwt-service) for you.
LK-JWT-Service is currently used for a single reason: generate JWT tokens with a given identity for a given room, so that users can use them to authenticate against LiveKit SFU.
See the project's [documentation](https://github.com/element-hq/lk-jwt-service/) to learn more.
## Decide on a domain and path
By default, JWT Service is configured to be served on the Matrix domain (`sfu-jwt.DOMAIN`, controlled by the `matrix_jwt-service_hostname` variable).
This makes it easy to set it up, **without** having to adjust your DNS records manually.
If you'd like to run JWT Service on another hostname or path, use the `matrix_jwt-service_hostname` variable.
## Adjusting DNS records
If you've changed the default hostname, **you may need to adjust your DNS** records accordingly to point to the correct server.
Ensure that the following DNS names have a public IP/FQDN:
- `sfu-jwt.DOMAIN`
## Adjusting the playbook configuration
Add the following configuration to your `inventory/host_vars/matrix.DOMAIN/vars.yml` file:
```yaml
matrix_jwt_service_enabled: true
# Set a secure key for LiveKit authentication
matrix_element_call_livekit_dev_key: 'your-secure-livekit-key'
```
## Installing
After potentially adjusting DNS records and configuring the playbook, run the installation command again:
```yaml
ansible-playbook -i inventory setup.yml
```
## Usage
Once installed, a new `org.matrix.msc4143.rtc_foci` section is added to the element web client to point to your JWT service URL (e.g., `https://sfu-jwt.DOMAIN`).
## Additional Information
Refer to the JWT-Service documentation for more details on configuring and using JWT Service.

View File

@ -0,0 +1,56 @@
# Setting up Livekit (optional)
The playbook can install and configure [Livekit](https://github.com/livekit/livekit) for you.
LiveKit is an open source project that provides scalable, multi-user conferencing based on WebRTC. It's designed to provide everything you need to build real-time video audio data capabilities in your applications.
See the project's [documentation](https://github.com/livekit/livekit) to learn more.
## Decide on a domain and path
By default, Livekit is configured to be served on the Matrix domain (`sfu.DOMAIN`, controlled by the `matrix_livekit_server_hostname` variable).
This makes it easy to set it up, **without** having to adjust your DNS records manually.
If you'd like to run Livekit on another hostname or path, use the `matrix_livekit_server_hostname` variable.
## Adjusting DNS records
If you've changed the default hostname, **you may need to adjust your DNS** records accordingly to point to the correct server.
Ensure that the following DNS names have a public IP/FQDN:
- `sfu.DOMAIN`
## Adjusting the playbook configuration
Add the following configuration to your `inventory/host_vars/matrix.DOMAIN/vars.yml` file:
```yaml
matrix_livekit_server_enabled: true
# Set a secure key for LiveKit authentication
matrix_element_call_livekit_dev_key: 'your-secure-livekit-key'
```
## Installing
After potentially adjusting DNS records and configuring the playbook, run the installation command again:
```yaml
ansible-playbook -i inventory setup.yml
```
## Usage
Once installed, and in conjunction with Element Call and JWT Service, Livekit will become the WebRTC backend for all Element client calls.
## Required Firewall and Port Forwarding Rules
To ensure the services function correctly, the following firewall rules and port forwarding settings are required:
LiveKit:
• Forward UDP ports 50100:50200 to the Docker instance running LiveKit.
• Forward TCP port 7881 to the Docker instance running LiveKit.
Ensure these ports are open and forwarded appropriately to allow traffic to flow correctly between the services.
## Additional Information
Refer to the Livekit documentation for more details on configuring and using Livekit.

View File

@ -235,3 +235,9 @@ When you're done with all the configuration you'd like to do, continue with [Ins
- [Setting up the Rageshake bug report server](configuring-playbook-rageshake.md) (optional)
- [Setting up Prometheus Alertmanager integration via matrix-alertmanager-receiver](configuring-playbook-alertmanager-receiver.md) (optional)
- [Setting up the Element Call server](configuring-playbook-element-call.md) (optional)
- [Setting up the JWT Service](configuring-playbook-jwt-service.md) (optional)
- [Setting up the Livekit server](configuring-playbook-livekit-server.md) (optional)

View File

@ -435,6 +435,12 @@ devture_systemd_service_manager_services_list_auto: |
+
([{'name': 'matrix-pantalaimon.service', 'priority': 4000, 'groups': ['matrix', 'pantalaimon']}] if matrix_pantalaimon_enabled else [])
+
([{'name': 'matrix-element-call.service', 'priority': 4000, 'groups': ['matrix', 'element-call']}] if matrix_element_call_enabled else [])
+
([{'name': 'matrix-jwt-service.service', 'priority': 3000, 'groups': ['matrix', 'jwt-service']}] if matrix_jwt_service_enabled else [])
+
([{'name': 'matrix-livekit-server.service', 'priority': 3000, 'groups': ['matrix', 'livekit-server']}] if matrix_livekit_server_enabled else [])
+
([{'name': 'matrix-registration.service', 'priority': 4000, 'groups': ['matrix', 'registration', 'matrix-registration']}] if matrix_registration_enabled else [])
+
([{'name': 'matrix-sliding-sync.service', 'priority': 1500, 'groups': ['matrix', 'sliding-sync']}] if matrix_sliding_sync_enabled else [])
@ -5989,3 +5995,110 @@ traefik_certs_dumper_ssl_dir_path: "{{ traefik_ssl_dir_path if traefik_enabled e
# /traefik_certs_dumper #
# #
########################################################################
########################################################################
# #
# matrix-element-call #
# #
########################################################################
# Matrix Element Call Configuration
matrix_element_call_enabled: false # Default is false; should be enabled in host_vars as needed
matrix_element_call_version: "latest" # Default version; can be overridden in host_vars
matrix_element_call_scheme: "https" # Scheme for Element Call (e.g., https)
matrix_element_call_hostname: "call.{{ matrix_domain }}" # Default hostname; should be overridden in host_vars if different
matrix_element_call_path_prefix: "/" # Path prefix for Element Call
matrix_element_call_base_path: "{{ matrix_base_data_path }}/element-call" # Base path for storing Element Call-related files
matrix_element_call_container_image: "ghcr.io/element-hq/element-call:{{ matrix_element_call_version }}"
matrix_element_call_container_image_name_prefix: ghcr.io/
matrix_element_call_container_image_registry_prefix: ghcr.io/
matrix_element_call_container_image_force_pull: true
# Docker network configuration for Element Call
matrix_element_call_container_network: "{{ matrix_addons_container_network }}"
matrix_element_call_container_additional_networks: "{{ [matrix_playbook_reverse_proxyable_services_additional_network] if (matrix_element_call_container_labels_traefik_enabled and matrix_playbook_reverse_proxyable_services_additional_network) else [] }}"
# Traefik Configuration for Element Call
matrix_element_call_container_labels_traefik_enabled: "{{ matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] }}"
matrix_element_call_container_labels_traefik_docker_network: "{{ matrix_playbook_reverse_proxyable_services_additional_network }}"
matrix_element_call_container_labels_traefik_entrypoints: "{{ traefik_entrypoint_primary }}"
matrix_element_call_container_labels_traefik_tls_certResolver: "{{ traefik_certResolver_primary }}"
########################################################################
# #
# /matrix-element-call #
# #
########################################################################
########################################################################
# #
# matrix-livekit-server #
# #
########################################################################
# Matrix Livekit Server Configuration
matrix_livekit_server_enabled: false # Default is false; should be enabled in host_vars as needed
matrix_livekit_server_version: "latest" # Default version; can be overridden in host_vars
matrix_livekit_server_scheme: "https"
matrix_livekit_server_hostname: "sfu.{{ matrix_domain }}" # Default hostname; should be overridden in host_vars if different
matrix_livekit_server_path_prefix: "/"
matrix_livekit_server_base_path: "{{ matrix_base_data_path }}/livekit-server"
matrix_livekit_server_container_image: "livekit/livekit-server:{{ matrix_livekit_server_version }}"
matrix_livekit_server_container_image_force_pull: true
# Docker network configuration for Livekit
matrix_livekit_server_container_network: "{{ matrix_addons_container_network }}"
matrix_livekit_server_container_additional_networks: "{{ [matrix_playbook_reverse_proxyable_services_additional_network] if (matrix_livekit_server_container_labels_traefik_enabled and matrix_playbook_reverse_proxyable_services_additional_network) else [] }}"
# Traefik Configuration for Livekit
matrix_livekit_container_labels_traefik_enabled: "{{ matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] }}"
matrix_livekit_container_labels_traefik_docker_network: "{{ matrix_playbook_reverse_proxyable_services_additional_network }}"
matrix_livekit_server_container_labels_traefik_entrypoints: "{{ traefik_entrypoint_primary }}"
matrix_livekit_server_container_labels_traefik_tls_certResolver: "{{ traefik_certResolver_primary }}"
# LiveKit Service Configuration
matrix_livekit_server_livekit_dev_key: "{{ matrix_livekit_server_dev_key }}" # LiveKit dev key
########################################################################
# #
# /matrix-livekit-server #
# #
########################################################################
########################################################################
# #
# matrix-jwt-service #
# #
########################################################################
# Matrix JWT Service Configuration
matrix_jwt_service_enabled: false # Default is false; should be enabled in host_vars as needed
matrix_jwt_service_version: "latest-ci" # Default version; can be overridden in host_vars
matrix_jwt_service_scheme: "https" # Scheme for Element Call (e.g., https)
matrix_jwt_service_hostname: "sfu-jwt.{{ matrix_domain }}" # Default hostname; should be overridden in host_vars if different
matrix_jwt_service_path_prefix: "/" # Path prefix for Element Call
matrix_jwt_service_base_path: "{{ matrix_base_data_path }}/matrix-jwt-service" # Base path for storing Element Call-related files
matrix_jwt_service_container_image: "ghcr.io/element-hq/lk-jwt-service:{{ matrix_jwt_service_version }}"
matrix_jwt_service_container_image_name_prefix: ghcr.io/
matrix_jwt_service_container_image_registry_prefix: ghcr.io/
matrix_jwt_service_container_image_force_pull: true
# Docker network configuration for JWT Service
matrix_jwt_service_container_network: "{{ matrix_addons_container_network }}"
matrix_jwt_service_container_additional_networks: "{{ [matrix_playbook_reverse_proxyable_services_additional_network] if (matrix_jwt_service_container_labels_traefik_enabled and matrix_playbook_reverse_proxyable_services_additional_network) else [] }}"
# Traefik Configuration for JWT Service
matrix_jwt_service_container_labels_traefik_enabled: "{{ matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] }}"
matrix_jwt_service_container_labels_traefik_docker_network: "{{ matrix_playbook_reverse_proxyable_services_additional_network }}"
matrix_jwt_service_container_labels_traefik_entrypoints: "{{ traefik_entrypoint_primary }}"
matrix_jwt_service_container_labels_traefik_tls_certResolver: "{{ traefik_certResolver_primary }}"
# JWT Service Configuration
matrix_jwt_service_url: "https://sfu-jwt.{{ matrix_domain }}" # Default JWT service URL; adjust as needed
########################################################################
# #
# /matrix-jwt-service #
# #
########################################################################

View File

@ -0,0 +1,125 @@
---
# Enable or disable matrix-element-call deployment
matrix_element_call_enabled: false
# Base path configuration
matrix_element_call_base_path: "{{ matrix_base_data_path }}/element-call"
matrix_homeserver_config_path: "{{ matrix_base_data_path }}/synapse/config/homeserver.yaml"
element_web_config_path: "{{ matrix_base_data_path }}/client-element/config.json"
# Docker network configuration
matrix_element_call_container_network: ''
matrix_element_call_container_http_host_bind_port: ''
matrix_element_call_container_additional_networks: [] # No additional networks by default
# Docker images
matrix_element_call_image: "ghcr.io/element-hq/element-call:latest"
# Ports
matrix_element_call_port: "8093"
# Well-known paths and domains (derived from matrix_domain)
matrix_element_call_domain: "call.{{ matrix_domain }}"
matrix_element_call_well_known_client_path: "{{ matrix_base_data_path }}/static-files/public/.well-known/matrix/client"
matrix_element_call_well_known_element_path: "{{ matrix_base_data_path }}/static-files/public/.well-known/element/element.json"
matrix_element_call_base_url: "https://{{ matrix_element_call_domain }}"
# Traefik Configuration for Element Call
matrix_element_call_container_labels_traefik_enabled: true
matrix_element_call_container_labels_traefik_docker_network: "{{ matrix_element_call_container_network }}"
matrix_element_call_container_labels_traefik_hostname: "{{ matrix_element_call_domain }}"
# The path prefix must either be `/` or not end with a slash (e.g. `/element`).
matrix_element_call_container_labels_traefik_path_prefix: "{{ matrix_element_call_path_prefix }}"
matrix_element_call_container_labels_traefik_rule: "Host(`{{ matrix_element_call_container_labels_traefik_hostname }}`){% if matrix_element_call_container_labels_traefik_path_prefix != '/' %} && PathPrefix(`{{ matrix_element_call_container_labels_traefik_path_prefix }}`){% endif %}"
matrix_element_call_container_labels_traefik_priority: 0
matrix_element_call_container_labels_traefik_entrypoints: web-secure
matrix_element_call_container_labels_traefik_tls: "{{ matrix_element_call_container_labels_traefik_entrypoints != 'web' }}"
matrix_element_call_container_labels_traefik_tls_certResolver: default # noqa var-naming
# Controls which additional headers to attach to all HTTP responses.
# To add your own headers, use `matrix_element_call_container_labels_traefik_additional_response_headers_custom`
matrix_element_call_container_labels_traefik_additional_response_headers: "{{ matrix_element_call_container_labels_traefik_additional_response_headers_auto | combine(matrix_element_call_container_labels_traefik_additional_response_headers_custom) }}"
matrix_element_call_container_labels_traefik_additional_response_headers_auto: |
{{
{}
| combine ({'X-XSS-Protection': matrix_element_call_http_header_xss_protection} if matrix_element_call_http_header_xss_protection else {})
| combine ({'X-Frame-Options': matrix_element_call_http_header_frame_options} if matrix_element_call_http_header_frame_options else {})
| combine ({'X-Content-Type-Options': matrix_element_call_http_header_content_type_options} if matrix_element_call_http_header_content_type_options else {})
| combine ({'Content-Security-Policy': matrix_element_call_http_header_content_security_policy} if matrix_element_call_http_header_content_security_policy else {})
| combine ({'Permission-Policy': matrix_element_call_http_header_content_permission_policy} if matrix_element_call_http_header_content_permission_policy else {})
| combine ({'Strict-Transport-Security': matrix_element_call_http_header_strict_transport_security} if matrix_element_call_http_header_strict_transport_security and matrix_element_call_container_labels_traefik_tls else {})
}}
matrix_element_call_container_labels_traefik_additional_response_headers_custom: {}
# matrix_client_element_container_labels_additional_labels contains a multiline string with additional labels to add to the container label file.
# See `../templates/labels.j2` for details.
#
# Example:
# matrix_client_element_container_labels_additional_labels: |
# my.label=1
# another.label="here"
matrix_element_call_container_labels_additional_labels: ''
# A list of extra arguments to pass to the container
matrix_element_call_container_extra_arguments: []
# Additional environment variables for the container
matrix_element_call_environment_variables_additional: {}
# List of systemd services that matrix-element-call.service depends on
matrix_element_call_systemd_required_services_list: "{{ [devture_systemd_docker_base_docker_service_name] if devture_systemd_docker_base_docker_service_name else [] }}"
# Specifies the value of the `X-XSS-Protection` header
# Stops pages from loading when they detect reflected cross-site scripting (XSS) attacks.
#
# Learn more about it is here:
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
# - https://portswigger.net/web-security/cross-site-scripting/reflected
matrix_element_call_http_header_xss_protection: ''
# Specifies the value of the `X-Frame-Options` header which controls whether framing can happen.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
matrix_element_call_http_header_frame_options: ''
# Specifies the value of the `X-Content-Type-Options` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
matrix_element_call_http_header_content_type_options: ''
# Specifies the value of the `Content-Security-Policy` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
matrix_element_call_http_header_content_security_policy: ''
# Specifies the value of the `Permission-Policy` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permission-Policy
matrix_element_call_http_header_content_permission_policy: ''
# Specifies the value of the `Strict-Transport-Security` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
matrix_element_call_http_header_strict_transport_security: ''
# Controls whether to send a "Permissions-Policy interest-cohort=();" header along with all responses
#
# Learn more about what it is here:
# - https://www.eff.org/deeplinks/2021/03/googles-floc-terrible-idea
# - https://paramdeo.com/blog/opting-your-website-out-of-googles-floc-network
# - https://amifloced.org/
#
# Of course, a better solution is to just stop using browsers (like Chrome), which participate in such tracking practices.
# See: `matrix_element_call_content_permission_policy`
matrix_element_call_floc_optout_enabled: false
# Controls if HSTS preloading is enabled
#
# In its strongest and recommended form, the [HSTS policy](https://www.chromium.org/hsts) includes all subdomains, and
# indicates a willingness to be "preloaded" into browsers:
# `Strict-Transport-Security: max-age=31536000; includeSubDomains; preload`
# For more information visit:
# - https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
# - https://hstspreload.org/#opt-in
# See: `matrix_element_call_http_header_strict_transport_security`
matrix_element_call_hsts_preload_enabled: false
# Enable or disable metrics collection
matrix_element_call_metrics_enabled: false
matrix_element_call_metrics_port: 2112

View File

@ -0,0 +1,99 @@
---
# roles/custom/matrix-element-call/tasks/install.yml
# Ensure Required Directories Exist
- name: Ensure matrix-element-call paths exist
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
mode: 0750
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
with_items:
- path: "{{ matrix_element_call_base_path }}"
- path: "{{ matrix_base_data_path }}/static-files/public/.well-known/element" # Directory for element.json
# Ensure Configuration Files are in Place
- name: Ensure Element Call config.json is in place
ansible.builtin.template:
src: "{{ role_path }}/templates/config.json.j2"
dest: "{{ matrix_element_call_base_path }}/config.json"
mode: 0640
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
- name: Ensure matrix-element-call Docker labels file is in place
ansible.builtin.template:
src: "{{ role_path }}/templates/element-call-labels.j2"
dest: "{{ matrix_element_call_base_path }}/element-call-labels"
mode: 0640
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
# Ensure Docker Images are Pulled
- name: Ensure matrix-element-call Docker image is pulled
community.docker.docker_image:
name: "{{ matrix_element_call_container_image }}"
source: pull
force_source: "{{ matrix_element_call_container_image_force_pull }}"
register: element_call_image_result
retries: "{{ devture_playbook_help_container_retries_count }}"
delay: "{{ devture_playbook_help_container_retries_delay }}"
until: element_call_image_result is not failed
# Systemd Services for Element Call
- name: Ensure matrix-element-call systemd service is installed
ansible.builtin.template:
src: "{{ role_path }}/templates/systemd/matrix-element-call.service.j2"
dest: "{{ devture_systemd_docker_base_systemd_path }}/matrix-element-call.service"
mode: 0644
# Update homeserver.yaml for Element Call
- name: Add listeners section for Element Call to homeserver.yaml
ansible.builtin.blockinfile:
path: "{{ matrix_homeserver_config_path }}"
block: |
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
resources:
- names: [client, federation, openid]
compress: false
marker: "# ANSIBLE MANAGED BLOCK - Element Call listeners"
mode: '0644'
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
when: matrix_element_call_enabled | bool
- name: Ensure serve_server_wellknown is enabled in homeserver.yaml
ansible.builtin.lineinfile:
path: "{{ matrix_homeserver_config_path }}"
line: "serve_server_wellknown: true"
insertafter: EOF
state: present
mode: '0644'
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
when: matrix_element_call_enabled | bool
# Update the well-known client file for Element Call (adding RTC FOCI)
- name: Update the well-known client file for Element Call
ansible.builtin.include_tasks: "tasks/update_well_known_client.yml"
when: matrix_element_call_enabled | bool
# Create .well-known/element/element.json for Element Call
- name: Create the well-known element.json file
ansible.builtin.template:
src: "{{ role_path }}/templates/well_known_element.json.j2"
dest: "{{ matrix_base_data_path }}/static-files/public/.well-known/element/element.json"
mode: '0644'
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
# Update Element Web config.json with Element Call settings
- name: Update Element Web config.json
ansible.builtin.include_tasks: "tasks/update_element_web_config.yml"
when: matrix_element_call_enabled | bool

View File

@ -0,0 +1,21 @@
---
# Main task file for matrix-element-call
- tags:
- setup-all
- setup-element-call
- install-all
- install-element-call
block:
- when: matrix_element_call_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/validate_config.yml"
- when: matrix_element_call_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/install.yml"
- tags:
- setup-all
- setup-element-call
block:
- when: not matrix_element_call_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/uninstall.yml"

View File

@ -0,0 +1,21 @@
---
# Uninstall tasks for matrix-element-call
- name: Stop and remove matrix-element-call container
community.docker.docker_container:
name: "matrix-element-call"
state: absent
- name: Remove matrix-element-call systemd service
ansible.builtin.file:
path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-element-call.service"
state: absent
- name: Remove matrix-element-call configuration files
ansible.builtin.file:
path: "{{ matrix_element_call_base_path }}"
state: absent
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: true

View File

@ -0,0 +1,40 @@
- name: Read Element Web config.json
ansible.builtin.slurp:
src: "{{ element_web_config_path }}"
register: element_web_config_content
- name: Load JSON data from config.json
ansible.builtin.set_fact:
element_web_config: "{{ element_web_config_content['content'] | b64decode | from_json }}"
- name: Update Element Call configuration in config.json
ansible.builtin.set_fact:
updated_element_call_config: >
{{
{
"element_call": {
"url": "https://{{ matrix_element_call_domain }}",
"participant_limit": 8,
"brand": "Element Call",
"use_exclusively": true
},
"features": {
"feature_video_rooms": true,
"feature_new_room_decoration_ui": true,
"feature_group_calls": true,
"feature_element_call_video_rooms": true
}
}
}}
- name: Merge updated Element Call configuration with existing config.json
ansible.builtin.set_fact:
element_web_config: "{{ element_web_config | combine(updated_element_call_config, recursive=True) }}"
- name: Write updated Element Web config.json
ansible.builtin.copy:
content: "{{ element_web_config | to_nice_json }}"
dest: "{{ element_web_config_path }}"
mode: '0644'
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"

View File

@ -0,0 +1,21 @@
---
- name: Read the existing well-known client file
ansible.builtin.slurp:
path: "{{ matrix_base_data_path }}/static-files/public/.well-known/matrix/client"
register: client_file_content
- name: Load the existing JSON content
ansible.builtin.set_fact:
client_json: "{{ client_file_content['content'] | b64decode | from_json }}"
- name: Update the existing well-known client file for Element Call (RTC FOCI)
ansible.builtin.set_fact:
updated_client_json: "{{ client_json | combine({'org.matrix.msc4143.rtc_foci': [{'type': 'livekit', 'livekit_service_url': matrix_jwt_service_url}]}, recursive=True) }}"
- name: Write the updated well-known client file
ansible.builtin.copy:
content: "{{ updated_client_json | to_nice_json }}"
dest: "{{ matrix_base_data_path }}/static-files/public/.well-known/matrix/client"
mode: '0644'
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"

View File

@ -0,0 +1,12 @@
---
# Validate configuration for matrix-element-call
- name: Fail if required matrix-element-call settings are not defined
ansible.builtin.fail:
msg: >
You need to define a required configuration setting (`{{ item.name }}`).
when: "item.when | bool and vars[item.name] == ''"
with_items:
- {'name': 'matrix_element_call_base_path', when: true}
- {'name': 'matrix_element_call_container_network', when: true}
- {'name': 'matrix_element_call_image', when: true}

View File

@ -0,0 +1,11 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "{{ matrix_homeserver_url }}",
"server_name": "{{ matrix_domain }}"
}
},
"livekit": {
"livekit_service_url": "{{ matrix_jwt_service_url }}"
}
}

View File

@ -0,0 +1,46 @@
{% if matrix_element_call_container_labels_traefik_enabled %}
traefik.enable=true
# Network configuration for Traefik
{% if matrix_element_call_container_labels_traefik_docker_network %}
traefik.docker.network={{ matrix_element_call_container_labels_traefik_docker_network }}
{% endif %}
traefik.http.services.matrix-element-call.loadbalancer.server.port=8080
{% set middlewares = [] %}
# Path prefix handling for Element Call
{% if matrix_element_call_container_labels_traefik_path_prefix != '/' %}
traefik.http.middlewares.matrix-element-call-slashless-redirect.redirectregex.regex=({{ matrix_element_call_container_labels_traefik_path_prefix | quote }})$
traefik.http.middlewares.matrix-element-call-slashless-redirect.redirectregex.replacement=${1}/
{% set middlewares = middlewares + ['matrix-element-call-slashless-redirect'] %}
traefik.http.middlewares.matrix-element-call-strip-prefix.stripprefix.prefixes={{ matrix_element_call_container_labels_traefik_path_prefix }}
{% set middlewares = middlewares + ['matrix-element-call-strip-prefix'] %}
{% endif %}
{% if matrix_element_call_container_labels_traefik_additional_response_headers.keys() | length > 0 %}
{% for name, value in matrix_element_call_container_labels_traefik_additional_response_headers.items() %}
traefik.http.middlewares.matrix-element-call-add-headers.headers.customresponseheaders.{{ name }}={{ value }}
{% endfor %}
{% set middlewares = middlewares + ['matrix-element-call-add-headers'] %}
{% endif %}
traefik.http.routers.matrix-element-call.rule={{ matrix_element_call_container_labels_traefik_rule }}
{% if matrix_element_call_container_labels_traefik_priority | int > 0 %}
traefik.http.routers.matrix-element-call.priority={{ matrix_element_call_container_labels_traefik_priority }}
{% endif %}
traefik.http.routers.matrix-element-call.service=matrix-element-call
{% if middlewares | length > 0 %}
traefik.http.routers.matrix-element-call.middlewares={{ middlewares | join(',') }}
{% endif %}
traefik.http.routers.matrix-element-call.entrypoints={{ matrix_element_call_container_labels_traefik_entrypoints }}
traefik.http.routers.matrix-element-call.tls={{ matrix_element_call_container_labels_traefik_tls | to_json }}
{% if matrix_element_call_container_labels_traefik_tls %}
traefik.http.routers.matrix-element-call.tls.certResolver={{ matrix_element_call_container_labels_traefik_tls_certResolver }}
{% endif %}
{% endif %}
{{ matrix_element_call_container_labels_additional_labels }}

View File

@ -0,0 +1,46 @@
#jinja2: lstrip_blocks: "True"
[Unit]
Description=Matrix Element Call Service
{% for service in matrix_client_element_systemd_required_services_list %}
Requires={{ service }}
After={{ service }}
{% endfor %}
DefaultDependencies=no
[Service]
Type=simple
Environment="HOME={{ devture_systemd_docker_base_systemd_unit_home_path }}"
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-element-call 2>/dev/null || true'
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-element-call 2>/dev/null || true'
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \
--rm \
--name=matrix-element-call \
--log-driver=none \
--user={{ matrix_user_uid }}:{{ matrix_user_gid }} \
--cap-drop=ALL \
--network={{ matrix_element_call_container_network }} \
--mount type=bind,src={{ matrix_element_call_base_path }}/config.json,dst=/app/config.json,ro \
{% if matrix_element_call_container_http_host_bind_port %}
-p {{ matrix_element_call_container_http_host_bind_port }}:8080 \
{% endif %}
--label-file={{ matrix_element_call_base_path }}/element-call-labels \
{% for arg in matrix_element_call_container_extra_arguments %}
{{ arg }} \
{% endfor %}
{{ matrix_element_call_image }}
{% for network in matrix_element_call_container_additional_networks %}
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-element-call
{% endfor %}
ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach matrix-element-call
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-element-call 2>/dev/null || true'
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-element-call 2>/dev/null || true'
Restart=always
RestartSec=30
SyslogIdentifier=matrix-element-call
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,5 @@
{
"call": {
"widget_url": "https://{{ matrix_element_call_domain }}"
}
}

View File

@ -0,0 +1,5 @@
---
# roles/custom/matrix-element-call/vars/main.yml
# Variables specific to matrix-element-call, like service configurations, can go here.
# Any environment-specific values can be overridden here.

View File

@ -0,0 +1,117 @@
---
# Enable or disable matrix-element-call deployment
matrix_jwt_service_enabled: false
# Base path configuration
matrix_jwt_service_base_path: "{{ matrix_base_data_path }}/jwt-service"
# Docker network configuration
matrix_jwt_service_container_network: ''
matrix_jwt_service_container_http_host_bind_port: '8881'
matrix_jwt_service_container_additional_networks: [] # No additional networks by default
# Docker images
matrix_jwt_service_image: "ghcr.io/element-hq/lk-jwt-service:latest-ci"
# Ports
matrix_jwt_service_port: "8881"
# jwt configuration
matrix_jwt_service_hostname: "sfu-jwt.{{ matrix_domain }}"
matrix_jwt_service_url: "https://sfu-jwt.{{ matrix_domain }}"
# Traefik Configuration for JWT Service
matrix_jwt_service_container_labels_traefik_enabled: true
matrix_jwt_service_container_labels_traefik_docker_network: "{{ matrix_jwt_service_container_network }}"
matrix_jwt_service_container_labels_traefik_hostname: "{{ matrix_jwt_service_hostname }}"
# The path prefix must either be `/` or not end with a slash (e.g. `/element`).
matrix_jwt_service_container_labels_traefik_path_prefix: "{{ matrix_jwt_service_path_prefix }}"
matrix_jwt_service_container_labels_traefik_rule: "Host(`{{ matrix_jwt_service_container_labels_traefik_hostname }}`){% if matrix_jwt_service_container_labels_traefik_path_prefix != '/' %} && PathPrefix(`{{ matrix_jwt_service_container_labels_traefik_path_prefix }}`){% endif %}"
matrix_jwt_service_container_labels_traefik_priority: 0
matrix_jwt_service_container_labels_traefik_entrypoints: web-secure
matrix_jwt_service_container_labels_traefik_tls: "{{ matrix_jwt_service_container_labels_traefik_entrypoints != 'web' }}"
matrix_jwt_service_container_labels_traefik_tls_certResolver: default # noqa var-naming
# Controls which additional headers to attach to all HTTP responses.
# To add your own headers, use `matrix_jwt_service_container_labels_traefik_additional_response_headers_custom`
matrix_jwt_service_container_labels_traefik_additional_response_headers: "{{ matrix_jwt_service_container_labels_traefik_additional_response_headers_auto | combine(matrix_jwt_service_container_labels_traefik_additional_response_headers_custom) }}"
matrix_jwt_service_container_labels_traefik_additional_response_headers_auto: |
{{
{}
| combine ({'X-XSS-Protection': matrix_jwt_service_http_header_xss_protection} if matrix_jwt_service_http_header_xss_protection else {})
| combine ({'X-Frame-Options': matrix_jwt_service_http_header_frame_options} if matrix_jwt_service_http_header_frame_options else {})
| combine ({'X-Content-Type-Options': matrix_jwt_service_http_header_content_type_options} if matrix_jwt_service_http_header_content_type_options else {})
| combine ({'Content-Security-Policy': matrix_jwt_service_http_header_content_security_policy} if matrix_jwt_service_http_header_content_security_policy else {})
| combine ({'Permission-Policy': matrix_jwt_service_http_header_content_permission_policy} if matrix_jwt_service_http_header_content_permission_policy else {})
| combine ({'Strict-Transport-Security': matrix_jwt_service_http_header_strict_transport_security} if matrix_jwt_service_http_header_strict_transport_security and matrix_jwt_service_container_labels_traefik_tls else {})
}}
matrix_jwt_service_container_labels_traefik_additional_response_headers_custom: {}
# matrix_client_element_container_labels_additional_labels contains a multiline string with additional labels to add to the container label file.
# See `../templates/labels.j2` for details.
#
# Example:
# matrix_client_element_container_labels_additional_labels: |
# my.label=1
# another.label="here"
matrix_jwt_service_container_labels_additional_labels: ''
# A list of extra arguments to pass to the container
matrix_jwt_service_container_extra_arguments: []
# Additional environment variables for the container
matrix_jwt_service_environment_variables_additional: {}
# List of systemd services that matrix-element-call.service depends on
matrix_jwt_service_systemd_required_services_list: "{{ [devture_systemd_docker_base_docker_service_name] if devture_systemd_docker_base_docker_service_name else [] }}"
# Specifies the value of the `X-XSS-Protection` header
# Stops pages from loading when they detect reflected cross-site scripting (XSS) attacks.
#
# Learn more about it is here:
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
# - https://portswigger.net/web-security/cross-site-scripting/reflected
matrix_jwt_service_http_header_xss_protection: ''
# Specifies the value of the `X-Frame-Options` header which controls whether framing can happen.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
matrix_jwt_service_http_header_frame_options: ''
# Specifies the value of the `X-Content-Type-Options` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
matrix_jwt_service_http_header_content_type_options: ''
# Specifies the value of the `Content-Security-Policy` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
matrix_jwt_service_http_header_content_security_policy: ''
# Specifies the value of the `Permission-Policy` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permission-Policy
matrix_jwt_service_http_header_content_permission_policy: ''
# Specifies the value of the `Strict-Transport-Security` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
matrix_jwt_service_http_header_strict_transport_security: ''
# Controls whether to send a "Permissions-Policy interest-cohort=();" header along with all responses
#
# Learn more about what it is here:
# - https://www.eff.org/deeplinks/2021/03/googles-floc-terrible-idea
# - https://paramdeo.com/blog/opting-your-website-out-of-googles-floc-network
# - https://amifloced.org/
#
# Of course, a better solution is to just stop using browsers (like Chrome), which participate in such tracking practices.
# See: `matrix_jwt_service_content_permission_policy`
matrix_jwt_service_floc_optout_enabled: false
# Controls if HSTS preloading is enabled
#
# In its strongest and recommended form, the [HSTS policy](https://www.chromium.org/hsts) includes all subdomains, and
# indicates a willingness to be "preloaded" into browsers:
# `Strict-Transport-Security: max-age=31536000; includeSubDomains; preload`
# For more information visit:
# - https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
# - https://hstspreload.org/#opt-in
# See: `matrix_jwt_service_http_header_strict_transport_security`
matrix_jwt_service_hsts_preload_enabled: true

View File

@ -0,0 +1,46 @@
---
# roles/custom/matrix-jwt-service/tasks/install.yml
# Ensure Required Directories Exist
- name: Ensure matrix-jwt-service paths exist
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
mode: 0750
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
with_items:
- path: "{{ matrix_jwt_service_base_path }}"
- name: Ensure matrix-jwt-service environment file is in place
ansible.builtin.template:
src: "{{ role_path }}/templates/env.j2"
dest: "{{ matrix_jwt_service_base_path }}/env"
mode: 0640
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
- name: Ensure JWT Service labels file is in place
ansible.builtin.template:
src: "{{ role_path }}/templates/labels.j2"
dest: "{{ matrix_jwt_service_base_path }}/labels"
mode: 0640
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
# Ensure Docker Images are Pulled
- name: Ensure jwt-service Docker image is pulled
community.docker.docker_image:
name: "{{ matrix_jwt_service_image }}"
source: pull
register: jwt_image_result
retries: 3
delay: 10
until: jwt_image_result is not failed
# Systemd Services for JWT Service
- name: Ensure jwt-service systemd service is installed
ansible.builtin.template:
src: "{{ role_path }}/templates/systemd/matrix-jwt-service.service.j2"
dest: "{{ devture_systemd_docker_base_systemd_path }}/matrix-jwt-service.service"
mode: 0644

View File

@ -0,0 +1,21 @@
---
# Main task file for matrix-element-call
- tags:
- setup-all
- setup-jwt-service
- install-all
- install-wt-service
block:
- when: matrix_jwt_service_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/validate_config.yml"
- when: matrix_jwt_service_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/install.yml"
- tags:
- setup-all
- setup-jwt-service
block:
- when: not matrix_jwt_service_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/uninstall.yml"

View File

@ -0,0 +1,22 @@
---
# Uninstall tasks for matrix-jwt-service
- name: Stop and remove jwt-service container
community.docker.docker_container:
name: "matrix-jwt-service"
state: absent
- name: Remove jwt-service systemd service
ansible.builtin.file:
path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-jwt-service.service"
state: absent
- name: Remove matrix-jwt-service configuration files
ansible.builtin.file:
path: "{{ matrix_jwt_service_base_path }}"
state: absent
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: true

View File

@ -0,0 +1,12 @@
---
# Validate configuration for matrix-jwt-service
- name: Fail if required matrix-jwt-service settings are not defined
ansible.builtin.fail:
msg: >
You need to define a required configuration setting (`{{ item.name }}`).
when: "item.when | bool and vars[item.name] == ''"
with_items:
- {'name': 'matrix_jwt_service_base_path', when: true}
- {'name': 'matrix_jwt_service_container_network', when: true}
- {'name': 'matrix_jwt_service_image', when: true}

View File

@ -0,0 +1,4 @@
# Environment variables for JWT Service
LIVEKIT_KEY=devkey
LIVEKIT_URL=wss://{{ matrix_livekit_server_hostname }}:443
LIVEKIT_SECRET={{ matrix_livekit_server_dev_key }}

View File

@ -0,0 +1,46 @@
{% if matrix_element_call_container_labels_traefik_enabled %}
traefik.enable=true
# Network configuration for Traefik
{% if matrix_jwt_service_container_labels_traefik_docker_network %}
traefik.docker.network={{ matrix_jwt_service_container_labels_traefik_docker_network }}
{% endif %}
traefik.http.services.matrix-jwt-service.loadbalancer.server.port=8080
{% set middlewares = [] %}
# Path prefix handling for JWT
{% if matrix_jwt_service_container_labels_traefik_path_prefix != '/' %}
traefik.http.middlewares.matrix-jwt-service-slashless-redirect.redirectregex.regex=({{ matrix_jwt_service_container_labels_traefik_path_prefix | quote }})$
traefik.http.middlewares.matrix-jwt-service-slashless-redirect.redirectregex.replacement=${1}/
{% set middlewares = middlewares + ['matrix-jwt-service-slashless-redirect'] %}
traefik.http.middlewares.matrix-jwt-service-strip-prefix.stripprefix.prefixes={{ matrix_jwt_service_container_labels_traefik_path_prefix }}
{% set middlewares = middlewares + ['matrix-jwt-service-strip-prefix'] %}
{% endif %}
{% if matrix_jwt_service_container_labels_traefik_additional_response_headers.keys() | length > 0 %}
{% for name, value in matrix_jwt_service_container_labels_traefik_additional_response_headers.items() %}
traefik.http.middlewares.matrix-jwt-service-add-headers.headers.customresponseheaders.{{ name }}={{ value }}
{% endfor %}
{% set middlewares = middlewares + ['matrix-jwt-service-add-headers'] %}
{% endif %}
traefik.http.routers.matrix-jwt-service.rule={{ matrix_jwt_service_container_labels_traefik_rule }}
{% if matrix_jwt_service_container_labels_traefik_priority | int > 0 %}
traefik.http.routers.matrix-jwt-service.priority={{ matrix_jwt_service_container_labels_traefik_priority }}
{% endif %}
traefik.http.routers.matrix-jwt-service.service=matrix-jwt-service
{% if middlewares | length > 0 %}
traefik.http.routers.matrix-jwt-service.middlewares={{ middlewares | join(',') }}
{% endif %}
traefik.http.routers.matrix-jwt-service.entrypoints={{ matrix_jwt_service_container_labels_traefik_entrypoints }}
traefik.http.routers.matrix-jwt-service.tls={{ matrix_jwt_service_container_labels_traefik_tls | to_json }}
{% if matrix_jwt_service_container_labels_traefik_tls %}
traefik.http.routers.matrix-jwt-service.tls.certResolver={{ matrix_jwt_service_container_labels_traefik_tls_certResolver }}
{% endif %}
{% endif %}
{{ matrix_jwt_service_container_labels_additional_labels }}

View File

@ -0,0 +1,40 @@
#jinja2: lstrip_blocks: "True"
[Unit]
Description=Matrix JWT Service
After=docker.service
Requires=docker.service
[Service]
Type=simple
Environment="HOME={{ devture_systemd_docker_base_systemd_unit_home_path }}"
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-jwt-service 2>/dev/null || true'
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-jwt-service 2>/dev/null || true'
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \
--rm \
--name=matrix-jwt-service \
--log-driver=none \
--user={{ matrix_user_uid }}:{{ matrix_user_gid }} \
--cap-drop=ALL \
--network={{ matrix_jwt_service_container_network }} \
{% if matrix_jwt_service_container_http_host_bind_port %}
-p {{ matrix_jwt_service_container_http_host_bind_port }}:8080 \
{% endif %}
--env-file={{ matrix_jwt_service_base_path }}/env \
--label-file={{ matrix_jwt_service_base_path }}/labels \
{{ matrix_jwt_service_image }}
{% for network in matrix_jwt_service_container_additional_networks %}
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-jwt-service
{% endfor %}
ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach matrix-jwt-service
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-jwt-service 2>/dev/null || true'
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-jwt-service 2>/dev/null || true'
Restart=always
RestartSec=30
SyslogIdentifier=matrix-jwt-service
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,115 @@
---
# Enable or disable matrix-livekit-server deployment
matrix_livekit_server_enabled: false
# Base path configuration
matrix_livekit_server_base_path: "{{ matrix_base_data_path }}/livekit-server"
# Docker network configuration
matrix_livekit_server_container_network: ''
matrix_livekit_server_container_http_host_bind_port: ''
matrix_livekit_server_container_additional_networks: [] # No additional networks by default
# Docker images
matrix_livekit_server_image: "livekit/livekit-server:latest"
# LiveKit configuration
matrix_livekit_server_livekit_server_dev_key: "{{ matrix_livekit_server_dev_key }}" # Must be defined in host_vars
matrix_livekit_server_jwt_secret: "{{ matrix_element_call_jwt_secret }}" # Must be defined in host_vars
matrix_livekit_server_hostname: "sfu.{{ matrix_domain }}"
# Traefik Configuration for Element Call
matrix_livekit_server_container_labels_traefik_enabled: true
matrix_livekit_server_container_labels_traefik_docker_network: "{{ matrix_livekit_server_container_network }}"
matrix_livekit_server_container_labels_traefik_hostname: "{{ matrix_livekit_server_hostname }}"
# The path prefix must either be `/` or not end with a slash (e.g. `/element`).
matrix_livekit_server_container_labels_traefik_path_prefix: "{{ matrix_livekit_server_path_prefix }}"
matrix_livekit_server_container_labels_traefik_rule: "Host(`{{ matrix_livekit_server_container_labels_traefik_hostname }}`){% if matrix_livekit_server_container_labels_traefik_path_prefix != '/' %} && PathPrefix(`{{ matrix_livekit_server_container_labels_traefik_path_prefix }}`){% endif %}"
matrix_livekit_server_container_labels_traefik_priority: 0
matrix_livekit_server_container_labels_traefik_entrypoints: web-secure
matrix_livekit_server_container_labels_traefik_tls: "{{ matrix_livekit_server_container_labels_traefik_entrypoints != 'web' }}"
matrix_livekit_server_container_labels_traefik_tls_certResolver: default # noqa var-naming
# Controls which additional headers to attach to all HTTP responses.
# To add your own headers, use `matrix_livekit_server_container_labels_traefik_additional_response_headers_custom`
matrix_livekit_server_container_labels_traefik_additional_response_headers: "{{ matrix_livekit_server_container_labels_traefik_additional_response_headers_auto | combine(matrix_livekit_server_container_labels_traefik_additional_response_headers_custom) }}"
matrix_livekit_server_container_labels_traefik_additional_response_headers_auto: |
{{
{}
| combine ({'X-XSS-Protection': matrix_livekit_server_http_header_xss_protection} if matrix_livekit_server_http_header_xss_protection else {})
| combine ({'X-Frame-Options': matrix_livekit_server_http_header_frame_options} if matrix_livekit_server_http_header_frame_options else {})
| combine ({'X-Content-Type-Options': matrix_livekit_server_http_header_content_type_options} if matrix_livekit_server_http_header_content_type_options else {})
| combine ({'Content-Security-Policy': matrix_livekit_server_http_header_content_security_policy} if matrix_livekit_server_http_header_content_security_policy else {})
| combine ({'Permission-Policy': matrix_livekit_server_http_header_content_permission_policy} if matrix_livekit_server_http_header_content_permission_policy else {})
| combine ({'Strict-Transport-Security': matrix_livekit_server_http_header_strict_transport_security} if matrix_livekit_server_http_header_strict_transport_security and matrix_livekit_server_container_labels_traefik_tls else {})
}}
matrix_livekit_server_container_labels_traefik_additional_response_headers_custom: {}
# matrix_client_element_container_labels_additional_labels contains a multiline string with additional labels to add to the container label file.
# See `../templates/labels.j2` for details.
#
# Example:
# matrix_client_element_container_labels_additional_labels: |
# my.label=1
# another.label="here"
matrix_livekit_server_container_labels_additional_labels: ''
# A list of extra arguments to pass to the container
matrix_livekit_server_container_extra_arguments: []
# Additional environment variables for the container
matrix_livekit_server_environment_variables_additional: {}
# List of systemd services that matrix-element-call.service depends on
matrix_livekit_server_systemd_required_services_list: "{{ [devture_systemd_docker_base_docker_service_name] if devture_systemd_docker_base_docker_service_name else [] }}"
# Specifies the value of the `X-XSS-Protection` header
# Stops pages from loading when they detect reflected cross-site scripting (XSS) attacks.
#
# Learn more about it is here:
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
# - https://portswigger.net/web-security/cross-site-scripting/reflected
matrix_livekit_server_http_header_xss_protection: ''
# Specifies the value of the `X-Frame-Options` header which controls whether framing can happen.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
matrix_livekit_server_http_header_frame_options: ''
# Specifies the value of the `X-Content-Type-Options` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
matrix_livekit_server_http_header_content_type_options: ''
# Specifies the value of the `Content-Security-Policy` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
matrix_livekit_server_http_header_content_security_policy: ''
# Specifies the value of the `Permission-Policy` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permission-Policy
matrix_livekit_server_http_header_content_permission_policy: ''
# Specifies the value of the `Strict-Transport-Security` header.
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
matrix_livekit_server_http_header_strict_transport_security: ''
# Controls whether to send a "Permissions-Policy interest-cohort=();" header along with all responses
#
# Learn more about what it is here:
# - https://www.eff.org/deeplinks/2021/03/googles-floc-terrible-idea
# - https://paramdeo.com/blog/opting-your-website-out-of-googles-floc-network
# - https://amifloced.org/
#
# Of course, a better solution is to just stop using browsers (like Chrome), which participate in such tracking practices.
# See: `matrix_livekit_server_content_permission_policy`
matrix_livekit_server_floc_optout_enabled: false
# Controls if HSTS preloading is enabled
#
# In its strongest and recommended form, the [HSTS policy](https://www.chromium.org/hsts) includes all subdomains, and
# indicates a willingness to be "preloaded" into browsers:
# `Strict-Transport-Security: max-age=31536000; includeSubDomains; preload`
# For more information visit:
# - https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
# - https://hstspreload.org/#opt-in
# See: `matrix_livekit_server_http_header_strict_transport_security`
matrix_livekit_server_hsts_preload_enabled: true

View File

@ -0,0 +1,47 @@
---
# roles/custom/matrix-livekit-server/tasks/install.yml
# Ensure Required Directories Exist
- name: Ensure matrix-livekit-server paths exist
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
mode: 0750
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
with_items:
- path: "{{ matrix_livekit_server_base_path }}"
# Ensure Configuration Files are in Place
- name: Ensure LiveKit livekit.yaml is in place
ansible.builtin.template:
src: "{{ role_path }}/templates/livekit.yaml.j2"
dest: "{{ matrix_livekit_server_base_path }}/livekit.yaml"
mode: 0640
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
- name: Ensure LiveKit labels file is in place
ansible.builtin.template:
src: "{{ role_path }}/templates/labels.j2"
dest: "{{ matrix_livekit_server_base_path }}/labels"
mode: 0640
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
# Ensure Docker Images are Pulled
- name: Ensure livekit Docker image is pulled
community.docker.docker_image:
name: "{{ matrix_livekit_server_image }}"
source: pull
register: livekit_image_result
retries: 3
delay: 10
until: livekit_image_result is not failed
# Systemd Services for LiveKit
- name: Ensure livekit systemd service is installed
ansible.builtin.template:
src: "{{ role_path }}/templates/systemd/matrix-livekit-server.service.j2"
dest: "{{ devture_systemd_docker_base_systemd_path }}/matrix-livekit-server.service"
mode: 0644

View File

@ -0,0 +1,21 @@
---
# Main task file for matrix-livekit-server
- tags:
- setup-all
- setup-livekit-server
- install-all
- install-livekit-server
block:
- when: matrix_livekit_server_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/validate_config.yml"
- when: matrix_livekit_server_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/install.yml"
- tags:
- setup-all
- setup-livekit-server
block:
- when: not matrix_livekit_server_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/uninstall.yml"

View File

@ -0,0 +1,21 @@
---
# Uninstall tasks for matrix-livekit-server
- name: Stop and remove livekit container
community.docker.docker_container:
name: "matrix-livekit-server"
state: absent
- name: Remove livekit systemd service
ansible.builtin.file:
path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-livekit-server.service"
state: absent
- name: Remove matrix-livekit-server configuration files
ansible.builtin.file:
path: "{{ matrix_livekit_serverbase_path }}"
state: absent
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: true

View File

@ -0,0 +1,13 @@
---
# Validate configuration for matrix-livekit-server
- name: Fail if required matrix-livekit-server settings are not defined
ansible.builtin.fail:
msg: >
You need to define a required configuration setting (`{{ item.name }}`).
when: "item.when | bool and vars[item.name] == ''"
with_items:
- {'name': 'matrix_livekit_server_base_path', when: true}
- {'name': 'matrix_livekit_server_container_network', when: true}
- {'name': 'matrix_livekit_server_image', when: true}
- {'name': 'matrix_livekit_server_image', when: true}

View File

@ -0,0 +1,46 @@
{% if matrix_livekit_server_container_labels_traefik_enabled %}
traefik.enable=true
# Network configuration for Traefik
{% if matrix_livekit_server_container_labels_traefik_docker_network %}
traefik.docker.network={{ matrix_livekit_server_container_labels_traefik_docker_network }}
{% endif %}
traefik.http.services.matrix-livekit-server.loadbalancer.server.port=7880
{% set middlewares = [] %}
# Path prefix handling for Livekit
{% if matrix_livekit_server_container_labels_traefik_path_prefix != '/' %}
traefik.http.middlewares.matrix-livekit-server-slashless-redirect.redirectregex.regex=({{ matrix_livekit_server_container_labels_traefik_path_prefix | quote }})$
traefik.http.middlewares.matrix-livekit-server-slashless-redirect.redirectregex.replacement=${1}/
{% set middlewares = middlewares + ['matrix-livekit-server-slashless-redirect'] %}
traefik.http.middlewares.matrix-livekit-server-strip-prefix.stripprefix.prefixes={{ matrix_livekit_server_container_labels_traefik_path_prefix }}
{% set middlewares = middlewares + ['matrix-livekit-server-strip-prefix'] %}
{% endif %}
{% if matrix_livekit_server_container_labels_traefik_additional_response_headers.keys() | length > 0 %}
{% for name, value in matrix_livekit_server_container_labels_traefik_additional_response_headers.items() %}
traefik.http.middlewares.matrix-livekit-server-add-headers.headers.customresponseheaders.{{ name }}={{ value }}
{% endfor %}
{% set middlewares = middlewares + ['matrix-livekit-server-add-headers'] %}
{% endif %}
traefik.http.routers.matrix-livekit-server.rule={{ matrix_livekit_server_container_labels_traefik_rule }}
{% if matrix_livekit_server_container_labels_traefik_priority | int > 0 %}
traefik.http.routers.matrix-livekit-server.priority={{ matrix_livekit_server_container_labels_traefik_priority }}
{% endif %}
traefik.http.routers.matrix-livekit-server.service=matrix-livekit-server
{% if middlewares | length > 0 %}
traefik.http.routers.matrix-livekit-server.middlewares={{ middlewares | join(',') }}
{% endif %}
traefik.http.routers.matrix-livekit-server.entrypoints={{ matrix_livekit_server_container_labels_traefik_entrypoints }}
traefik.http.routers.matrix-livekit-server.tls={{ matrix_livekit_server_container_labels_traefik_tls | to_json }}
{% if matrix_livekit_server_container_labels_traefik_tls %}
traefik.http.routers.matrix-livekit-server.tls.certResolver={{ matrix_livekit_server_container_labels_traefik_tls_certResolver }}
{% endif %}
{% endif %}
{{ matrix_livekit_server_container_labels_additional_labels }}

View File

@ -0,0 +1,20 @@
port: 7880
bind_addresses:
- "0.0.0.0"
rtc:
tcp_port: 7881
port_range_start: 50100
port_range_end: 50200
use_external_ip: true
turn:
enabled: false
domain: localhost
cert_file: ""
key_file: ""
tls_port: 5349
udp_port: 443
external_tls: true
keys:
devkey: "{{ matrix_livekit_server_livekit_dev_key }}"

View File

@ -0,0 +1,34 @@
#jinja2: lstrip_blocks: "True"
[Unit]
Description=Matrix LiveKit Server
After=docker.service
Requires=docker.service
[Service]
Type=simple
Environment="HOME={{ devture_systemd_docker_base_systemd_unit_home_path }}"
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-livekit-server 2>/dev/null || true'
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-livekit-server 2>/dev/null || true'
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \
--rm \
--name=matrix-livekit-server \
--log-driver=none \
--user={{ matrix_user_uid }}:{{ matrix_user_gid }} \
--cap-drop=ALL \
--network=host \
--mount type=bind,src={{ matrix_livekit_server_base_path }}/livekit.yaml,dst=/etc/livekit.yaml,ro \
--label-file={{ matrix_livekit_server_base_path }}/labels \
{{ matrix_livekit_server_image }} \
--dev --config /etc/livekit.yaml
ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach matrix-livekit-server
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-livekit-server 2>/dev/null || true'
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-livekit-server 2>/dev/null || true'
Restart=always
RestartSec=30
SyslogIdentifier=matrix-livekit-server
[Install]
WantedBy=multi-user.target

View File

@ -131,6 +131,9 @@
- custom/matrix-coturn
- custom/matrix-media-repo
- custom/matrix-pantalaimon
- custom/matrix-element-call
- custom/matrix-livekit-server
- custom/matrix-jwt-service
- role: galaxy/postgres_backup