mirror of
https://github.com/spantaleev/matrix-docker-ansible-deploy.git
synced 2026-02-07 22:43:10 +03:00
The whoami-based approach is now the only implementation for sync worker routing. It works with all token types (native Synapse, MAS, etc.) and is automatically enabled when sync workers exist. The old map-based approach only worked with native Synapse tokens (syt_<b64>_...) and would give poor results with MAS or other auth systems.
355 lines
18 KiB
Django/Jinja
355 lines
18 KiB
Django/Jinja
#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 %}
|