mirror of
https://github.com/spantaleev/matrix-docker-ansible-deploy.git
synced 2026-02-28 01:43:10 +00:00
Merge Synapse reverse-proxy companion role into matrix-synapse
The companion role was tightly coupled to Synapse through shared tags, worker routing, and lifecycle ordering. Keeping them separate added coordination overhead without practical benefits, especially for parallelized execution. This merges the role into matrix-synapse while keeping companion logic organized under dedicated reverse_proxy_companion task/template subdirectories. Compatibility is preserved: - matrix_synapse_reverse_proxy_companion_* variable names remain unchanged - install/setup companion-specific tags remain available Cross-role/global wiring is now in group_vars (matrix-synapse section), while role defaults provide sensible standalone defaults and self-wiring for Synapse-owned values.
This commit is contained in:
@@ -1710,3 +1710,378 @@ matrix_synapse_configuration: "{{ matrix_synapse_configuration_yaml | from_yaml
|
||||
# When the Matrix Authentication Service is enabled, the register-user script from this role cannot be used
|
||||
# and users will be pointed to the one provided by Matrix Authentication Service.
|
||||
matrix_synapse_register_user_script_matrix_authentication_service_path: ""
|
||||
|
||||
|
||||
########################################################################################
|
||||
# #
|
||||
# Synapse reverse-proxy companion #
|
||||
# #
|
||||
########################################################################################
|
||||
|
||||
# matrix-synapse-reverse-proxy-companion is a role which brings up a containerized nginx webserver which helps with reverse-proxying to Synapse when workers are enabled.
|
||||
#
|
||||
# When Synapse is NOT running in worker-mode, reverse-proxying is relatively simple (everything goes to `matrix-synapse:XXXX`).
|
||||
# In such cases, using this reverse-proxy companion is possible, but unnecessary - it's one more service in the stack, which also impacts performance a bit.
|
||||
#
|
||||
# When Synapse workers are enabled, however, the reverse-proxying configuration is much more complicated - certain requests need to go to certain workers, etc.
|
||||
# matrix-synapse-reverse-proxy-companion is the central place services that need to reach Synapse could be pointed to.
|
||||
#
|
||||
# Project source code URL: https://github.com/nginx/nginx
|
||||
|
||||
matrix_synapse_reverse_proxy_companion_enabled: "{{ matrix_synapse_enabled and matrix_synapse_workers_enabled }}"
|
||||
|
||||
# renovate: datasource=docker depName=nginx
|
||||
matrix_synapse_reverse_proxy_companion_version: 1.29.5-alpine
|
||||
|
||||
matrix_synapse_reverse_proxy_companion_base_path: "{{ matrix_synapse_base_path }}/reverse-proxy-companion"
|
||||
matrix_synapse_reverse_proxy_companion_confd_path: "{{ matrix_synapse_reverse_proxy_companion_base_path }}/conf.d"
|
||||
matrix_synapse_reverse_proxy_companion_njs_path: "{{ matrix_synapse_reverse_proxy_companion_base_path }}/njs"
|
||||
|
||||
# List of systemd services that matrix-synapse-reverse-proxy-companion.service depends on
|
||||
matrix_synapse_reverse_proxy_companion_systemd_required_services_list: "{{ matrix_synapse_reverse_proxy_companion_systemd_required_services_list_default + matrix_synapse_reverse_proxy_companion_systemd_required_services_list_auto + matrix_synapse_reverse_proxy_companion_systemd_required_services_list_custom }}"
|
||||
matrix_synapse_reverse_proxy_companion_systemd_required_services_list_default: []
|
||||
matrix_synapse_reverse_proxy_companion_systemd_required_services_list_auto: []
|
||||
matrix_synapse_reverse_proxy_companion_systemd_required_services_list_custom: []
|
||||
|
||||
# List of systemd services that matrix-synapse-reverse-proxy-companion.service wants
|
||||
matrix_synapse_reverse_proxy_companion_systemd_wanted_services_list: ['matrix-synapse.service']
|
||||
|
||||
# We use an official nginx image, which we fix-up to run unprivileged.
|
||||
# An alternative would be an `nginxinc/nginx-unprivileged` image, but
|
||||
# that is frequently out of date.
|
||||
matrix_synapse_reverse_proxy_companion_container_image: "{{ matrix_synapse_reverse_proxy_companion_container_image_registry_prefix }}nginx:{{ matrix_synapse_reverse_proxy_companion_container_image_tag }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_image_registry_prefix: "{{ matrix_synapse_reverse_proxy_companion_container_image_registry_prefix_upstream }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_image_registry_prefix_upstream: "{{ matrix_synapse_reverse_proxy_companion_container_image_registry_prefix_upstream_default }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_image_registry_prefix_upstream_default: "docker.io/"
|
||||
matrix_synapse_reverse_proxy_companion_container_image_tag: "{{ matrix_synapse_reverse_proxy_companion_version }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_image_force_pull: "{{ matrix_synapse_reverse_proxy_companion_container_image.endswith(':latest') }}"
|
||||
|
||||
matrix_synapse_reverse_proxy_companion_container_network: "{{ matrix_synapse_container_network }}"
|
||||
|
||||
# A list of additional container networks that matrix-synapse-reverse-proxy-companion would be connected to.
|
||||
# The playbook does not create these networks, so make sure they already exist.
|
||||
matrix_synapse_reverse_proxy_companion_container_additional_networks: "{{ matrix_synapse_reverse_proxy_companion_container_additional_networks_auto + matrix_synapse_reverse_proxy_companion_container_additional_networks_custom }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_additional_networks_auto: []
|
||||
matrix_synapse_reverse_proxy_companion_container_additional_networks_custom: []
|
||||
|
||||
# Controls whether the matrix-synapse-reverse-proxy-companion container exposes its HTTP Client-Server API port (tcp/8008 in the container).
|
||||
#
|
||||
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:8008"), or empty string to not expose.
|
||||
matrix_synapse_reverse_proxy_companion_container_client_api_host_bind_port: ''
|
||||
|
||||
# Controls whether the matrix-synapse-reverse-proxy-companion container exposes its HTTP Federation (Server-Server) API port (tcp/8048 in the container).
|
||||
#
|
||||
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:8048"), or empty string to not expose.
|
||||
matrix_synapse_reverse_proxy_companion_container_federation_api_host_bind_port: ''
|
||||
|
||||
# matrix_synapse_reverse_proxy_companion_container_labels_traefik_enabled controls whether labels to assist a Traefik reverse-proxy will be attached to the container.
|
||||
# See `../templates/labels.j2` for details.
|
||||
#
|
||||
# To inject your own other container labels, see `matrix_synapse_reverse_proxy_companion_container_labels_additional_labels`.
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_traefik_enabled: true
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_traefik_docker_network: "{{ matrix_synapse_reverse_proxy_companion_container_network }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_traefik_entrypoints: web-secure
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_traefik_tls_certResolver: default # noqa var-naming
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_traefik_hostname: ''
|
||||
|
||||
# Controls whether a compression middleware will be injected into the middlewares list.
|
||||
# This compression middleware is supposed to be defined elsewhere (using labels or a File provider, etc.) and is merely referenced by this router.
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_enabled: false
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_name: ""
|
||||
|
||||
# Controls whether labels will be added that expose the Client-Server API on a public Traefik entrypoint.
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_enabled: true
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_hostname: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_hostname }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_path_prefix: /_matrix
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_rule: "Host(`{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_hostname }}`) && PathPrefix(`{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_path_prefix }}`)"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_priority: 0
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_entrypoints: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_entrypoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_tls: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_entrypoints != 'web' }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_tls_certResolver: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_tls_certResolver }}" # noqa var-naming
|
||||
|
||||
# Controls whether labels will be added that expose the Client-Server API on the internal Traefik entrypoint.
|
||||
# This is similar to `matrix_synapse_container_labels_public_client_api_enabled`, but the entrypoint and intent is different.
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_enabled: "{{ matrix_synapse_container_labels_internal_client_api_enabled }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_path_prefix: "{{ matrix_synapse_container_labels_public_client_api_traefik_path_prefix }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_rule: "PathPrefix(`{{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_path_prefix }}`)"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_priority: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_priority }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_entrypoints: "{{ matrix_synapse_container_labels_internal_client_api_traefik_entrypoints }}"
|
||||
|
||||
# Controls whether labels will be added that expose the /_synapse/client paths
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_enabled: "{{ matrix_synapse_container_labels_public_client_synapse_client_api_enabled }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_hostname: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_hostname }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_path_prefix: /_synapse/client
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_rule: "Host(`{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_hostname }}`) && PathPrefix(`{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_path_prefix }}`)"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_priority: 0
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_entrypoints: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_entrypoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_tls: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_entrypoints != 'web' }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_tls_certResolver: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_tls_certResolver }}" # noqa var-naming
|
||||
|
||||
# Controls whether labels will be added that expose the /_synapse/admin paths
|
||||
# Following these recommendations (https://github.com/element-hq/synapse/blob/master/docs/reverse_proxy.md), by default, we don't.
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_enabled: "{{ matrix_synapse_container_labels_public_client_synapse_admin_api_enabled }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_hostname: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_hostname }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_path_prefix: /_synapse/admin
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_rule: "Host(`{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_hostname }}`) && PathPrefix(`{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_path_prefix }}`)"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_priority: 0
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_entrypoints: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_entrypoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_tls: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_entrypoints != 'web' }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_tls_certResolver: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_tls_certResolver }}" # noqa var-naming
|
||||
|
||||
# Controls whether labels will be added that expose the /_synapse/admin paths on the internal Traefik entrypoint.
|
||||
# This is similar to `matrix_synapse_container_labels_public_client_api_enabled`, but the entrypoint and intent is different.
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_enabled: "{{ matrix_synapse_container_labels_internal_client_synapse_admin_api_enabled }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_path_prefix: "{{ matrix_synapse_container_labels_internal_client_synapse_admin_api_traefik_path_prefix }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_rule: "PathPrefix(`{{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_path_prefix }}`)"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_priority: 0
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_entrypoints: ""
|
||||
|
||||
# Controls whether labels will be added that expose the Server-Server API (Federation API).
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_enabled: "{{ matrix_synapse_reverse_proxy_companion_federation_api_enabled }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_hostname: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_hostname }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_path_prefix: /_matrix
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_rule: "Host(`{{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_hostname }}`) && PathPrefix(`{{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_path_prefix }}`)"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_priority: 0
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_entrypoints: "{{ matrix_synapse_container_labels_public_federation_api_traefik_entrypoints }}"
|
||||
# TLS is force-enabled here, because the spec (https://spec.matrix.org/v1.9/server-server-api/#tls) says that the federation API must use HTTPS.
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_tls: "{{ matrix_synapse_container_labels_public_federation_api_traefik_tls }}"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_tls_certResolver: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_tls_certResolver }}" # noqa var-naming
|
||||
|
||||
# matrix_synapse_reverse_proxy_companion_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_synapse_reverse_proxy_companion_container_labels_additional_labels: |
|
||||
# my.label=1
|
||||
# another.label="here"
|
||||
matrix_synapse_reverse_proxy_companion_container_labels_additional_labels: ''
|
||||
|
||||
# A list of extra arguments to pass to the container
|
||||
# Also see `matrix_synapse_reverse_proxy_companion_container_arguments`
|
||||
matrix_synapse_reverse_proxy_companion_container_extra_arguments: []
|
||||
|
||||
# matrix_synapse_reverse_proxy_companion_container_extra_arguments_auto is a list of extra arguments to pass to the container.
|
||||
# This list is managed by the playbook. You're not meant to override this variable.
|
||||
# If you'd like to inject your own arguments, see `matrix_synapse_reverse_proxy_companion_container_extra_arguments`.
|
||||
matrix_synapse_reverse_proxy_companion_container_extra_arguments_auto: []
|
||||
|
||||
# matrix_synapse_reverse_proxy_companion_container_arguments holds the final list of extra arguments to pass to the container.
|
||||
# You're not meant to override this variable.
|
||||
# If you'd like to inject your own arguments, see `matrix_synapse_reverse_proxy_companion_container_extra_arguments`.
|
||||
matrix_synapse_reverse_proxy_companion_container_arguments: "{{ matrix_synapse_reverse_proxy_companion_container_extra_arguments + matrix_synapse_reverse_proxy_companion_container_extra_arguments_auto }}"
|
||||
|
||||
# The amount of worker processes and connections
|
||||
# Consider increasing these when you are expecting high amounts of traffic
|
||||
# http://nginx.org/en/docs/ngx_core_module.html#worker_connections
|
||||
matrix_synapse_reverse_proxy_companion_worker_processes: auto
|
||||
matrix_synapse_reverse_proxy_companion_worker_connections: 1024
|
||||
|
||||
# Option to disable the access log
|
||||
matrix_synapse_reverse_proxy_companion_access_log_enabled: true
|
||||
|
||||
# Controls whether to send access logs to a remote syslog-compatible server
|
||||
matrix_synapse_reverse_proxy_companion_access_log_syslog_integration_enabled: false
|
||||
matrix_synapse_reverse_proxy_companion_access_log_syslog_integration_server_port: ''
|
||||
# This is intentionally different. The maximum allowed length is 32 characters and dashes are not allowed.
|
||||
matrix_synapse_reverse_proxy_companion_access_log_syslog_integration_tag: matrix_synapse_rev_proxy_comp
|
||||
|
||||
# The tmpfs at /tmp needs to be large enough to handle multiple concurrent file uploads.
|
||||
matrix_synapse_reverse_proxy_companion_tmp_directory_size_mb: "{{ (matrix_synapse_reverse_proxy_companion_federation_api_client_max_body_size_mb | int) * 50 }}"
|
||||
matrix_synapse_reverse_proxy_companion_tmp_cache_directory_size_mb: "{{ (matrix_synapse_reverse_proxy_companion_synapse_cache_max_size_mb | int) * 2 }}"
|
||||
|
||||
# A list of strings containing additional configuration blocks to add to the nginx server configuration (nginx.conf).
|
||||
# for big matrixservers to enlarge the number of open files to prevent timeouts
|
||||
# matrix_synapse_reverse_proxy_companion_additional_configuration_blocks:
|
||||
# - 'worker_rlimit_nofile 30000;'
|
||||
matrix_synapse_reverse_proxy_companion_additional_configuration_blocks: []
|
||||
|
||||
# A list of strings containing additional configuration blocks to add to the nginx event server configuration (nginx.conf).
|
||||
matrix_synapse_reverse_proxy_companion_event_additional_configuration_blocks: []
|
||||
|
||||
# A list of strings containing additional configuration blocks to add to the nginx http's server configuration (nginx-http.conf).
|
||||
matrix_synapse_reverse_proxy_companion_http_additional_server_configuration_blocks: []
|
||||
|
||||
# To increase request timeout in NGINX using proxy_read_timeout, proxy_connect_timeout, proxy_send_timeout, send_timeout directives
|
||||
# Nginx Default: proxy_connect_timeout 60s; #Defines a timeout for establishing a connection with a proxied server
|
||||
# Nginx Default: proxy_send_timeout 60s; #Sets a timeout for transmitting a request to the proxied server.
|
||||
# Nginx Default: proxy_read_timeout 60s; #Defines a timeout for reading a response from the proxied server.
|
||||
# Nginx Default: send_timeout 60s; #Sets a timeout for transmitting a response to the client.
|
||||
#
|
||||
# For more information visit:
|
||||
# http://nginx.org/en/docs/http/ngx_http_proxy_module.html
|
||||
# http://nginx.org/en/docs/http/ngx_http_core_module.html#send_timeout
|
||||
# https://www.nginx.com/resources/wiki/start/topics/examples/fullexample2/
|
||||
#
|
||||
# Here we are sticking with nginx default values change this value carefully.
|
||||
matrix_synapse_reverse_proxy_companion_proxy_connect_timeout: 60
|
||||
matrix_synapse_reverse_proxy_companion_proxy_send_timeout: 60
|
||||
matrix_synapse_reverse_proxy_companion_proxy_read_timeout: 60
|
||||
matrix_synapse_reverse_proxy_companion_send_timeout: 60
|
||||
|
||||
# For OCSP purposes, we need to define a resolver at the `server{}` level or `http{}` level (we do the latter).
|
||||
#
|
||||
# Otherwise, we get warnings like this:
|
||||
# > [warn] 22#22: no resolver defined to resolve r3.o.lencr.org while requesting certificate status, responder: r3.o.lencr.org, certificate: "/matrix/ssl/config/live/…/fullchain.pem"
|
||||
#
|
||||
# We point it to the internal Docker resolver, which likely delegates to nameservers defined in `/etc/resolv.conf`.
|
||||
matrix_synapse_reverse_proxy_companion_http_level_resolver: 127.0.0.11
|
||||
|
||||
matrix_synapse_reverse_proxy_companion_hostname: "matrix-synapse-reverse-proxy-companion"
|
||||
|
||||
# matrix_synapse_reverse_proxy_companion_client_api_addr specifies the address where the Client-Server API is
|
||||
matrix_synapse_reverse_proxy_companion_client_api_addr: 'matrix-synapse:{{ matrix_synapse_container_client_api_port }}'
|
||||
|
||||
# The maximum body size for client requests to any of the endpoints on the Client-Server API.
|
||||
# This needs to be equal or higher than the maximum upload size accepted by Synapse.
|
||||
matrix_synapse_reverse_proxy_companion_client_api_client_max_body_size_mb: "{{ matrix_synapse_max_upload_size_mb }}"
|
||||
|
||||
# The buffer size for client requests to any of the endpoints on the Client-Server API.
|
||||
matrix_synapse_reverse_proxy_companion_client_api_client_body_buffer_size_mb: "{{ matrix_synapse_reverse_proxy_companion_client_api_client_max_body_size_mb }}"
|
||||
|
||||
# matrix_synapse_reverse_proxy_companion_federation_api_enabled specifies whether reverse proxying for the Federation (Server-Server) API should be done
|
||||
matrix_synapse_reverse_proxy_companion_federation_api_enabled: true
|
||||
# matrix_synapse_reverse_proxy_companion_federation_api_addr specifies the address where the Federation (Server-Server) API is
|
||||
matrix_synapse_reverse_proxy_companion_federation_api_addr: 'matrix-synapse:{{ matrix_synapse_container_federation_api_plain_port }}'
|
||||
|
||||
# The maximum body size for client requests to any of the endpoints on the Federation API.
|
||||
# We auto-calculate this based on the Client-Server API's maximum body size, but use a minimum value to ensure we don't go to low.
|
||||
matrix_synapse_reverse_proxy_companion_federation_api_client_max_body_size_mb: "{{ [matrix_synapse_reverse_proxy_companion_federation_api_client_max_body_size_mb_minimum, (matrix_synapse_reverse_proxy_companion_client_api_client_max_body_size_mb | int) * 3] | max }}"
|
||||
matrix_synapse_reverse_proxy_companion_federation_api_client_max_body_size_mb_minimum: 100
|
||||
|
||||
# The buffer size for client requests to any of the endpoints on the Federation API.
|
||||
matrix_synapse_reverse_proxy_companion_federation_api_client_body_buffer_size_mb: "{{ matrix_synapse_reverse_proxy_companion_federation_api_client_max_body_size_mb }}"
|
||||
|
||||
# A list of strings containing additional configuration blocks to add to the nginx vhost handling the Synapse Client-Server API
|
||||
matrix_synapse_reverse_proxy_companion_synapse_client_api_additional_server_configuration_blocks: []
|
||||
|
||||
# A list of strings containing additional configuration blocks to add to the nginx vhost handling the Synapse Federation (Server-Server) API
|
||||
matrix_synapse_reverse_proxy_companion_synapse_federation_api_additional_server_configuration_blocks: []
|
||||
|
||||
|
||||
# synapse worker activation and endpoint mappings.
|
||||
# These are all populated via Ansible group variables.
|
||||
# (or fall back to role-level Synapse worker defaults when not overridden)
|
||||
matrix_synapse_reverse_proxy_companion_synapse_workers_enabled: "{{ matrix_synapse_workers_enabled }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_workers_list: "{{ matrix_synapse_workers_enabled_list }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_room_worker_client_server_locations: "{{ matrix_synapse_workers_room_worker_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_room_worker_federation_locations: "{{ matrix_synapse_workers_room_worker_federation_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_sync_worker_client_server_locations: "{{ matrix_synapse_workers_sync_worker_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_client_reader_client_server_locations: "{{ matrix_synapse_workers_client_reader_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_federation_reader_federation_locations: "{{ matrix_synapse_workers_federation_reader_federation_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_generic_worker_client_server_locations: "{{ matrix_synapse_workers_generic_worker_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_generic_worker_federation_locations: "{{ matrix_synapse_workers_generic_worker_federation_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_stream_writer_typing_stream_worker_client_server_locations: "{{ matrix_synapse_workers_stream_writer_typing_stream_worker_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_stream_writer_to_device_stream_worker_client_server_locations: "{{ matrix_synapse_workers_stream_writer_to_device_stream_worker_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_stream_writer_account_data_stream_worker_client_server_locations: "{{ matrix_synapse_workers_stream_writer_account_data_stream_worker_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_stream_writer_receipts_stream_worker_client_server_locations: "{{ matrix_synapse_workers_stream_writer_receipts_stream_worker_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_stream_writer_presence_stream_worker_client_server_locations: "{{ matrix_synapse_workers_stream_writer_presence_stream_worker_client_server_endpoints }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_media_repository_locations: "{{ matrix_synapse_workers_media_repository_endpoints | default([]) }}"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_user_dir_locations: "{{ matrix_synapse_workers_user_dir_worker_client_server_endpoints | default([]) }}"
|
||||
matrix_synapse_reverse_proxy_companion_client_server_main_override_locations_regex: ^/_matrix/client/(api/v1|r0|v3|unstable)/(account/3pid/|directory/list/room/|pushrules/|rooms/[^/]+/(forget|upgrade|report)|login/sso/redirect/|register)
|
||||
matrix_synapse_reverse_proxy_companion_client_server_sso_override_locations_regex: ^(/_matrix/client/(api/v1|r0|v3|unstable)/login/sso/redirect|/_synapse/client/(pick_username|(new_user_consent|oidc/callback|pick_idp|sso_register)$))
|
||||
# Related to MSC4108 (https://github.com/matrix-org/matrix-spec-proposals/pull/4108)
|
||||
matrix_synapse_reverse_proxy_companion_client_server_qr_code_login_locations_regex: ^(/_matrix/client/(unstable|v1)/org.matrix.msc4108/rendezvous|/_synapse/client/rendezvous)$
|
||||
|
||||
matrix_synapse_reverse_proxy_companion_federation_override_locations_regex: ^/_matrix/federation/v1/openid/userinfo$
|
||||
|
||||
# synapse content caching
|
||||
matrix_synapse_reverse_proxy_companion_synapse_cache_enabled: false
|
||||
matrix_synapse_reverse_proxy_companion_synapse_cache_path: /tmp/synapse-cache
|
||||
matrix_synapse_reverse_proxy_companion_synapse_cache_keys_zone_name: "STATIC"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_cache_keys_zone_size: "10m"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_cache_inactive_time: "48h"
|
||||
matrix_synapse_reverse_proxy_companion_synapse_cache_max_size_mb: 1024
|
||||
matrix_synapse_reverse_proxy_companion_synapse_cache_proxy_cache_valid_time: "24h"
|
||||
|
||||
|
||||
# Controls whether matrix-synapse-reverse-proxy-companion trusts an upstream server's X-Forwarded-Proto header.
|
||||
# The `matrix-synapse-reverse-proxy-companion` does not terminate SSL and always expects to be fronted by another reverse-proxy server.
|
||||
# As such, it trusts the protocol scheme forwarded by the upstream proxy.
|
||||
matrix_synapse_reverse_proxy_companion_trust_forwarded_proto: true
|
||||
matrix_synapse_reverse_proxy_companion_x_forwarded_proto_value: "{{ '$http_x_forwarded_proto' if matrix_synapse_reverse_proxy_companion_trust_forwarded_proto else '$scheme' }}"
|
||||
|
||||
########################################################################################
|
||||
# #
|
||||
# /Synapse reverse-proxy companion core settings #
|
||||
# #
|
||||
########################################################################################
|
||||
|
||||
|
||||
########################################################################################
|
||||
# #
|
||||
# njs module #
|
||||
# #
|
||||
########################################################################################
|
||||
|
||||
# Controls whether the njs module is loaded.
|
||||
matrix_synapse_reverse_proxy_companion_njs_enabled: "{{ matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_enabled }}"
|
||||
|
||||
########################################################################################
|
||||
# #
|
||||
# /njs module #
|
||||
# #
|
||||
########################################################################################
|
||||
|
||||
|
||||
########################################################################################
|
||||
# #
|
||||
# Whoami-based sync worker routing #
|
||||
# #
|
||||
########################################################################################
|
||||
|
||||
# Controls whether the whoami-based sync worker router is enabled.
|
||||
# When enabled, the reverse proxy will call Synapse's /_matrix/client/v3/account/whoami endpoint
|
||||
# to resolve access tokens to usernames, allowing consistent routing of requests from the same user
|
||||
# to the same sync worker regardless of which device or token they use.
|
||||
#
|
||||
# This works with any authentication system (native Synapse auth, MAS, etc.) because Synapse
|
||||
# handles the token validation internally.
|
||||
#
|
||||
# Enabled by default when there are sync workers, because sync workers benefit from user-level
|
||||
# stickiness due to their per-user in-memory caches.
|
||||
matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_enabled: "{{ matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'sync_worker') | list | length > 0 }}"
|
||||
|
||||
# The whoami endpoint path (Matrix spec endpoint).
|
||||
matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_endpoint: /_matrix/client/v3/account/whoami
|
||||
|
||||
# The full URL to the whoami endpoint.
|
||||
matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_url: "http://{{ matrix_synapse_reverse_proxy_companion_client_api_addr }}{{ matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_endpoint }}"
|
||||
|
||||
# Cache duration (in seconds) for whoami lookup results.
|
||||
# Token -> username mappings are cached to avoid repeated whoami calls.
|
||||
# A longer TTL reduces load on Synapse but means username changes take longer to take effect.
|
||||
matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_cache_ttl_seconds: 3600
|
||||
|
||||
# Size of the shared memory zone for caching whoami results (in megabytes).
|
||||
# Each cached entry is approximately 100-200 bytes.
|
||||
matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_cache_size_mb: 1
|
||||
|
||||
# Controls whether verbose logging is enabled for the whoami sync worker router.
|
||||
# When enabled, logs cache hits/misses and routing decisions.
|
||||
# Useful for debugging, but should be disabled in production.
|
||||
matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_logging_enabled: false
|
||||
|
||||
# The length of the access token to show in logs when logging is enabled.
|
||||
# Keeping this short is a good idea from a security perspective.
|
||||
matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_logging_token_length: 12
|
||||
|
||||
# Controls whether debug response headers are added to sync requests.
|
||||
# When enabled, adds X-Sync-Worker-Router-User-Identifier and X-Sync-Worker-Router-Upstream headers.
|
||||
# Useful for debugging routing behavior, but should be disabled in production.
|
||||
matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_debug_headers_enabled: false
|
||||
|
||||
########################################################################################
|
||||
# #
|
||||
# /Whoami-based sync worker routing #
|
||||
# #
|
||||
########################################################################################
|
||||
|
||||
# matrix_synapse_reverse_proxy_companion_restart_necessary controls whether the service
|
||||
# will be restarted (when true) or merely started (when false) by the
|
||||
# systemd service manager role (when conditional restart is enabled).
|
||||
#
|
||||
# This value is automatically computed during installation based on whether
|
||||
# any configuration files, the systemd service file, or the container image changed.
|
||||
# The default of `false` means "no restart needed" — appropriate when the role's
|
||||
# installation tasks haven't run (e.g., due to --tags skipping them).
|
||||
matrix_synapse_reverse_proxy_companion_restart_necessary: false
|
||||
|
||||
@@ -30,11 +30,13 @@ SPDX-FileCopyrightText: 2022 Quentin Young
|
||||
SPDX-FileCopyrightText: 2022 Shaleen Jain
|
||||
SPDX-FileCopyrightText: 2022 Yan Minagawa
|
||||
SPDX-FileCopyrightText: 2023 - 2024 Michael Hollister
|
||||
SPDX-FileCopyrightText: 2023 Dan Arnfield
|
||||
SPDX-FileCopyrightText: 2023 Aeris One
|
||||
SPDX-FileCopyrightText: 2023 Luke D Iremadze
|
||||
SPDX-FileCopyrightText: 2023 Samuel Meenzen
|
||||
SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
|
||||
SPDX-FileCopyrightText: 2024 Charles Wright
|
||||
SPDX-FileCopyrightText: 2025 Catalan Lover <catalanlover@protonmail.com>
|
||||
SPDX-FileCopyrightText: 2024 David Mehren
|
||||
SPDX-FileCopyrightText: 2024 - 2025 Catalan Lover <catalanlover@protonmail.com>
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -47,6 +47,16 @@
|
||||
# This always runs because it handles uninstallation for sub-components too.
|
||||
- ansible.builtin.include_tasks: "{{ role_path }}/tasks/setup_uninstall.yml"
|
||||
|
||||
- tags:
|
||||
- setup-all
|
||||
- setup-synapse-reverse-proxy-companion
|
||||
- setup-synapse
|
||||
- install-all
|
||||
- install-synapse-reverse-proxy-companion
|
||||
- install-synapse
|
||||
block:
|
||||
- ansible.builtin.include_tasks: "{{ role_path }}/tasks/reverse_proxy_companion/main.yml"
|
||||
|
||||
- tags:
|
||||
- import-synapse-media-store
|
||||
block:
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# SPDX-FileCopyrightText: 2022 - 2024 Slavi Pantaleev
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
---
|
||||
|
||||
- tags:
|
||||
- setup-all
|
||||
- setup-synapse-reverse-proxy-companion
|
||||
- setup-synapse
|
||||
- install-all
|
||||
- install-synapse-reverse-proxy-companion
|
||||
- install-synapse
|
||||
block:
|
||||
- when: matrix_synapse_reverse_proxy_companion_enabled | bool
|
||||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/reverse_proxy_companion/validate_config.yml"
|
||||
|
||||
- when: matrix_synapse_reverse_proxy_companion_enabled | bool
|
||||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/reverse_proxy_companion/setup_install.yml"
|
||||
|
||||
- tags:
|
||||
- setup-all
|
||||
- setup-synapse-reverse-proxy-companion
|
||||
- setup-synapse
|
||||
block:
|
||||
- when: not matrix_synapse_reverse_proxy_companion_enabled | bool
|
||||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/reverse_proxy_companion/setup_uninstall.yml"
|
||||
@@ -0,0 +1,86 @@
|
||||
# SPDX-FileCopyrightText: 2022 - 2024 Slavi Pantaleev
|
||||
# SPDX-FileCopyrightText: 2024 David Mehren
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
---
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion paths exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: directory
|
||||
mode: '0750'
|
||||
owner: "{{ matrix_user_name }}"
|
||||
group: "{{ matrix_group_name }}"
|
||||
with_items:
|
||||
- {path: "{{ matrix_synapse_reverse_proxy_companion_base_path }}", when: true}
|
||||
- {path: "{{ matrix_synapse_reverse_proxy_companion_confd_path }}", when: true}
|
||||
- {path: "{{ matrix_synapse_reverse_proxy_companion_njs_path }}", when: "{{ matrix_synapse_reverse_proxy_companion_njs_enabled }}"}
|
||||
when: item.when | bool
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion is configured
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ item.dest }}"
|
||||
owner: "{{ matrix_user_name }}"
|
||||
group: "{{ matrix_group_name }}"
|
||||
mode: '0644'
|
||||
with_items:
|
||||
- src: "{{ role_path }}/templates/reverse_proxy_companion/nginx/nginx.conf.j2"
|
||||
dest: "{{ matrix_synapse_reverse_proxy_companion_base_path }}/nginx.conf"
|
||||
- src: "{{ role_path }}/templates/reverse_proxy_companion/nginx/conf.d/nginx-http.conf.j2"
|
||||
dest: "{{ matrix_synapse_reverse_proxy_companion_confd_path }}/nginx-http.conf"
|
||||
- src: "{{ role_path }}/templates/reverse_proxy_companion/nginx/conf.d/matrix-synapse-reverse-proxy-companion.conf.j2"
|
||||
dest: "{{ matrix_synapse_reverse_proxy_companion_confd_path }}/matrix-synapse-reverse-proxy-companion.conf"
|
||||
- src: "{{ role_path }}/templates/reverse_proxy_companion/labels.j2"
|
||||
dest: "{{ matrix_synapse_reverse_proxy_companion_base_path }}/labels"
|
||||
register: matrix_synapse_reverse_proxy_companion_config_result
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion whoami sync worker router njs script is deployed
|
||||
ansible.builtin.template:
|
||||
src: "{{ role_path }}/templates/reverse_proxy_companion/nginx/njs/whoami_sync_worker_router.js.j2"
|
||||
dest: "{{ matrix_synapse_reverse_proxy_companion_njs_path }}/whoami_sync_worker_router.js"
|
||||
owner: "{{ matrix_user_name }}"
|
||||
group: "{{ matrix_group_name }}"
|
||||
mode: '0644'
|
||||
when: matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_enabled | bool
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion njs path is removed when njs is disabled
|
||||
ansible.builtin.file:
|
||||
path: "{{ matrix_synapse_reverse_proxy_companion_njs_path }}"
|
||||
state: absent
|
||||
when: not matrix_synapse_reverse_proxy_companion_njs_enabled
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion nginx container image is pulled
|
||||
community.docker.docker_image:
|
||||
name: "{{ matrix_synapse_reverse_proxy_companion_container_image }}"
|
||||
source: "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}"
|
||||
force_source: "{{ matrix_synapse_reverse_proxy_companion_container_image_force_pull if ansible_version.major > 2 or ansible_version.minor >= 8 else omit }}"
|
||||
force: "{{ omit if ansible_version.major > 2 or ansible_version.minor >= 8 else matrix_synapse_reverse_proxy_companion_container_image_force_pull }}"
|
||||
register: matrix_synapse_reverse_proxy_companion_container_image_pull_result
|
||||
retries: "{{ devture_playbook_help_container_retries_count }}"
|
||||
delay: "{{ devture_playbook_help_container_retries_delay }}"
|
||||
until: matrix_synapse_reverse_proxy_companion_container_image_pull_result is not failed
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion container network is created
|
||||
community.general.docker_network:
|
||||
enable_ipv6: "{{ devture_systemd_docker_base_ipv6_enabled }}"
|
||||
name: "{{ matrix_synapse_reverse_proxy_companion_container_network }}"
|
||||
driver: bridge
|
||||
driver_options: "{{ devture_systemd_docker_base_container_networks_driver_options }}"
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion.service installed
|
||||
ansible.builtin.template:
|
||||
src: "{{ role_path }}/templates/reverse_proxy_companion/systemd/matrix-synapse-reverse-proxy-companion.service.j2"
|
||||
dest: "{{ devture_systemd_docker_base_systemd_path }}/matrix-synapse-reverse-proxy-companion.service"
|
||||
mode: '0644'
|
||||
register: matrix_synapse_reverse_proxy_companion_systemd_service_result
|
||||
|
||||
- name: Determine whether Synapse reverse-proxy companion needs a restart
|
||||
ansible.builtin.set_fact:
|
||||
matrix_synapse_reverse_proxy_companion_restart_necessary: >-
|
||||
{{
|
||||
matrix_synapse_reverse_proxy_companion_config_result.changed | default(false)
|
||||
or matrix_synapse_reverse_proxy_companion_systemd_service_result.changed | default(false)
|
||||
or matrix_synapse_reverse_proxy_companion_container_image_pull_result.changed | default(false)
|
||||
}}
|
||||
@@ -0,0 +1,29 @@
|
||||
# SPDX-FileCopyrightText: 2022 - 2023 Slavi Pantaleev
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
---
|
||||
|
||||
- name: Check existence of matrix-synapse-reverse-proxy-companion service
|
||||
ansible.builtin.stat:
|
||||
path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-synapse-reverse-proxy-companion.service"
|
||||
register: matrix_synapse_reverse_proxy_companion_service_stat
|
||||
|
||||
- when: matrix_synapse_reverse_proxy_companion_service_stat.stat.exists | bool
|
||||
block:
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion.service is stopped
|
||||
ansible.builtin.service:
|
||||
name: matrix-synapse-reverse-proxy-companion
|
||||
state: stopped
|
||||
enabled: false
|
||||
daemon_reload: true
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion.service doesn't exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-synapse-reverse-proxy-companion.service"
|
||||
state: absent
|
||||
|
||||
- name: Ensure matrix-synapse-reverse-proxy-companion data deleted
|
||||
ansible.builtin.file:
|
||||
path: "{{ matrix_synapse_reverse_proxy_companion_base_path }}"
|
||||
state: absent
|
||||
@@ -0,0 +1,27 @@
|
||||
# SPDX-FileCopyrightText: 2024 Slavi Pantaleev
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
---
|
||||
|
||||
- name: Fail if required matrix-synapse-reverse-proxy-companion settings not defined
|
||||
ansible.builtin.fail:
|
||||
msg: >-
|
||||
You need to define a required configuration setting (`{{ item.name }}`).
|
||||
when: "item.when | bool and lookup('vars', item.name, default='') | string | length == 0"
|
||||
with_items:
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_network', when: true}
|
||||
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_hostname', when: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_enabled }}"}
|
||||
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_hostname', when: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_enabled }}"}
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_hostname', when: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_enabled }}"}
|
||||
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_hostname', when: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_enabled }}"}
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_entrypoints', when: "{{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_enabled }}"}
|
||||
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_entrypoints', when: "{{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_enabled }}"}
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_entrypoints', when: "{{ matrix_synapse_container_labels_internal_client_synapse_admin_api_enabled }}"}
|
||||
|
||||
|
||||
- {'name': 'matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_name', when: "{{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_enabled }}"}
|
||||
@@ -0,0 +1,224 @@
|
||||
{#
|
||||
SPDX-FileCopyrightText: 2024 Slavi Pantaleev
|
||||
SPDX-FileCopyrightText: 2024 - 2025 Catalan Lover <catalanlover@protonmail.com>
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_traefik_enabled %}
|
||||
traefik.enable=true
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_traefik_docker_network %}
|
||||
traefik.docker.network={{ matrix_synapse_reverse_proxy_companion_container_labels_traefik_docker_network }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.services.matrix-synapse-reverse-proxy-companion-client-api.loadbalancer.server.port=8008
|
||||
traefik.http.services.matrix-synapse-reverse-proxy-companion-federation-api.loadbalancer.server.port=8048
|
||||
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_enabled %}
|
||||
############################################################
|
||||
# #
|
||||
# Public Client-API (/_matrix) #
|
||||
# #
|
||||
############################################################
|
||||
|
||||
{% set client_api_middlewares = [] %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_enabled %}
|
||||
{% set client_api_middlewares = client_api_middlewares + [matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_name] %}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-api.rule={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_rule }}
|
||||
|
||||
{% if client_api_middlewares | length > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-api.middlewares={{ client_api_middlewares | join(',') }}
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_priority | int > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-api.priority={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_priority }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-api.service=matrix-synapse-reverse-proxy-companion-client-api
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-api.entrypoints={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_entrypoints }}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-api.tls={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_tls | to_json }}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_tls %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-api.tls.certResolver={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_api_traefik_tls_certResolver }}
|
||||
{% endif %}
|
||||
|
||||
############################################################
|
||||
# #
|
||||
# /Public Client-API (/_matrix) #
|
||||
# #
|
||||
############################################################
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_enabled %}
|
||||
############################################################
|
||||
# #
|
||||
# Internal Client-API (/_matrix) #
|
||||
# #
|
||||
############################################################
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-internal-client-api.rule={{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_rule }}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_priority | int > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-internal-client-api.priority={{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_priority }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-internal-client-api.service=matrix-synapse-reverse-proxy-companion-client-api
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-internal-client-api.entrypoints={{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_api_traefik_entrypoints }}
|
||||
|
||||
############################################################
|
||||
# #
|
||||
# /Internal Client-API (/_matrix) #
|
||||
# #
|
||||
############################################################
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_enabled %}
|
||||
############################################################
|
||||
# #
|
||||
# Public Synapse Client API (/_synapse/client) #
|
||||
# #
|
||||
############################################################
|
||||
|
||||
{% set synapse_client_api_middlewares = [] %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_enabled %}
|
||||
{% set synapse_client_api_middlewares = synapse_client_api_middlewares + [matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_name] %}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-client-api.rule={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_rule }}
|
||||
|
||||
{% if synapse_client_api_middlewares | length > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-client-api.middlewares={{ synapse_client_api_middlewares | join(',') }}
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_priority | int > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-client-api.priority={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_priority }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-client-api.service=matrix-synapse-reverse-proxy-companion-client-api
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-client-api.entrypoints={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_entrypoints }}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-client-api.tls={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_tls | to_json }}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_tls %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-client-api.tls.certResolver={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_client_api_traefik_tls_certResolver }}
|
||||
{% endif %}
|
||||
|
||||
############################################################
|
||||
# #
|
||||
# /Public Synapse Client API (/_synapse/client) #
|
||||
# #
|
||||
############################################################
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_enabled %}
|
||||
############################################################
|
||||
# #
|
||||
# Public Synapse Admin API (/_synapse/admin) #
|
||||
# #
|
||||
############################################################
|
||||
|
||||
{% set synapse_admin_api_middlewares = [] %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_enabled %}
|
||||
{% set synapse_admin_api_middlewares = synapse_admin_api_middlewares + [matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_name] %}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-admin-api.rule={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_rule }}
|
||||
|
||||
{% if synapse_admin_api_middlewares | length > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-admin-api.middlewares={{ synapse_admin_api_middlewares | join(',') }}
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_priority | int > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-admin-api.priority={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_priority }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-admin-api.service=matrix-synapse-reverse-proxy-companion-client-api
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-admin-api.entrypoints={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_entrypoints }}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-admin-api.tls={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_tls | to_json }}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_tls %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-admin-api.tls.certResolver={{ matrix_synapse_reverse_proxy_companion_container_labels_public_client_synapse_admin_api_traefik_tls_certResolver }}
|
||||
{% endif %}
|
||||
|
||||
############################################################
|
||||
# #
|
||||
# /Public Synapse Admin API (/_synapse/admin) #
|
||||
# #
|
||||
############################################################
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_enabled %}
|
||||
############################################################
|
||||
# #
|
||||
# Internal Synapse Admin API (/_synapse/admin) #
|
||||
# #
|
||||
############################################################
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-internal-client-synapse-admin-api.rule={{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_rule }}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_priority | int > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-client-synapse-admin-api.priority={{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_priority }}
|
||||
{% endif %}
|
||||
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-internal-client-synapse-admin-api.service=matrix-synapse-reverse-proxy-companion-client-api
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-internal-client-synapse-admin-api.entrypoints={{ matrix_synapse_reverse_proxy_companion_container_labels_internal_client_synapse_admin_api_traefik_entrypoints }}
|
||||
|
||||
############################################################
|
||||
# #
|
||||
# /Internal Synapse Admin API (/_synapse/admin) #
|
||||
# #
|
||||
############################################################
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_enabled %}
|
||||
############################################################
|
||||
# #
|
||||
# Public Federation-API (/_matrix) #
|
||||
# #
|
||||
############################################################
|
||||
|
||||
{% set federation_api_middlewares = [] %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_enabled %}
|
||||
{% set federation_api_middlewares = federation_api_middlewares + [matrix_synapse_reverse_proxy_companion_container_labels_traefik_compression_middleware_name] %}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-federation-api.rule={{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_rule }}
|
||||
|
||||
{% if federation_api_middlewares | length > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-federation-api.middlewares={{ federation_api_middlewares | join(',') }}
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_priority | int > 0 %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-federation-api.priority={{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_priority }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-federation-api.service=matrix-synapse-reverse-proxy-companion-federation-api
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-federation-api.entrypoints={{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_entrypoints }}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-federation-api.tls={{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_tls | to_json }}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_tls %}
|
||||
traefik.http.routers.matrix-synapse-reverse-proxy-companion-public-federation-api.tls.certResolver={{ matrix_synapse_reverse_proxy_companion_container_labels_public_federation_api_traefik_tls_certResolver }}
|
||||
{% endif %}
|
||||
|
||||
############################################################
|
||||
# #
|
||||
# /Public Federation-API (/_matrix) #
|
||||
# #
|
||||
############################################################
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endif %}
|
||||
|
||||
{{ matrix_synapse_reverse_proxy_companion_container_labels_additional_labels }}
|
||||
@@ -0,0 +1,354 @@
|
||||
#jinja2: lstrip_blocks: True
|
||||
|
||||
{% set room_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'room_worker') | list %}
|
||||
{% set sync_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'sync_worker') | list %}
|
||||
{% set client_reader_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'client_reader') | list %}
|
||||
{% set federation_reader_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'federation_reader') | list %}
|
||||
{% set generic_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'generic_worker') | list %}
|
||||
{% set stream_writer_typing_stream_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'stream_writer') | selectattr('stream_writer_stream', 'equalto', 'typing') | list %}
|
||||
{% set stream_writer_to_device_stream_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'stream_writer') | selectattr('stream_writer_stream', 'equalto', 'to_device') | list %}
|
||||
{% set stream_writer_account_data_stream_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'stream_writer') | selectattr('stream_writer_stream', 'equalto', 'account_data') | list %}
|
||||
{% set stream_writer_receipts_stream_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'stream_writer') | selectattr('stream_writer_stream', 'equalto', 'receipts') | list %}
|
||||
{% set stream_writer_presence_stream_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'stream_writer') | selectattr('stream_writer_stream', 'equalto', 'presence') | list %}
|
||||
{% set media_repository_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'media_repository') | list %}
|
||||
{% set user_dir_workers = matrix_synapse_reverse_proxy_companion_synapse_workers_list | selectattr('type', 'equalto', 'user_dir') | list %}
|
||||
|
||||
{% macro render_worker_upstream(name, workers, load_balance) %}
|
||||
upstream {{ name }} {
|
||||
{#
|
||||
We need to use a zone so that the upstream is stored in shared memory,
|
||||
otherwise we can't use `resolve` below, as reported by nginx:
|
||||
> resolving names at run time requires upstream ".." in ... to be in shared memory
|
||||
#}
|
||||
zone {{ name }} 64k;
|
||||
|
||||
{{ load_balance }}
|
||||
keepalive {{ ((workers | length) * 2) | string }};
|
||||
resolver {{ matrix_synapse_reverse_proxy_companion_http_level_resolver }} valid=5s;
|
||||
{% for worker in workers %}
|
||||
server "{{ worker.name }}:{{ worker.port }}" resolve;
|
||||
{% endfor %}
|
||||
}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_locations_to_upstream(locations, upstream_name) %}
|
||||
{% for location in locations %}
|
||||
location ~ {{ location }} {
|
||||
proxy_pass http://{{ upstream_name }}$request_uri;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_locations_to_upstream_with_whoami_sync_worker_router(locations, upstream_name) %}
|
||||
{% for location in locations %}
|
||||
location ~ {{ location }} {
|
||||
# Use auth_request to call the whoami sync worker router.
|
||||
# The handler resolves the access token to a user identifier and returns it
|
||||
# in the X-User-Identifier header, which is then used for upstream hashing.
|
||||
auth_request /_whoami_sync_worker_router;
|
||||
auth_request_set $user_identifier $sent_http_x_user_identifier;
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_debug_headers_enabled %}
|
||||
add_header X-Sync-Worker-Router-User-Identifier $user_identifier always;
|
||||
add_header X-Sync-Worker-Router-Upstream $upstream_addr always;
|
||||
{% endif %}
|
||||
|
||||
proxy_pass http://{{ upstream_name }}$request_uri;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_synapse_workers_enabled %}
|
||||
|
||||
# Whether to upgrade HTTP connection
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
#Extract room name from URI
|
||||
map $request_uri $room_name {
|
||||
~^/_matrix/(client|federation)/.*?(?:%21|!)(?<room>[A-Za-z0-9._=\-\/]+)(?::|%3A)[A-Za-z0-9._=\-\/]+ $room;
|
||||
}
|
||||
# End maps
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_synapse_cache_enabled %}
|
||||
proxy_cache_path {{ matrix_synapse_reverse_proxy_companion_synapse_cache_path }} levels=1:2 keys_zone={{ matrix_synapse_reverse_proxy_companion_synapse_cache_keys_zone_name }}:{{ matrix_synapse_reverse_proxy_companion_synapse_cache_keys_zone_size }} inactive={{ matrix_synapse_reverse_proxy_companion_synapse_cache_inactive_time }} max_size={{ matrix_synapse_reverse_proxy_companion_synapse_cache_max_size_mb }}m;
|
||||
{% endif %}
|
||||
# Round Robin "upstream" pools for workers
|
||||
|
||||
{% if room_workers | length > 0 %}
|
||||
{{- render_worker_upstream('room_workers_upstream', room_workers, 'hash $room_name consistent;') }}
|
||||
{% endif %}
|
||||
|
||||
{% if sync_workers | length > 0 %}
|
||||
{{- render_worker_upstream('sync_workers_upstream', sync_workers, 'hash $user_identifier consistent;') }}
|
||||
{% endif %}
|
||||
|
||||
{% if client_reader_workers | length > 0 %}
|
||||
{{- render_worker_upstream('client_reader_workers_upstream', client_reader_workers, 'least_conn;') }}
|
||||
{% endif %}
|
||||
|
||||
{% if federation_reader_workers | length > 0 %}
|
||||
{{- render_worker_upstream('federation_reader_workers_upstream', federation_reader_workers, 'hash $http_x_forwarded_for;') }}
|
||||
{% endif %}
|
||||
|
||||
{% if generic_workers | length > 0 %}
|
||||
{{- render_worker_upstream('generic_workers_upstream', generic_workers, 'hash $http_x_forwarded_for;') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_typing_stream_workers | length > 0 %}
|
||||
{{- render_worker_upstream('stream_writer_typing_stream_workers_upstream', stream_writer_typing_stream_workers, '') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_to_device_stream_workers | length > 0 %}
|
||||
{{- render_worker_upstream('stream_writer_to_device_stream_workers_upstream', stream_writer_to_device_stream_workers, '') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_account_data_stream_workers | length > 0 %}
|
||||
{{- render_worker_upstream('stream_writer_account_data_stream_workers_upstream', stream_writer_account_data_stream_workers, '') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_receipts_stream_workers | length > 0 %}
|
||||
{{- render_worker_upstream('stream_writer_receipts_stream_workers_upstream', stream_writer_receipts_stream_workers, '') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_presence_stream_workers | length > 0 %}
|
||||
{{- render_worker_upstream('stream_writer_presence_stream_workers_upstream', stream_writer_presence_stream_workers, '') }}
|
||||
{% endif %}
|
||||
|
||||
{% if media_repository_workers | length > 0 %}
|
||||
{{- render_worker_upstream('media_repository_workers_upstream', media_repository_workers, 'least_conn;') }}
|
||||
{% endif %}
|
||||
|
||||
{% if user_dir_workers | length > 0 %}
|
||||
{{- render_worker_upstream('user_dir_workers_upstream', user_dir_workers, '') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
server {
|
||||
listen 8008;
|
||||
server_name {{ matrix_synapse_reverse_proxy_companion_hostname }};
|
||||
|
||||
server_tokens off;
|
||||
root /dev/null;
|
||||
|
||||
client_max_body_size {{ matrix_synapse_reverse_proxy_companion_client_api_client_max_body_size_mb }}M;
|
||||
client_body_buffer_size {{ matrix_synapse_reverse_proxy_companion_client_api_client_body_buffer_size_mb }}M;
|
||||
|
||||
proxy_buffering on;
|
||||
proxy_max_temp_file_size 0;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_enabled %}
|
||||
# Internal location for whoami-based sync worker routing.
|
||||
# This is called via auth_request from sync worker locations.
|
||||
# The njs handler calls the whoami endpoint to resolve access tokens to usernames,
|
||||
# then returns the username in the X-User-Identifier header for upstream hashing.
|
||||
location = /_whoami_sync_worker_router {
|
||||
internal;
|
||||
js_content whoami_sync_worker_router.handleAuthRequest;
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_synapse_workers_enabled %}
|
||||
# Client-server overrides — These locations must go to the main Synapse process
|
||||
location ~ {{ matrix_synapse_reverse_proxy_companion_client_server_main_override_locations_regex }} {
|
||||
{# FIXME: This block was copied from the main Synapse fallback below. It would be better to have it in one place and avoid duplication. #}
|
||||
{# Use the embedded DNS resolver in Docker containers to discover the service #}
|
||||
resolver {{ matrix_synapse_reverse_proxy_companion_http_level_resolver }} valid=5s;
|
||||
set $backend "{{ matrix_synapse_reverse_proxy_companion_client_api_addr }}";
|
||||
proxy_pass http://$backend;
|
||||
}
|
||||
|
||||
# Client-server SSO overrides — These locations must go to the main Synapse process
|
||||
location ~ {{ matrix_synapse_reverse_proxy_companion_client_server_sso_override_locations_regex }} {
|
||||
{# FIXME: This block was copied from the main Synapse fallback below. It would be better to have it in one place and avoid duplication. #}
|
||||
{# Use the embedded DNS resolver in Docker containers to discover the service #}
|
||||
resolver {{ matrix_synapse_reverse_proxy_companion_http_level_resolver }} valid=5s;
|
||||
set $backend "{{ matrix_synapse_reverse_proxy_companion_client_api_addr }}";
|
||||
proxy_pass http://$backend;
|
||||
}
|
||||
|
||||
# QR code login (`rendezvous`) locations need to go to the same Synapse process.
|
||||
# It doesn't necessarily need to be the main process, but it needs to be consistent.
|
||||
# For simplicity, we'll send them to the main process though.
|
||||
location ~ {{ matrix_synapse_reverse_proxy_companion_client_server_qr_code_login_locations_regex }} {
|
||||
{# FIXME: This block was copied from the main Synapse fallback below. It would be better to have it in one place and avoid duplication. #}
|
||||
{# Use the embedded DNS resolver in Docker containers to discover the service #}
|
||||
resolver {{ matrix_synapse_reverse_proxy_companion_http_level_resolver }} valid=5s;
|
||||
set $backend "{{ matrix_synapse_reverse_proxy_companion_client_api_addr }}";
|
||||
proxy_pass http://$backend;
|
||||
}
|
||||
|
||||
{# Workers redirects BEGIN #}
|
||||
|
||||
{% if generic_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#synapseappgeneric_worker
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_generic_worker_client_server_locations, 'generic_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_typing_stream_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#the-typing-stream
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_stream_writer_typing_stream_worker_client_server_locations, 'stream_writer_typing_stream_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_to_device_stream_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#the-to_device-stream
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_stream_writer_to_device_stream_worker_client_server_locations, 'stream_writer_to_device_stream_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_account_data_stream_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#the-account_data-stream
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_stream_writer_account_data_stream_worker_client_server_locations, 'stream_writer_account_data_stream_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_receipts_stream_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#the-receipts-stream
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_stream_writer_receipts_stream_worker_client_server_locations, 'stream_writer_receipts_stream_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if stream_writer_presence_stream_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#the-presence-stream
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_stream_writer_presence_stream_worker_client_server_locations, 'stream_writer_presence_stream_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if room_workers | length > 0 %}
|
||||
# room workers
|
||||
# https://tcpipuk.github.io/synapse/deployment/workers.html
|
||||
# https://tcpipuk.github.io/synapse/deployment/nginx.html#locationsconf
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_room_worker_client_server_locations, 'room_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if sync_workers | length > 0 %}
|
||||
# sync workers
|
||||
# https://tcpipuk.github.io/synapse/deployment/workers.html
|
||||
# https://tcpipuk.github.io/synapse/deployment/nginx.html#locationsconf
|
||||
{{ render_locations_to_upstream_with_whoami_sync_worker_router(matrix_synapse_reverse_proxy_companion_synapse_sync_worker_client_server_locations, 'sync_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if client_reader_workers | length > 0 %}
|
||||
# client_reader workers
|
||||
# https://tcpipuk.github.io/synapse/deployment/workers.html
|
||||
# https://tcpipuk.github.io/synapse/deployment/nginx.html#locationsconf
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_client_reader_client_server_locations, 'client_reader_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if media_repository_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#synapseappmedia_repository
|
||||
{% for location in matrix_synapse_reverse_proxy_companion_synapse_media_repository_locations %}
|
||||
location ~ {{ location }} {
|
||||
proxy_pass http://media_repository_workers_upstream$request_uri;
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_synapse_cache_enabled %}
|
||||
proxy_cache {{ matrix_synapse_reverse_proxy_companion_synapse_cache_keys_zone_name }};
|
||||
proxy_cache_valid any {{ matrix_synapse_reverse_proxy_companion_synapse_cache_proxy_cache_valid_time }};
|
||||
proxy_force_ranges on;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
{% endif %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if user_dir_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#updating-the-user-directory
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_user_dir_locations, 'user_dir_workers_upstream') }}
|
||||
{% endif %}
|
||||
{# Workers redirects END #}
|
||||
{% endif %}
|
||||
|
||||
{% for configuration_block in matrix_synapse_reverse_proxy_companion_synapse_client_api_additional_server_configuration_blocks %}
|
||||
{{- configuration_block }}
|
||||
{% endfor %}
|
||||
|
||||
{# Everything else just goes to the API server ##}
|
||||
location / {
|
||||
{# Use the embedded DNS resolver in Docker containers to discover the service #}
|
||||
resolver {{ matrix_synapse_reverse_proxy_companion_http_level_resolver }} valid=5s;
|
||||
set $backend "{{ matrix_synapse_reverse_proxy_companion_client_api_addr }}";
|
||||
proxy_pass http://$backend;
|
||||
}
|
||||
}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_federation_api_enabled %}
|
||||
server {
|
||||
listen 8048;
|
||||
server_name {{ matrix_synapse_reverse_proxy_companion_hostname }};
|
||||
|
||||
server_tokens off;
|
||||
root /dev/null;
|
||||
|
||||
client_max_body_size {{ matrix_synapse_reverse_proxy_companion_federation_api_client_max_body_size_mb }}M;
|
||||
client_body_buffer_size {{ matrix_synapse_reverse_proxy_companion_federation_api_client_body_buffer_size_mb }}M;
|
||||
|
||||
proxy_buffering on;
|
||||
proxy_max_temp_file_size 0;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_synapse_workers_enabled %}
|
||||
# Federation overrides — These locations must go to the main Synapse process
|
||||
location ~ {{ matrix_synapse_reverse_proxy_companion_federation_override_locations_regex }} {
|
||||
{# FIXME: This block was copied from the fallback location below. It would be better to have it in one place and avoid duplication. #}
|
||||
{# Use the embedded DNS resolver in Docker containers to discover the service #}
|
||||
resolver {{ matrix_synapse_reverse_proxy_companion_http_level_resolver }} valid=5s;
|
||||
set $backend "{{ matrix_synapse_reverse_proxy_companion_federation_api_addr }}";
|
||||
proxy_pass http://$backend;
|
||||
}
|
||||
|
||||
{% if room_workers | length > 0 %}
|
||||
# https://tcpipuk.github.io/synapse/deployment/workers.html
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_room_worker_federation_locations, 'room_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if generic_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#synapseappgeneric_worker
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_generic_worker_federation_locations, 'generic_workers_upstream') }}
|
||||
{% endif %}
|
||||
|
||||
{% if media_repository_workers | length > 0 %}
|
||||
# https://matrix-org.github.io/synapse/latest/workers.html#synapseappmedia_repository
|
||||
{% for location in matrix_synapse_reverse_proxy_companion_synapse_media_repository_locations %}
|
||||
location ~ {{ location }} {
|
||||
proxy_pass http://media_repository_workers_upstream$request_uri;
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_synapse_cache_enabled %}
|
||||
proxy_buffering on;
|
||||
proxy_cache {{ matrix_synapse_reverse_proxy_companion_synapse_cache_keys_zone_name }};
|
||||
proxy_cache_valid any {{ matrix_synapse_reverse_proxy_companion_synapse_cache_proxy_cache_valid_time }};
|
||||
proxy_force_ranges on;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
{% endif %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{#
|
||||
This is last, because we'd like more-specific requests (e.g. `/_matrix/federation/v1/media/` that may be handled by a media repository worker, if enabled)
|
||||
to be routed to more specialized workers via their respective `locations` defined earlier (above).
|
||||
|
||||
As https://nginx.org/en/docs/http/ngx_http_core_module.html#location says about location matching:
|
||||
> .. Then regular expressions are checked, in the order of their appearance in the configuration file.
|
||||
|
||||
See: https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/3918
|
||||
#}
|
||||
{% if federation_reader_workers | length > 0 %}
|
||||
# https://tcpipuk.github.io/synapse/deployment/workers.html
|
||||
{{ render_locations_to_upstream(matrix_synapse_reverse_proxy_companion_synapse_federation_reader_federation_locations, 'federation_reader_workers_upstream') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for configuration_block in matrix_synapse_reverse_proxy_companion_synapse_federation_api_additional_server_configuration_blocks %}
|
||||
{{- configuration_block }}
|
||||
{% endfor %}
|
||||
|
||||
location / {
|
||||
{# Use the embedded DNS resolver in Docker containers to discover the service #}
|
||||
resolver {{ matrix_synapse_reverse_proxy_companion_http_level_resolver }} valid=5s;
|
||||
set $backend "{{ matrix_synapse_reverse_proxy_companion_federation_api_addr }}";
|
||||
proxy_pass http://$backend;
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,5 @@
|
||||
SPDX-FileCopyrightText: 2022 - 2025 Slavi Pantaleev
|
||||
SPDX-FileCopyrightText: 2024 Charles Wright
|
||||
SPDX-FileCopyrightText: 2024 Suguru Hirahara
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
@@ -0,0 +1,13 @@
|
||||
#jinja2: lstrip_blocks: True
|
||||
# The default is aligned to the CPU's cache size,
|
||||
# which can sometimes be too low.
|
||||
# Thus, we ensure a larger bucket size value is used.
|
||||
server_names_hash_bucket_size 64;
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_http_level_resolver %}
|
||||
resolver {{ matrix_synapse_reverse_proxy_companion_http_level_resolver }};
|
||||
{% endif %}
|
||||
|
||||
{% for configuration_block in matrix_synapse_reverse_proxy_companion_http_additional_server_configuration_blocks %}
|
||||
{{- configuration_block }}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,3 @@
|
||||
SPDX-FileCopyrightText: 2022 Slavi Pantaleev
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
@@ -0,0 +1,93 @@
|
||||
#jinja2: lstrip_blocks: True
|
||||
# This is a custom nginx configuration file that we use in the container (instead of the default one),
|
||||
# because it allows us to run nginx with a non-root user.
|
||||
#
|
||||
# For this to work, the default vhost file (`/etc/nginx/conf.d/default.conf`) also needs to be removed.
|
||||
#
|
||||
# The following changes have been done compared to a default nginx configuration file:
|
||||
# - various temp paths are changed to `/tmp`, so that a non-root user can write to them
|
||||
# - the `user` directive was removed, as we don't want nginx to switch users
|
||||
|
||||
# load_module directives must be first or nginx will choke with:
|
||||
# > [emerg] "load_module" directive is specified too late.
|
||||
{% if matrix_synapse_reverse_proxy_companion_njs_enabled %}
|
||||
load_module modules/ngx_http_js_module.so;
|
||||
{% endif %}
|
||||
|
||||
worker_processes {{ matrix_synapse_reverse_proxy_companion_worker_processes }};
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /tmp/nginx.pid;
|
||||
{% for configuration_block in matrix_synapse_reverse_proxy_companion_additional_configuration_blocks %}
|
||||
{{- configuration_block }}
|
||||
{% endfor %}
|
||||
|
||||
events {
|
||||
worker_connections {{ matrix_synapse_reverse_proxy_companion_worker_connections }};
|
||||
{% for configuration_block in matrix_synapse_reverse_proxy_companion_event_additional_configuration_blocks %}
|
||||
{{- configuration_block }}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
http {
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
client_body_temp_path /tmp/client_temp;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_njs_enabled %}
|
||||
js_path /njs/;
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_enabled %}
|
||||
# njs module for whoami-based sync worker routing
|
||||
js_import whoami_sync_worker_router from whoami_sync_worker_router.js;
|
||||
js_shared_dict_zone zone=whoami_sync_worker_router_cache:{{ matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_cache_size_mb }}m;
|
||||
{% endif %}
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_access_log_enabled %}
|
||||
access_log /var/log/nginx/access.log main;
|
||||
{% else %}
|
||||
access_log off;
|
||||
{% endif %}
|
||||
|
||||
{% if matrix_synapse_reverse_proxy_companion_access_log_syslog_integration_enabled %}
|
||||
log_format prometheus_fmt 'matrix-synapse-reverse-proxy-companion $server_name - $upstream_addr - $remote_addr - $remote_user [$time_local] '
|
||||
'$host "$request" '
|
||||
'$status "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log syslog:server={{ matrix_synapse_reverse_proxy_companion_access_log_syslog_integration_server_port }},tag={{ matrix_synapse_reverse_proxy_companion_access_log_syslog_integration_tag }} prometheus_fmt;
|
||||
{% endif %}
|
||||
|
||||
{% if not matrix_synapse_reverse_proxy_companion_access_log_enabled and not matrix_synapse_reverse_proxy_companion_access_log_syslog_integration_enabled %}
|
||||
access_log off;
|
||||
{% endif %}
|
||||
|
||||
proxy_connect_timeout {{ matrix_synapse_reverse_proxy_companion_proxy_connect_timeout }};
|
||||
proxy_send_timeout {{ matrix_synapse_reverse_proxy_companion_proxy_send_timeout }};
|
||||
proxy_read_timeout {{ matrix_synapse_reverse_proxy_companion_proxy_read_timeout }};
|
||||
send_timeout {{ matrix_synapse_reverse_proxy_companion_send_timeout }};
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
server_tokens off;
|
||||
|
||||
{# Map directive needed for proxied WebSocket upgrades #}
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
SPDX-FileCopyrightText: 2022 - 2024 Slavi Pantaleev
|
||||
SPDX-FileCopyrightText: 2022 MDAD project contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
@@ -0,0 +1,202 @@
|
||||
#jinja2: lstrip_blocks: True
|
||||
// Whoami-based sync worker router
|
||||
//
|
||||
// This script resolves access tokens to usernames by calling the whoami endpoint.
|
||||
// Results are cached to minimize latency impact. The username is returned via the
|
||||
// X-User-Identifier header, which nginx captures and uses for upstream hashing.
|
||||
//
|
||||
// This works with any authentication system (native Synapse auth, MAS, etc.) because
|
||||
// Synapse handles token validation internally.
|
||||
//
|
||||
// Why auth_request instead of js_set?
|
||||
// -----------------------------------
|
||||
// A simpler approach would be to use js_set to populate a variable (e.g., $user_identifier)
|
||||
// and then use that variable in an upstream's `hash` directive. However, this doesn't work
|
||||
// because:
|
||||
//
|
||||
// 1. The whoami lookup requires an HTTP subrequest (ngx.fetch), which is asynchronous.
|
||||
// 2. js_set handlers must return synchronously - nginx's variable evaluation doesn't support
|
||||
// async operations. Using async functions with js_set causes errors like:
|
||||
// "async operation inside variable handler"
|
||||
//
|
||||
// The auth_request approach solves this by:
|
||||
// 1. Making a subrequest to an internal location that uses js_content (which supports async)
|
||||
// 2. Returning the user identifier via a response header (X-User-Identifier)
|
||||
// 3. Capturing that header with auth_request_set into $user_identifier
|
||||
// 4. Using $user_identifier in the upstream's hash directive for consistent routing
|
||||
|
||||
const WHOAMI_URL = {{ matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_url | to_json }};
|
||||
const CACHE_TTL_MS = {{ (matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_cache_ttl_seconds * 1000) | to_json }};
|
||||
|
||||
const LOGGING_ENABLED = {{ matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_logging_enabled | to_json }};
|
||||
const LOGGING_TOKEN_LENGTH = {{ matrix_synapse_reverse_proxy_companion_whoami_sync_worker_router_logging_token_length | to_json }};
|
||||
|
||||
function log(message) {
|
||||
if (LOGGING_ENABLED) {
|
||||
// Using WARN level because nginx's error_log is hardcoded to 'warn' and our logs won't be visible otherwise
|
||||
ngx.log(ngx.WARN, 'whoami_sync_worker_router: ' + message);
|
||||
}
|
||||
}
|
||||
|
||||
// Truncate token for logging (show first X chars only for security)
|
||||
function truncateToken(token) {
|
||||
if (!token || token.length <= LOGGING_TOKEN_LENGTH) {
|
||||
return token;
|
||||
}
|
||||
return token.substring(0, LOGGING_TOKEN_LENGTH) + '...';
|
||||
}
|
||||
|
||||
// Extract token from request (Authorization header or query parameter)
|
||||
function extractToken(r) {
|
||||
// Try Authorization header first
|
||||
const authHeader = r.headersIn['Authorization'];
|
||||
if (authHeader && authHeader.startsWith('Bearer ')) {
|
||||
return authHeader.substring(7);
|
||||
}
|
||||
|
||||
// Fall back to access_token query parameter (deprecated in Matrix v1.11, but homeservers must support it)
|
||||
if (r.args.access_token) {
|
||||
return r.args.access_token;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract localpart from user_id (e.g., "@alice:example.com" -> "alice")
|
||||
function extractLocalpart(userId) {
|
||||
if (!userId || !userId.startsWith('@')) {
|
||||
return null;
|
||||
}
|
||||
const colonIndex = userId.indexOf(':');
|
||||
if (colonIndex === -1) {
|
||||
return null;
|
||||
}
|
||||
return userId.substring(1, colonIndex);
|
||||
}
|
||||
|
||||
// Get cached username for token
|
||||
function getCachedUsername(token) {
|
||||
const cache = ngx.shared.whoami_sync_worker_router_cache;
|
||||
if (!cache) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const entry = cache.get(token);
|
||||
if (entry) {
|
||||
try {
|
||||
const data = JSON.parse(entry);
|
||||
if (data.expires > Date.now()) {
|
||||
log('cache hit for token ' + truncateToken(token) + ' -> ' + data.username);
|
||||
return data.username;
|
||||
}
|
||||
// Expired, remove from cache
|
||||
log('cache expired for token ' + truncateToken(token));
|
||||
cache.delete(token);
|
||||
} catch (e) {
|
||||
cache.delete(token);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cache username for token
|
||||
function cacheUsername(token, username) {
|
||||
const cache = ngx.shared.whoami_sync_worker_router_cache;
|
||||
if (!cache) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const entry = JSON.stringify({
|
||||
username: username,
|
||||
expires: Date.now() + CACHE_TTL_MS
|
||||
});
|
||||
cache.set(token, entry);
|
||||
log('cached token ' + truncateToken(token) + ' -> ' + username);
|
||||
} catch (e) {
|
||||
// Cache full or other error, log and continue
|
||||
ngx.log(ngx.WARN, 'whoami_sync_worker_router: cache error: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Call whoami endpoint to get user_id
|
||||
async function lookupWhoami(token) {
|
||||
log('performing whoami lookup for token ' + truncateToken(token));
|
||||
try {
|
||||
const response = await ngx.fetch(WHOAMI_URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + token
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.user_id) {
|
||||
const localpart = extractLocalpart(data.user_id);
|
||||
log('whoami lookup success: ' + data.user_id + ' -> ' + localpart);
|
||||
return localpart;
|
||||
}
|
||||
} else if (response.status === 401) {
|
||||
// Token is invalid/expired - this is expected for some requests
|
||||
log('whoami lookup returned 401 (invalid/expired token)');
|
||||
return null;
|
||||
} else {
|
||||
ngx.log(ngx.WARN, 'whoami_sync_worker_router: whoami returned status ' + response.status);
|
||||
}
|
||||
} catch (e) {
|
||||
ngx.log(ngx.ERR, 'whoami_sync_worker_router: whoami failed: ' + e.message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Set response header with the user identifier for upstream hashing
|
||||
function setUserIdentifier(r, identifier) {
|
||||
log('resolved user identifier: ' + identifier);
|
||||
r.headersOut['X-User-Identifier'] = identifier;
|
||||
}
|
||||
|
||||
// Main handler for auth_request subrequest.
|
||||
// Returns 200 with X-User-Identifier header containing the user identifier for upstream hashing.
|
||||
async function handleAuthRequest(r) {
|
||||
const token = extractToken(r);
|
||||
|
||||
if (!token) {
|
||||
// No token found (e.g., OPTIONS preflight requests don't include Authorization header).
|
||||
// We return a random value to distribute these requests across workers.
|
||||
// Returning an empty string would cause all no-token requests to hash to the same value,
|
||||
// routing them all to a single worker.
|
||||
// This doesn't affect the cache since we only cache token -> username mappings.
|
||||
log('no token found in request, distributing randomly');
|
||||
setUserIdentifier(r, '_no_token_' + Math.random());
|
||||
r.return(200);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check cache first
|
||||
const cachedUsername = getCachedUsername(token);
|
||||
if (cachedUsername) {
|
||||
setUserIdentifier(r, cachedUsername);
|
||||
r.return(200);
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform whoami lookup
|
||||
log('cache miss for token ' + truncateToken(token));
|
||||
const username = await lookupWhoami(token);
|
||||
if (username) {
|
||||
cacheUsername(token, username);
|
||||
setUserIdentifier(r, username);
|
||||
r.return(200);
|
||||
return;
|
||||
}
|
||||
|
||||
// Whoami lookup failed, fall back to using the token itself for hashing.
|
||||
// This still provides device-level sticky routing (same token -> same worker).
|
||||
log('whoami lookup failed, falling back to token-based routing');
|
||||
setUserIdentifier(r, token);
|
||||
r.return(200);
|
||||
}
|
||||
|
||||
export default { handleAuthRequest };
|
||||
@@ -0,0 +1,3 @@
|
||||
SPDX-FileCopyrightText: 2026 Slavi Pantaleev
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
@@ -0,0 +1,62 @@
|
||||
#jinja2: lstrip_blocks: True
|
||||
[Unit]
|
||||
Description=Synapse reverse-proxy companion
|
||||
{% for service in matrix_synapse_reverse_proxy_companion_systemd_required_services_list %}
|
||||
Requires={{ service }}
|
||||
After={{ service }}
|
||||
{% endfor %}
|
||||
{% for service in matrix_synapse_reverse_proxy_companion_systemd_wanted_services_list %}
|
||||
Wants={{ 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 -t {{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-synapse-reverse-proxy-companion 2>/dev/null || true'
|
||||
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-synapse-reverse-proxy-companion 2>/dev/null || true'
|
||||
|
||||
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \
|
||||
--rm \
|
||||
--name=matrix-synapse-reverse-proxy-companion \
|
||||
--log-driver=none \
|
||||
--user={{ matrix_user_uid }}:{{ matrix_user_gid }} \
|
||||
--cap-drop=ALL \
|
||||
--read-only \
|
||||
--tmpfs=/tmp:rw,noexec,nosuid,size={{ matrix_synapse_reverse_proxy_companion_tmp_directory_size_mb }}m \
|
||||
{% if matrix_synapse_reverse_proxy_companion_synapse_cache_enabled %}
|
||||
--tmpfs=/tmp/synapse-cache:rw,noexec,nosuid,size={{ matrix_synapse_reverse_proxy_companion_tmp_cache_directory_size_mb }}m\
|
||||
{% endif %}
|
||||
--network={{ matrix_synapse_reverse_proxy_companion_container_network }} \
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_client_api_host_bind_port %}
|
||||
-p {{ matrix_synapse_reverse_proxy_companion_container_client_api_host_bind_port }}:8008 \
|
||||
{% endif %}
|
||||
{% if matrix_synapse_reverse_proxy_companion_container_federation_api_host_bind_port %}
|
||||
-p {{ matrix_synapse_reverse_proxy_companion_container_federation_api_host_bind_port }}:8048 \
|
||||
{% endif %}
|
||||
--mount type=bind,src={{ matrix_synapse_reverse_proxy_companion_base_path }}/nginx.conf,dst=/etc/nginx/nginx.conf,ro \
|
||||
--mount type=bind,src={{ matrix_synapse_reverse_proxy_companion_confd_path }},dst=/etc/nginx/conf.d,ro \
|
||||
{% if matrix_synapse_reverse_proxy_companion_njs_enabled %}
|
||||
--mount type=bind,src={{ matrix_synapse_reverse_proxy_companion_njs_path }},dst=/njs,ro \
|
||||
{% endif %}
|
||||
--label-file={{ matrix_synapse_reverse_proxy_companion_base_path }}/labels \
|
||||
{% for arg in matrix_synapse_reverse_proxy_companion_container_arguments %}
|
||||
{{ arg }} \
|
||||
{% endfor %}
|
||||
{{ matrix_synapse_reverse_proxy_companion_container_image }}
|
||||
|
||||
{% for network in matrix_synapse_reverse_proxy_companion_container_additional_networks %}
|
||||
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-synapse-reverse-proxy-companion
|
||||
{% endfor %}
|
||||
|
||||
ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach matrix-synapse-reverse-proxy-companion
|
||||
|
||||
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop -t {{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-synapse-reverse-proxy-companion 2>/dev/null || true'
|
||||
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-synapse-reverse-proxy-companion 2>/dev/null || true'
|
||||
ExecReload={{ devture_systemd_docker_base_host_command_docker }} exec matrix-synapse-reverse-proxy-companion /usr/sbin/nginx -s reload
|
||||
Restart=always
|
||||
RestartSec=30
|
||||
SyslogIdentifier=matrix-synapse-reverse-proxy-companion
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,4 @@
|
||||
SPDX-FileCopyrightText: 2022 - 2024 Slavi Pantaleev
|
||||
SPDX-FileCopyrightText: 2024 Michael Hollister
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
Reference in New Issue
Block a user