diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index bf55b9a43..1739f54dd 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -435,9 +435,9 @@ devture_systemd_service_manager_services_list_auto: | + ([{'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_element_call_enabled else []) + ([{'name': 'matrix-jwt-service.service', 'priority': 3000, 'groups': ['matrix', 'jwt-service']}] if matrix_jwt_service_enabled else []) + - ([{'name': 'matrix-livekit.service', 'priority': 3000, 'groups': ['matrix', 'livekit']}] if matrix_element_call_enabled else []) + ([{'name': 'matrix-livekit-server.service', 'priority': 3000, 'groups': ['matrix', 'livekit-server']}] if matrix_livekit_server_enabled else []) + ([{'name': 'matrix-redis.service', 'priority': 450, 'groups': ['matrix', 'redis']}] if matrix_element_call_enabled else []) + @@ -5897,27 +5897,87 @@ matrix_element_call_container_image_force_pull: true 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: "{{ devture_traefik_entrypoint_primary }}" matrix_element_call_container_labels_traefik_tls_certResolver: "{{ devture_traefik_certResolver_primary }}" -# JWT Service Configuration -matrix_element_call_jwt_service_url: "https://sfu-jwt.{{ matrix_domain }}" # Default JWT service URL; adjust as needed - -# LiveKit Service Configuration -matrix_element_call_livekit_service_url: "https://sfu.{{ matrix_domain }}" # Default LiveKit service URL; adjust as needed -matrix_element_call_livekit_dev_key: "{{ matrix_livekit_dev_key }}" # LiveKit dev key - -# Redis Configuration for Element Call -matrix_element_call_redis_hostname: "localhost" # Default Redis hostname; can be overridden -matrix_element_call_redis_port: 6379 # Default Redis port; can be overridden -matrix_element_call_redis_password: "" # Redis password; should be set in host_vars if needed ######################################################################## # # # /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: "{{ devture_traefik_entrypoint_primary }}" +matrix_livekit_server_container_labels_traefik_tls_certResolver: "{{ devture_traefik_certResolver_primary }}" + +# LiveKit Service Configuration +matrix_livekit_server_livekit_dev_key: "{{ matrix_livekit_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: "lk-jwt-service" # 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 }}/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: "{{ devture_traefik_entrypoint_primary }}" +matrix_jwt_service_container_labels_traefik_tls_certResolver: "{{ devture_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 # +# # +######################################################################## \ No newline at end of file diff --git a/roles/custom/matrix-element-call/defaults/main.yml b/roles/custom/matrix-element-call/defaults/main.yml index d2660e7e3..eb7652b1a 100644 --- a/roles/custom/matrix-element-call/defaults/main.yml +++ b/roles/custom/matrix-element-call/defaults/main.yml @@ -4,8 +4,6 @@ matrix_element_call_enabled: false # Base path configuration matrix_element_call_base_path: "{{ matrix_base_data_path }}/element-call" -matrix_element_call_config_path: "{{ matrix_element_call_base_path }}/config" -matrix_element_call_backend_path: "{{ matrix_element_call_base_path }}/backend" matrix_homeserver_config_path: "{{ matrix_base_data_path }}/synapse/config/homeserver.yaml" element_web_config_path: "{{ matrix_base_data_path }}/static-files/public/.well-known/matrix/client" @@ -16,24 +14,12 @@ matrix_element_call_container_additional_networks: [] # No additional networks # Docker images matrix_element_call_image: "ghcr.io/element-hq/element-call:latest" -matrix_jwt_service_image: "ghcr.io/element-hq/lk-jwt-service:latest-ci" -matrix_livekit_image: "livekit/livekit-server:latest" redis_image: "redis:6-alpine" # Ports matrix_element_call_port: "8093" -matrix_jwt_service_port: "8881" redis_port: "6379" -# LiveKit configuration -matrix_element_call_livekit_dev_key: "{{ matrix_livekit_dev_key }}" # Must be defined in host_vars -matrix_element_call_jwt_secret: "{{ matrix_jwt_secret }}" # Must be defined in host_vars -matrix_element_call_livekit_service_url: "wss://sfu.{{ matrix_domain }}:443" -matrix_element_call_livekit_hostname: "sfu.{{ matrix_domain }}" - -# jwt configuration -matrix_element_call_jwt_hostname: "sfu-jwt.{{ matrix_domain }}" - # 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" @@ -47,7 +33,7 @@ redis_password: "" # Traefik Configuration for Element Call matrix_element_call_container_labels_traefik_enabled: true -matrix_element_call_container_labels_traefik_docker_network: "{{ matrix_element_callcontainer_network }}" +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 }}" @@ -112,11 +98,11 @@ matrix_element_call_http_header_content_security_policy: frame-ancestors 'self' # 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: "{{ 'interest-cohort=()' if matrix_element_callfloc_optout_enabled else '' }}" +matrix_element_call_http_header_content_permission_policy: "{{ 'interest-cohort=()' if matrix_element_call_floc_optout_enabled else '' }}" # 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: "max-age=31536000; includeSubDomains{{ '; preload' if matrix_element_callhsts_preload_enabled else '' }}" +matrix_element_call_http_header_strict_transport_security: "max-age=31536000; includeSubDomains{{ '; preload' if matrix_element_call_hsts_preload_enabled else '' }}" # Controls whether to send a "Permissions-Policy interest-cohort=();" header along with all responses # @@ -126,8 +112,8 @@ matrix_element_call_http_header_strict_transport_security: "max-age=31536000; in # - 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_callcontent_permission_policy` -matrix_element_callfloc_optout_enabled: true +# See: `matrix_element_call_content_permission_policy` +matrix_element_call_floc_optout_enabled: true # Controls if HSTS preloading is enabled # @@ -139,7 +125,7 @@ matrix_element_callfloc_optout_enabled: true # - 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_callhsts_preload_enabled: false +matrix_element_call_hsts_preload_enabled: false # Enable or disable metrics collection matrix_element_call_metrics_enabled: false diff --git a/roles/custom/matrix-element-call/tasks/create_element_json.yml b/roles/custom/matrix-element-call/tasks/create_element_json.yml deleted file mode 100644 index 7fe689183..000000000 --- a/roles/custom/matrix-element-call/tasks/create_element_json.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- ---- -# Create the element.json file to point to Element Call - -- name: Ensure .well-known/element directory exists - ansible.builtin.file: - path: "{{ matrix_element_call_well_known_element_path | dirname }}" - state: directory - mode: 0755 - -- name: Create or update the element.json file with Element Call config - ansible.builtin.copy: - dest: "{{ matrix_element_call_well_known_element_path }}" - content: | - { - "call": { - "widget_url": "{{ matrix_element_call_base_url }}" - } - } - mode: '0644' - owner: "{{ matrix_user_username }}" - group: "{{ matrix_user_groupname }}" \ No newline at end of file diff --git a/roles/custom/matrix-element-call/tasks/install.yml b/roles/custom/matrix-element-call/tasks/install.yml index f036fa2f9..48719f413 100644 --- a/roles/custom/matrix-element-call/tasks/install.yml +++ b/roles/custom/matrix-element-call/tasks/install.yml @@ -175,7 +175,7 @@ "org.matrix.msc4143.rtc_foci": [ { "type": "livekit", - "livekit_service_url": "{{ matrix_element_call_jwt_service_url }}" + "livekit_service_url": "{{ matrix_jwt_service_url }}" } ] marker: "# ANSIBLE MANAGED BLOCK - Element Call RTC FOCI" diff --git a/roles/custom/matrix-element-call/tasks/install_docker_containers.yml b/roles/custom/matrix-element-call/tasks/install_docker_containers.yml deleted file mode 100644 index a9d55ff85..000000000 --- a/roles/custom/matrix-element-call/tasks/install_docker_containers.yml +++ /dev/null @@ -1,166 +0,0 @@ ---- -# 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 }}" - loop: - - path: "{{ matrix_element_call_base_path }}" - - path: "{{ matrix_element_call_base_path }}/data" - - path: "{{ matrix_element_call_base_path }}/config" - - path: "{{ matrix_element_call_base_path }}/backend" # For LiveKit and Redis config - -# 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/config.json" - mode: 0640 - owner: "{{ matrix_user_username }}" - group: "{{ matrix_user_groupname }}" - -- name: Ensure LiveKit livekit.yaml is in place - ansible.builtin.template: - src: "{{ role_path }}/templates/livekit.yaml.j2" - dest: "{{ matrix_element_call_base_path }}/backend/livekit.yaml" - mode: 0640 - owner: "{{ matrix_user_username }}" - group: "{{ matrix_user_groupname }}" - -- name: Ensure Redis redis.conf is in place - ansible.builtin.template: - src: "{{ role_path }}/templates/redis.conf.j2" - dest: "{{ matrix_element_call_base_path }}/backend/redis.conf" - mode: 0640 - owner: "{{ matrix_user_username }}" - group: "{{ matrix_user_groupname }}" - -- name: Ensure matrix-element-call environment file is in place - ansible.builtin.template: - src: "{{ role_path }}/templates/env.j2" - dest: "{{ matrix_element_call_base_path }}/config/env" - 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/labels.j2" - dest: "{{ matrix_element_call_base_path }}/config/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_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 - -- name: Ensure jwt-service Docker image is pulled - community.docker.docker_image: - name: "ghcr.io/element-hq/lk-jwt-service:latest-ci" - source: pull - register: jwt_image_result - retries: 3 - delay: 10 - until: jwt_image_result is not failed - -- name: Ensure livekit Docker image is pulled - community.docker.docker_image: - name: "livekit/livekit-server:latest" - source: pull - register: livekit_image_result - retries: 3 - delay: 10 - until: livekit_image_result is not failed - -- name: Ensure redis Docker image is pulled - community.docker.docker_image: - name: "redis:6-alpine" - source: pull - register: redis_image_result - retries: 3 - delay: 10 - until: redis_image_result is not failed - -- name: Debug matrix_element_call_base_path - ansible.builtin.debug: - var: matrix_element_call_base_path - -- name: Debug labels file content - ansible.builtin.debug: - msg: "{{ lookup('file', matrix_element_call_base_path ~ '/config/labels') | from_yaml }}" - -# Ensure Docker Containers are Running -- name: Run matrix-element-call Docker container - community.docker.docker_container: - name: "matrix-element-call" - image: "{{ matrix_element_call_image }}" - state: started - restart_policy: unless-stopped - env_file: "{{ matrix_element_call_base_path }}/config/env" - labels: "{{ lookup('file', matrix_element_call_base_path ~ '/config/labels') | from_yaml }}" - networks: - - name: "{{ matrix_element_call_container_network }}" - volumes: - - "{{ matrix_element_call_base_path }}/config/config.json:/app/config.json" - - "{{ matrix_element_call_base_path }}/data:/data" - -- name: Run jwt-service Docker container - community.docker.docker_container: - name: "matrix-jwt-service" - image: "ghcr.io/element-hq/lk-jwt-service:latest-ci" - state: started - restart_policy: unless-stopped - environment: - LIVEKIT_SECRET: "{{ matrix_element_call_livekit_dev_key }}" # User-specified key - LIVEKIT_URL: "{{ matrix_element_call_livekit_service_url }}" - LIVEKIT_KEY: "devkey" - networks: - - name: "{{ matrix_element_call_container_network }}" - -- name: Run livekit Docker container - community.docker.docker_container: - name: "matrix-livekit" - image: "livekit/livekit-server:latest" - state: started - restart_policy: unless-stopped - command: "--dev --config /etc/livekit.yaml" - volumes: - - "{{ matrix_element_call_base_path }}/backend/livekit.yaml:/etc/livekit.yaml" - network_mode: "host" - -- name: Run redis Docker container - community.docker.docker_container: - name: "matrix-redis" - image: "redis:6-alpine" - state: started - restart_policy: unless-stopped - command: redis-server /etc/redis.conf - volumes: - - "{{ matrix_element_call_base_path }}/backend/redis.conf:/etc/redis.conf" - networks: - - name: "{{ matrix_element_call_container_network }}" - -# Ensure Systemd Services are Set Up -- name: Ensure matrix-element-call systemd service is installed - ansible.builtin.template: - src: "{{ role_path }}/templates/element-call.service.j2" - dest: "{{ devture_systemd_docker_base_systemd_path }}/matrix-element-call.service" - mode: 0644 - -- name: Ensure matrix-element-call systemd service is enabled and started - ansible.builtin.systemd: - name: matrix-element-call - enabled: true - state: started - daemon_reload: true diff --git a/roles/custom/matrix-element-call/tasks/update_element_web_config.yml b/roles/custom/matrix-element-call/tasks/update_element_web_config.yml deleted file mode 100644 index 0fa227172..000000000 --- a/roles/custom/matrix-element-call/tasks/update_element_web_config.yml +++ /dev/null @@ -1,29 +0,0 @@ ---- -# Update Element-Web config.json with Element Call features - -- name: Ensure Element-Web config.json exists - ansible.builtin.file: - path: "{{ matrix_element_web_config_path }}" - state: file - mode: 0644 - -- name: Update Element-Web config.json with Element Call features - ansible.builtin.blockinfile: - path: "{{ matrix_element_web_config_path }}" - block: | - "features": { - "feature_video_rooms": true, - "feature_new_room_decoration_ui": true, - "feature_group_calls": true, - "feature_element_call_video_rooms": true - }, - "element_call": { - "url": "{{ matrix_element_call_base_url }}", - "participant_limit": 8, - "brand": "Element Call", - "use_exclusively": true - } - marker: "# ANSIBLE MANAGED BLOCK - Element Call features" - mode: '0644' - owner: "{{ matrix_user_username }}" - group: "{{ matrix_user_groupname }}" \ No newline at end of file diff --git a/roles/custom/matrix-element-call/tasks/update_homeserver_config.yml b/roles/custom/matrix-element-call/tasks/update_homeserver_config.yml deleted file mode 100644 index 46e4f5a09..000000000 --- a/roles/custom/matrix-element-call/tasks/update_homeserver_config.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- -# Update the homeserver.yaml file with Element Call config - -- name: Ensure homeserver.yaml exists - ansible.builtin.file: - path: "{{ matrix_homeserver_config_path }}" - state: file - mode: 0644 - -- 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 }}" - -- 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 }}" \ No newline at end of file diff --git a/roles/custom/matrix-element-call/tasks/update_well_known_client.yml b/roles/custom/matrix-element-call/tasks/update_well_known_client.yml deleted file mode 100644 index b02269f1c..000000000 --- a/roles/custom/matrix-element-call/tasks/update_well_known_client.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- ---- -# Update the .well-known/matrix/client file with Element Call config - -- name: Ensure .well-known directory exists - ansible.builtin.file: - path: "{{ matrix_element_call_well_known_client_path | dirname }}" - state: directory - mode: 0755 - -- name: Update .well-known/matrix/client file with Element Call config - ansible.builtin.blockinfile: - path: "{{ matrix_element_call_well_known_client_path }}" - block: | - "org.matrix.msc4143.rtc_foci": [ - { - "type": "livekit", - "livekit_service_url": "{{ matrix_element_call_jwt_service_url }}" - } - ] - create: yes - mode: '0644' - owner: "{{ matrix_user_username }}" - group: "{{ matrix_user_groupname }}" \ No newline at end of file diff --git a/roles/custom/matrix-element-call/tasks/validate_config.yml b/roles/custom/matrix-element-call/tasks/validate_config.yml index c0e0ef940..7760cb94e 100644 --- a/roles/custom/matrix-element-call/tasks/validate_config.yml +++ b/roles/custom/matrix-element-call/tasks/validate_config.yml @@ -14,4 +14,4 @@ - {'name': 'matrix_livekit_image', when: true} - {'name': 'redis_image', when: true} - {'name': 'matrix_element_call_livekit_dev_key', when: true} - - {'name': 'matrix_element_call_livekit_service_url', when: true} + - {'name': 'matrix_jwt_service_url', when: true} diff --git a/roles/custom/matrix-element-call/templates/config.json.j2 b/roles/custom/matrix-element-call/templates/config.json.j2 index 3dc7f0e8a..e58648e50 100644 --- a/roles/custom/matrix-element-call/templates/config.json.j2 +++ b/roles/custom/matrix-element-call/templates/config.json.j2 @@ -6,6 +6,6 @@ } }, "livekit": { - "livekit_service_url": "{{ matrix_element_call_livekit_service_url }}" + "livekit_service_url": "{{ matrix_jwt_service_url }}" } } diff --git a/roles/custom/matrix-element-call/templates/env.j2 b/roles/custom/matrix-element-call/templates/env.j2 deleted file mode 100644 index b5a5d4be4..000000000 --- a/roles/custom/matrix-element-call/templates/env.j2 +++ /dev/null @@ -1,11 +0,0 @@ -# Environment variables for Element Call -ELEMENT_CALL_SERVER_URL=https://{{ matrix_element_call_domain }} -LIVEKIT_KEY=devkey -LIVEKIT_URL={{ matrix_element_call_livekit_service_url }} -LIVEKIT_SECRET={{ matrix_element_call_jwt_secret }} -JWT_SERVICE_URL={{ matrix_element_call_jwt_service_url }} - -# Optional additional environment variables provided by the user -{% for key, value in matrix_element_call_environment_variables_additional.items() %} -{{ key }}={{ value }} -{% endfor %} diff --git a/roles/custom/matrix-element-call/templates/jwt-service-labels.j2 b/roles/custom/matrix-element-call/templates/jwt-service-labels.j2 deleted file mode 100644 index 603ced758..000000000 --- a/roles/custom/matrix-element-call/templates/jwt-service-labels.j2 +++ /dev/null @@ -1,13 +0,0 @@ -{% if matrix_element_call_container_labels_traefik_enabled %} -traefik.enable=true - -{% if matrix_element_call_container_labels_traefik_docker_network %} -traefik.docker.network={{ matrix_element_call_container_labels_traefik_docker_network }} -{% endif %} - -# Define the Traefik router rule for JWT Service -traefik.http.routers.jwt-router.rule=Host(`{{ matrix_element_call_jwt_hostname }}`) -traefik.http.routers.jwt-router.entrypoints={{ matrix_element_call_container_labels_traefik_entrypoints }} -traefik.http.routers.jwt-router.tls.certresolver={{ matrix_element_call_container_labels_traefik_tls_certResolver }} -traefik.http.services.jwt-service.loadbalancer.server.port=8881 -{% endif %} diff --git a/roles/custom/matrix-element-call/templates/livekit-labels.j2 b/roles/custom/matrix-element-call/templates/livekit-labels.j2 deleted file mode 100644 index 5fa0c51ad..000000000 --- a/roles/custom/matrix-element-call/templates/livekit-labels.j2 +++ /dev/null @@ -1,13 +0,0 @@ -{% if matrix_element_call_container_labels_traefik_enabled %} -traefik.enable=true - -{% if matrix_element_call_container_labels_traefik_docker_network %} -traefik.docker.network={{ matrix_element_call_container_labels_traefik_docker_network }} -{% endif %} - -# Define the Traefik router rule for LiveKit -traefik.http.routers.livekit-router.rule=Host(`{{ matrix_element_call_livekit_hostname }}`) -traefik.http.routers.livekit-router.entrypoints={{ matrix_element_call_container_labels_traefik_entrypoints }} -traefik.http.routers.livekit-router.tls.certresolver={{ matrix_element_call_container_labels_traefik_tls_certResolver }} -traefik.http.services.livekit-service.loadbalancer.server.port=7880 -{% endif %} diff --git a/roles/custom/matrix-jwt-service/defaults/main.yml b/roles/custom/matrix-jwt-service/defaults/main.yml new file mode 100644 index 000000000..cf087da87 --- /dev/null +++ b/roles/custom/matrix-jwt-service/defaults/main.yml @@ -0,0 +1,118 @@ +--- +# 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" +matrix_homeserver_config_path: "{{ matrix_base_data_path }}/synapse/config/homeserver.yaml" + +# Docker network configuration +matrix_jwt_service_container_network: '' +matrix_jwt_service_container_http_host_bind_port: '' +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: "1; mode=block" + +# 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: SAMEORIGIN + +# 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: nosniff + +# 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: frame-ancestors 'self' + +# 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: "{{ 'interest-cohort=()' if matrix_jwt_service_floc_optout_enabled else '' }}" + +# 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: "max-age=31536000; includeSubDomains{{ '; preload' if matrix_jwt_service_hsts_preload_enabled else '' }}" + +# 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: true + +# 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: false \ No newline at end of file diff --git a/roles/custom/matrix-jwt-service/tasks/install.yml b/roles/custom/matrix-jwt-service/tasks/install.yml new file mode 100644 index 000000000..9a51bdfd3 --- /dev/null +++ b/roles/custom/matrix-jwt-service/tasks/install.yml @@ -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 \ No newline at end of file diff --git a/roles/custom/matrix-jwt-service/tasks/main.yml b/roles/custom/matrix-jwt-service/tasks/main.yml new file mode 100644 index 000000000..ee74a8967 --- /dev/null +++ b/roles/custom/matrix-jwt-service/tasks/main.yml @@ -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" diff --git a/roles/custom/matrix-jwt-service/tasks/uninstall.yml b/roles/custom/matrix-jwt-service/tasks/uninstall.yml new file mode 100644 index 000000000..550c82951 --- /dev/null +++ b/roles/custom/matrix-jwt-service/tasks/uninstall.yml @@ -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 diff --git a/roles/custom/matrix-jwt-service/tasks/validate_config.yml b/roles/custom/matrix-jwt-service/tasks/validate_config.yml new file mode 100644 index 000000000..a0105e940 --- /dev/null +++ b/roles/custom/matrix-jwt-service/tasks/validate_config.yml @@ -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} diff --git a/roles/custom/matrix-jwt-service/templates/env.j2 b/roles/custom/matrix-jwt-service/templates/env.j2 new file mode 100644 index 000000000..8034a9b33 --- /dev/null +++ b/roles/custom/matrix-jwt-service/templates/env.j2 @@ -0,0 +1,4 @@ +# Environment variables for JWT Service +LIVEKIT_KEY=devkey +LIVEKIT_URL=wss://{{ matrix_livekit_server_hostname }}:443 +LIVEKIT_SECRET={{ matrix_element_call_jwt_secret }} \ No newline at end of file diff --git a/roles/custom/matrix-jwt-service/templates/labels.j2 b/roles/custom/matrix-jwt-service/templates/labels.j2 new file mode 100644 index 000000000..b547e1952 --- /dev/null +++ b/roles/custom/matrix-jwt-service/templates/labels.j2 @@ -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 }} diff --git a/roles/custom/matrix-element-call/templates/systemd/matrix-jwt-service.service.j2 b/roles/custom/matrix-jwt-service/templates/systemd/matrix-jwt-service.service.j2 similarity index 85% rename from roles/custom/matrix-element-call/templates/systemd/matrix-jwt-service.service.j2 rename to roles/custom/matrix-jwt-service/templates/systemd/matrix-jwt-service.service.j2 index 7d2ac8fd8..07c8ef1ed 100644 --- a/roles/custom/matrix-element-call/templates/systemd/matrix-jwt-service.service.j2 +++ b/roles/custom/matrix-jwt-service/templates/systemd/matrix-jwt-service.service.j2 @@ -15,13 +15,13 @@ ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \ --log-driver=none \ --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ --cap-drop=ALL \ - --network={{ matrix_element_call_container_network }} \ + --network={{ matrix_jwt_service_container_network }} \ -p {{ matrix_jwt_service_port }}:8080 \ - --env-file={{ matrix_element_call_base_path }}/config/env \ - --label-file={{ matrix_element_call_base_path }}/config/jwt-service-labels \ + --env-file={{ matrix_jwt_service_base_path }}/env \ + --label-file={{ matrix_jwt_service_base_path }}/labels \ {{ matrix_jwt_service_image }} -{% for network in matrix_element_call_container_additional_networks %} +{% for network in matrix_jwt_service_container_additional_networks %} ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-jwt-service {% endfor %} diff --git a/roles/custom/matrix-livekit/defaults/main.yml b/roles/custom/matrix-livekit/defaults/main.yml new file mode 100644 index 000000000..73ee72f6b --- /dev/null +++ b/roles/custom/matrix-livekit/defaults/main.yml @@ -0,0 +1,119 @@ +--- +# 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" +matrix_livekit_server_config_path: "{{ matrix_livekit_server_base_path }}/config" +matrix_livekit_server_backend_path: "{{ matrix_livekit_server_base_path }}/backend" +matrix_homeserver_config_path: "{{ matrix_base_data_path }}/synapse/config/homeserver.yaml" +element_web_config_path: "{{ matrix_base_data_path }}/static-files/public/.well-known/matrix/client" + +# 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_domain }}" +# 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: "1; mode=block" + +# 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: SAMEORIGIN + +# 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: nosniff + +# 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: frame-ancestors 'self' + +# 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: "{{ 'interest-cohort=()' if matrix_livekit_server_floc_optout_enabled else '' }}" + +# 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: "max-age=31536000; includeSubDomains{{ '; preload' if matrix_livekit_server_hsts_preload_enabled else '' }}" + +# 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: true + +# 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: false \ No newline at end of file diff --git a/roles/custom/matrix-livekit/tasks/install.yml b/roles/custom/matrix-livekit/tasks/install.yml new file mode 100644 index 000000000..cccb89deb --- /dev/null +++ b/roles/custom/matrix-livekit/tasks/install.yml @@ -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.service" + mode: 0644 \ No newline at end of file diff --git a/roles/custom/matrix-livekit/tasks/main.yml b/roles/custom/matrix-livekit/tasks/main.yml new file mode 100644 index 000000000..255906c75 --- /dev/null +++ b/roles/custom/matrix-livekit/tasks/main.yml @@ -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" diff --git a/roles/custom/matrix-livekit/tasks/uninstall.yml b/roles/custom/matrix-livekit/tasks/uninstall.yml new file mode 100644 index 000000000..371db5c83 --- /dev/null +++ b/roles/custom/matrix-livekit/tasks/uninstall.yml @@ -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 diff --git a/roles/custom/matrix-livekit/tasks/validate_config.yml b/roles/custom/matrix-livekit/tasks/validate_config.yml new file mode 100644 index 000000000..552524318 --- /dev/null +++ b/roles/custom/matrix-livekit/tasks/validate_config.yml @@ -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_image', when: true} diff --git a/roles/custom/matrix-livekit/templates/labels.j2 b/roles/custom/matrix-livekit/templates/labels.j2 new file mode 100644 index 000000000..c41b7ed01 --- /dev/null +++ b/roles/custom/matrix-livekit/templates/labels.j2 @@ -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 }} diff --git a/roles/custom/matrix-element-call/templates/livekit.yaml.j2 b/roles/custom/matrix-livekit/templates/livekit.yaml.j2 similarity index 83% rename from roles/custom/matrix-element-call/templates/livekit.yaml.j2 rename to roles/custom/matrix-livekit/templates/livekit.yaml.j2 index 384cf3722..f8e2ad0c2 100644 --- a/roles/custom/matrix-element-call/templates/livekit.yaml.j2 +++ b/roles/custom/matrix-livekit/templates/livekit.yaml.j2 @@ -17,4 +17,4 @@ turn: external_tls: true keys: - devkey: "{{ matrix_element_call_livekit_dev_key }}" + devkey: "{{ matrix_livekit_server_livekit_dev_key }}" diff --git a/roles/custom/matrix-element-call/templates/systemd/matrix-livekit.service.j2 b/roles/custom/matrix-livekit/templates/systemd/matrix-livekit-server.service.j2 similarity index 71% rename from roles/custom/matrix-element-call/templates/systemd/matrix-livekit.service.j2 rename to roles/custom/matrix-livekit/templates/systemd/matrix-livekit-server.service.j2 index 4b7f3ea8a..0f416c82d 100644 --- a/roles/custom/matrix-element-call/templates/systemd/matrix-livekit.service.j2 +++ b/roles/custom/matrix-livekit/templates/systemd/matrix-livekit-server.service.j2 @@ -1,33 +1,33 @@ [Unit] -Description=Matrix LiveKit Service +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 2>/dev/null || true' -ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-livekit 2>/dev/null || true' +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 \ + --name=matrix-livekit-server \ --log-driver=none \ --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ --cap-drop=ALL \ --network=host \ - --mount type=bind,src={{ matrix_element_call_backend_path }}/livekit.yaml,dst=/etc/livekit.yaml,ro \ - --label-file={{ matrix_element_call_base_path }}/config/livekit-labels \ + --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_image }} \ --dev --config /etc/livekit.yaml -ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach matrix-livekit +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 2>/dev/null || true' -ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-livekit 2>/dev/null || true' +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 +SyslogIdentifier=matrix-livekit-server [Install] WantedBy=multi-user.target