From 4d62a75f6f46becb0ece21bd4c063830db229ece Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Mon, 25 Jan 2021 09:21:17 +0200 Subject: [PATCH] Get matrix-corporal to play nicely with a Synapse worker setup We do this by creating one more layer of indirection. First we reach some generic vhost handling matrix.DOMAIN. A bunch of override rules are added there (capturing traffic to send to ma1sd, etc). nginx-status and similar generic things also live there. We then proxy to the homeserver on some other vhost (only Synapse being available right now, but repointing this to Dendrite or other will be possible in the future). Then that homeserver-specific vhost does its thing to proxy to the homeserver. It may or may not use workers, etc. Without matrix-corporal, the flow is now: 1. matrix.DOMAIN (matrix-nginx-proxy/matrix-domain.conf) 2. matrix-nginx-proxy/matrix-synapse.conf 3. matrix-synapse With matrix-corporal enabled, it becomes: 1. matrix.DOMAIN (matrix-nginx-proxy/matrix-domain.conf) 2. matrix-corporal 3. matrix-nginx-proxy/matrix-synapse.conf 4. matrix-synapse (matrix-corporal gets injected at step 2). --- group_vars/matrix_servers | 17 +- roles/matrix-nginx-proxy/defaults/main.yml | 38 ++- .../tasks/setup_nginx_proxy.yml | 24 +- .../nginx/conf.d/matrix-base-domain.conf.j2 | 70 +++++ .../nginx/conf.d/matrix-domain.conf.j2 | 198 +++++++++++- .../nginx/conf.d/matrix-synapse.conf.j2 | 296 ++++-------------- 6 files changed, 370 insertions(+), 273 deletions(-) create mode 100644 roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-base-domain.conf.j2 diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index f64b02a02..88afb186d 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -673,7 +673,8 @@ matrix_corporal_systemd_required_services_list: | (['matrix-synapse.service']) }} -matrix_corporal_matrix_homeserver_api_endpoint: "http://matrix-synapse:8008" +# This goes to Synapse's vhost +matrix_corporal_matrix_homeserver_api_endpoint: "http://matrix-nginx-proxy:12080" matrix_corporal_matrix_auth_shared_secret: "{{ matrix_synapse_ext_password_provider_shared_secret_auth_shared_secret }}" @@ -885,7 +886,7 @@ matrix_ma1sd_synapsesql_connection: //{{ matrix_synapse_database_host }}/{{ matr matrix_ma1sd_dns_overwrite_enabled: true matrix_ma1sd_dns_overwrite_homeserver_client_name: "{{ matrix_server_fqn_matrix }}" -matrix_ma1sd_dns_overwrite_homeserver_client_value: "http://{{ 'matrix-corporal:41080' if matrix_corporal_enabled else 'matrix-synapse:8008' }}" +matrix_ma1sd_dns_overwrite_homeserver_client_value: "http://{{ matrix_nginx_proxy_proxy_matrix_client_api_addr_with_container }}" # By default, we send mail through the `matrix-mailer` service. matrix_ma1sd_threepid_medium_email_identity_from: "{{ matrix_mailer_sender_address }}" @@ -932,8 +933,8 @@ matrix_ma1sd_database_password: "{{ matrix_synapse_macaroon_secret_key | passwor # If that's not the case, you may wish to disable this and take care of proxying yourself. matrix_nginx_proxy_enabled: true -matrix_nginx_proxy_proxy_matrix_client_api_addr_with_container: "{{ 'matrix-corporal:41080' if matrix_corporal_enabled else 'matrix-synapse:8008' }}" -matrix_nginx_proxy_proxy_matrix_client_api_addr_sans_container: "{{ '127.0.0.1:41080' if matrix_corporal_enabled else '127.0.0.1:8008' }}" +matrix_nginx_proxy_proxy_matrix_client_api_addr_with_container: "{{ 'matrix-corporal:41080' if matrix_corporal_enabled else 'matrix-nginx-proxy:12080' }}" +matrix_nginx_proxy_proxy_matrix_client_api_addr_sans_container: "{{ '127.0.0.1:41080' if matrix_corporal_enabled else '127.0.0.1:12080' }}" matrix_nginx_proxy_proxy_matrix_client_api_client_max_body_size_mb: "{{ matrix_synapse_max_upload_size_mb }}" matrix_nginx_proxy_proxy_matrix_client_api_forwarded_location_synapse_admin_api_enabled: "{{ matrix_synapse_admin_enabled }}" @@ -956,8 +957,12 @@ matrix_nginx_proxy_proxy_matrix_identity_api_addr_sans_container: "127.0.0.1:809 # By default, we do TLS termination for the Matrix Federation API (port 8448) at matrix-nginx-proxy. # Unless this is handled there OR Synapse's federation listener port is disabled, we'll reverse-proxy. matrix_nginx_proxy_proxy_matrix_federation_api_enabled: "{{ matrix_synapse_federation_port_enabled and not matrix_synapse_tls_federation_listener_enabled }}" -matrix_nginx_proxy_proxy_matrix_federation_api_addr_with_container: "matrix-synapse:8048" -matrix_nginx_proxy_proxy_matrix_federation_api_addr_sans_container: "127.0.0.1:8048" +matrix_nginx_proxy_proxy_matrix_federation_api_addr_with_container: "matrix-nginx-proxy:12088" +matrix_nginx_proxy_proxy_matrix_federation_api_addr_sans_container: "127.0.0.1:12088" + +# Settings controlling matrix-synapse-proxy.conf +matrix_nginx_proxy_proxy_synapse_enabled: "{{ matrix_synapse_enabled }}" +matrix_nginx_proxy_proxy_synapse_federation_api_enabled: "{{ matrix_nginx_proxy_proxy_matrix_federation_api_enabled }}" matrix_nginx_proxy_container_federation_host_bind_port: "{{ matrix_federation_public_port }}" diff --git a/roles/matrix-nginx-proxy/defaults/main.yml b/roles/matrix-nginx-proxy/defaults/main.yml index 44ed8acf0..6ab7e6249 100644 --- a/roles/matrix-nginx-proxy/defaults/main.yml +++ b/roles/matrix-nginx-proxy/defaults/main.yml @@ -99,6 +99,10 @@ matrix_nginx_proxy_access_log_enabled: true matrix_nginx_proxy_proxy_riot_compat_redirect_enabled: false matrix_nginx_proxy_proxy_riot_compat_redirect_hostname: "riot.{{ matrix_domain }}" +# Controls whether proxying the Synapse domain should be done. +matrix_nginx_proxy_proxy_synapse_enabled: false +matrix_nginx_proxy_proxy_synapse_hostname: "matrix-nginx-proxy" + # Controls whether proxying the Element domain should be done. matrix_nginx_proxy_proxy_element_enabled: false matrix_nginx_proxy_proxy_element_hostname: "{{ matrix_server_fqn_element }}" @@ -146,8 +150,13 @@ matrix_nginx_proxy_proxy_synapse_metrics_basic_auth_key: "" # The addresses where the Matrix Client API is. # Certain extensions (like matrix-corporal) may override this in order to capture all traffic. -matrix_nginx_proxy_proxy_matrix_client_api_addr_with_container: "matrix-synapse:8008" -matrix_nginx_proxy_proxy_matrix_client_api_addr_sans_container: "127.0.0.1:8008" +matrix_nginx_proxy_proxy_matrix_client_api_addr_with_container: "matrix-nginx-proxy:12080" +matrix_nginx_proxy_proxy_matrix_client_api_addr_sans_container: "127.0.0.1:12080" + +# The addresses where the Matrix Client API is, when using Synapse. +matrix_nginx_proxy_proxy_synapse_client_api_addr_with_container: "matrix-synapse:8008" +matrix_nginx_proxy_proxy_synapse_client_api_addr_sans_container: "127.0.0.1:8008" + # This needs to be equal or higher than the maximum upload size accepted by Synapse. matrix_nginx_proxy_proxy_matrix_client_api_client_max_body_size_mb: 50 @@ -185,34 +194,41 @@ matrix_nginx_proxy_proxy_matrix_client_redirect_root_uri_to_domain: "" # Controls whether proxying for the Matrix Federation API should be done. matrix_nginx_proxy_proxy_matrix_federation_api_enabled: false -matrix_nginx_proxy_proxy_matrix_federation_api_addr_with_container: "matrix-synapse:8048" -matrix_nginx_proxy_proxy_matrix_federation_api_addr_sans_container: "localhost:8048" +matrix_nginx_proxy_proxy_matrix_federation_api_addr_with_container: "matrix-nginx-proxy:12088" +matrix_nginx_proxy_proxy_matrix_federation_api_addr_sans_container: "localhost:12088" matrix_nginx_proxy_proxy_matrix_federation_api_client_max_body_size_mb: "{{ (matrix_nginx_proxy_proxy_matrix_client_api_client_max_body_size_mb | int) * 3 }}" matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate: "{{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/fullchain.pem" matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate_key: "{{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/privkey.pem" +# The addresses where the Federation API is, when using Synapse. +matrix_nginx_proxy_proxy_synapse_federation_api_addr_with_container: "matrix-synapse:8048" +matrix_nginx_proxy_proxy_synapse_federation_api_addr_sans_container: "localhost:8048" + # The tmpfs at /tmp needs to be large enough to handle multiple concurrent file uploads. matrix_nginx_proxy_tmp_directory_size_mb: "{{ (matrix_nginx_proxy_proxy_matrix_federation_api_client_max_body_size_mb | int) * 50 }}" -# A list of strings containing additional configuration blocks to add to the nginx http's server configuration. +# A list of strings containing additional configuration blocks to add to the nginx http's server configuration (nginx-http.conf). matrix_nginx_proxy_proxy_http_additional_server_configuration_blocks: [] -# A list of strings containing additional configuration blocks to add to the matrix synapse's server configuration. +# A list of strings containing additional configuration blocks to add to the base matrix server configuration (matrix-domain.conf). matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks: [] -# A list of strings containing additional configuration blocks to add to Riot's server configuration. +# A list of strings containing additional configuration blocks to add to the synapse's server configuration (matrix-synapse.conf). +matrix_nginx_proxy_proxy_synapse_additional_server_configuration_blocks: [] + +# A list of strings containing additional configuration blocks to add to Riot's server configuration (matrix-riot-web.conf). matrix_nginx_proxy_proxy_riot_additional_server_configuration_blocks: [] -# A list of strings containing additional configuration blocks to add to Element's server configuration. +# A list of strings containing additional configuration blocks to add to Element's server configuration (matrix-client-element.conf). matrix_nginx_proxy_proxy_element_additional_server_configuration_blocks: [] -# A list of strings containing additional configuration blocks to add to Dimension's server configuration. +# A list of strings containing additional configuration blocks to add to Dimension's server configuration (matrix-dimension.conf). matrix_nginx_proxy_proxy_dimension_additional_server_configuration_blocks: [] -# A list of strings containing additional configuration blocks to add to Jitsi's server configuration. +# A list of strings containing additional configuration blocks to add to Jitsi's server configuration (matrix-jitsi.conf). matrix_nginx_proxy_proxy_jitsi_additional_server_configuration_blocks: [] -# A list of strings containing additional configuration blocks to add to the base domain server configuration. +# A list of strings containing additional configuration blocks to add to the base domain server configuration (matrix-base-domain.conf). matrix_nginx_proxy_proxy_domain_additional_server_configuration_blocks: [] # Specifies the SSL configuration that should be used for the SSL protocols and ciphers diff --git a/roles/matrix-nginx-proxy/tasks/setup_nginx_proxy.yml b/roles/matrix-nginx-proxy/tasks/setup_nginx_proxy.yml index 90f0da73c..9a9bef2dd 100644 --- a/roles/matrix-nginx-proxy/tasks/setup_nginx_proxy.yml +++ b/roles/matrix-nginx-proxy/tasks/setup_nginx_proxy.yml @@ -45,12 +45,18 @@ mode: 0644 when: matrix_nginx_proxy_enabled|bool -- name: Ensure Matrix nginx-proxy configuration for matrix domain exists +- name: Ensure Matrix nginx-proxy configuration for matrix-synapse exists template: src: "{{ role_path }}/templates/nginx/conf.d/matrix-synapse.conf.j2" dest: "{{ matrix_nginx_proxy_confd_path }}/matrix-synapse.conf" mode: 0644 - when: matrix_nginx_proxy_proxy_matrix_enabled|bool + when: matrix_nginx_proxy_proxy_synapse_enabled|bool + +- name: Ensure Matrix nginx-proxy configuration for matrix-synapse deleted + file: + path: "{{ matrix_nginx_proxy_confd_path }}/matrix-synapse.conf" + state: absent + when: "not matrix_nginx_proxy_proxy_synapse_enabled|bool" - name: Ensure Matrix nginx-proxy configuration for Element domain exists template: @@ -80,6 +86,12 @@ mode: 0644 when: matrix_nginx_proxy_proxy_jitsi_enabled|bool +- name: Ensure Matrix nginx-proxy configuration for Matrix domain exists + template: + src: "{{ role_path }}/templates/nginx/conf.d/matrix-domain.conf.j2" + dest: "{{ matrix_nginx_proxy_confd_path }}/matrix-domain.conf" + mode: 0644 + - name: Ensure Matrix nginx-proxy data directory for base domain exists file: path: "{{ matrix_nginx_proxy_data_path }}/matrix-domain" @@ -100,8 +112,8 @@ - name: Ensure Matrix nginx-proxy configuration for base domain exists template: - src: "{{ role_path }}/templates/nginx/conf.d/matrix-domain.conf.j2" - dest: "{{ matrix_nginx_proxy_confd_path }}/matrix-domain.conf" + src: "{{ role_path }}/templates/nginx/conf.d/matrix-base-domain.conf.j2" + dest: "{{ matrix_nginx_proxy_confd_path }}/matrix-base-domain.conf" mode: 0644 when: matrix_nginx_proxy_base_domain_serving_enabled|bool @@ -161,7 +173,7 @@ - name: Ensure Matrix nginx-proxy configuration for matrix domain deleted file: - path: "{{ matrix_nginx_proxy_confd_path }}/matrix-synapse.conf" + path: "{{ matrix_nginx_proxy_confd_path }}/matrix-domain.conf" state: absent when: "not matrix_nginx_proxy_proxy_matrix_enabled|bool" @@ -191,7 +203,7 @@ - name: Ensure Matrix nginx-proxy configuration for base domain deleted file: - path: "{{ matrix_nginx_proxy_confd_path }}/matrix-domain.conf" + path: "{{ matrix_nginx_proxy_confd_path }}/matrix-base-domain.conf" state: absent when: "not matrix_nginx_proxy_base_domain_serving_enabled|bool" diff --git a/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-base-domain.conf.j2 b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-base-domain.conf.j2 new file mode 100644 index 000000000..227747a54 --- /dev/null +++ b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-base-domain.conf.j2 @@ -0,0 +1,70 @@ +#jinja2: lstrip_blocks: "True" + +{% macro render_vhost_directives() %} + root /nginx-data/matrix-domain; + + gzip on; + gzip_types text/plain application/json; + {% for configuration_block in matrix_nginx_proxy_proxy_domain_additional_server_configuration_blocks %} + {{- configuration_block }} + {% endfor %} + + location /.well-known/matrix { + root {{ matrix_static_files_base_path }}; + {# + A somewhat long expires value is used to prevent outages + in case this is unreachable due to network failure. + #} + expires 4h; + default_type application/json; + add_header Access-Control-Allow-Origin *; + } +{% endmacro %} + +server { + listen {{ 8080 if matrix_nginx_proxy_enabled else 80 }}; + + server_name {{ matrix_nginx_proxy_base_domain_hostname }}; + server_tokens off; + + {% if matrix_nginx_proxy_https_enabled %} + location /.well-known/acme-challenge { + {% if matrix_nginx_proxy_enabled %} + {# Use the embedded DNS resolver in Docker containers to discover the service #} + resolver 127.0.0.11 valid=5s; + set $backend "matrix-certbot:8080"; + proxy_pass http://$backend; + {% else %} + {# Generic configuration for use outside of our container setup #} + proxy_pass http://127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}; + {% endif %} + } + + location / { + return 301 https://$http_host$request_uri; + } + {% else %} + {{ render_vhost_directives() }} + {% endif %} +} + +{% if matrix_nginx_proxy_https_enabled %} +server { + listen {{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; + listen [::]:{{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; + + server_name {{ matrix_nginx_proxy_base_domain_hostname }}; + server_tokens off; + + ssl_certificate {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_base_domain_hostname }}/fullchain.pem; + ssl_certificate_key {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_base_domain_hostname }}/privkey.pem; + + ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }}; + {% if matrix_nginx_proxy_ssl_ciphers != '' %} + ssl_ciphers {{ matrix_nginx_proxy_ssl_ciphers }}; + {% endif %} + ssl_prefer_server_ciphers {{ matrix_nginx_proxy_ssl_prefer_server_ciphers }}; + + {{ render_vhost_directives() }} +} +{% endif %} diff --git a/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-domain.conf.j2 b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-domain.conf.j2 index 227747a54..2ab78a1b5 100644 --- a/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-domain.conf.j2 +++ b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-domain.conf.j2 @@ -1,31 +1,148 @@ #jinja2: lstrip_blocks: "True" +{% macro render_nginx_status_location_block(addresses) %} + {# Empty first line to make indentation prettier. #} + + location /nginx_status { + stub_status on; + access_log off; + {% for address in addresses %} + allow {{ address }}; + {% endfor %} + deny all; + } +{% endmacro %} + {% macro render_vhost_directives() %} - root /nginx-data/matrix-domain; - gzip on; gzip_types text/plain application/json; - {% for configuration_block in matrix_nginx_proxy_proxy_domain_additional_server_configuration_blocks %} - {{- configuration_block }} - {% endfor %} location /.well-known/matrix { root {{ matrix_static_files_base_path }}; {# A somewhat long expires value is used to prevent outages - in case this is unreachable due to network failure. + in case this is unreachable due to network failure or + due to the base domain's server completely dying. #} expires 4h; default_type application/json; add_header Access-Control-Allow-Origin *; } + + {% if matrix_nginx_proxy_proxy_matrix_nginx_status_enabled %} + {{ render_nginx_status_location_block(matrix_nginx_proxy_proxy_matrix_nginx_status_allowed_addresses) }} + {% endif %} + + {% if matrix_nginx_proxy_proxy_matrix_corporal_api_enabled %} + location ^~ /_matrix/corporal { + {% if matrix_nginx_proxy_enabled %} + {# Use the embedded DNS resolver in Docker containers to discover the service #} + resolver 127.0.0.11 valid=5s; + set $backend "{{ matrix_nginx_proxy_proxy_matrix_corporal_api_addr_with_container }}"; + proxy_pass http://$backend; + {% else %} + {# Generic configuration for use outside of our container setup #} + proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_corporal_api_addr_sans_container }}; + {% endif %} + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + } + {% endif %} + + {% if matrix_nginx_proxy_proxy_matrix_identity_api_enabled %} + location ^~ /_matrix/identity { + {% if matrix_nginx_proxy_enabled %} + {# Use the embedded DNS resolver in Docker containers to discover the service #} + resolver 127.0.0.11 valid=5s; + set $backend "{{ matrix_nginx_proxy_proxy_matrix_identity_api_addr_with_container }}"; + proxy_pass http://$backend; + {% else %} + {# Generic configuration for use outside of our container setup #} + proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_identity_api_addr_sans_container }}; + {% endif %} + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + } + {% endif %} + + {% if matrix_nginx_proxy_proxy_matrix_user_directory_search_enabled %} + location ^~ /_matrix/client/r0/user_directory/search { + {% if matrix_nginx_proxy_enabled %} + {# Use the embedded DNS resolver in Docker containers to discover the service #} + resolver 127.0.0.11 valid=5s; + set $backend "{{ matrix_nginx_proxy_proxy_matrix_user_directory_search_addr_with_container }}"; + proxy_pass http://$backend; + {% else %} + {# Generic configuration for use outside of our container setup #} + proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_user_directory_search_addr_sans_container }}; + {% endif %} + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + } + {% endif %} + + {% if matrix_nginx_proxy_proxy_matrix_3pid_registration_enabled %} + location ~ ^/_matrix/client/r0/register/(email|msisdn)/requestToken$ { + {% if matrix_nginx_proxy_enabled %} + {# Use the embedded DNS resolver in Docker containers to discover the service #} + resolver 127.0.0.11 valid=5s; + set $backend "{{ matrix_nginx_proxy_proxy_matrix_3pid_registration_addr_with_container }}"; + proxy_pass http://$backend; + {% else %} + {# Generic configuration for use outside of our container setup #} + proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_3pid_registration_addr_sans_container }}; + {% endif %} + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + } + {% endif %} + + {% for configuration_block in matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks %} + {{- configuration_block }} + {% endfor %} + + {# + This handles the Matrix Client API only. + The Matrix Federation API is handled by a separate vhost. + #} + location ~* ^({{ matrix_nginx_proxy_proxy_matrix_client_api_forwarded_location_prefix_regexes|join('|') }}) { + {% if matrix_nginx_proxy_enabled %} + {# Use the embedded DNS resolver in Docker containers to discover the service #} + resolver 127.0.0.11 valid=5s; + set $backend "{{ matrix_nginx_proxy_proxy_matrix_client_api_addr_with_container }}"; + proxy_pass http://$backend; + {% else %} + {# Generic configuration for use outside of our container setup #} + proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_client_api_addr_sans_container }}; + {% endif %} + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + + client_body_buffer_size 25M; + client_max_body_size {{ matrix_nginx_proxy_proxy_matrix_client_api_client_max_body_size_mb }}M; + proxy_max_temp_file_size 0; + } + + location / { + {% if matrix_nginx_proxy_proxy_matrix_client_redirect_root_uri_to_domain %} + return 302 $scheme://{{ matrix_nginx_proxy_proxy_matrix_client_redirect_root_uri_to_domain }}$request_uri; + {% else %} + rewrite ^/$ /_matrix/static/ last; + {% endif %} + } {% endmacro %} server { listen {{ 8080 if matrix_nginx_proxy_enabled else 80 }}; + server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; - server_name {{ matrix_nginx_proxy_base_domain_hostname }}; server_tokens off; + root /dev/null; {% if matrix_nginx_proxy_https_enabled %} location /.well-known/acme-challenge { @@ -40,6 +157,10 @@ server { {% endif %} } + {% if matrix_nginx_proxy_proxy_matrix_nginx_status_enabled %} + {{ render_nginx_status_location_block(matrix_nginx_proxy_proxy_matrix_nginx_status_allowed_addresses) }} + {% endif %} + location / { return 301 https://$http_host$request_uri; } @@ -53,11 +174,13 @@ server { listen {{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; listen [::]:{{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; - server_name {{ matrix_nginx_proxy_base_domain_hostname }}; - server_tokens off; + server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; - ssl_certificate {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_base_domain_hostname }}/fullchain.pem; - ssl_certificate_key {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_base_domain_hostname }}/privkey.pem; + server_tokens off; + root /dev/null; + + ssl_certificate {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/fullchain.pem; + ssl_certificate_key {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/privkey.pem; ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }}; {% if matrix_nginx_proxy_ssl_ciphers != '' %} @@ -68,3 +191,56 @@ server { {{ render_vhost_directives() }} } {% endif %} + +{% if matrix_nginx_proxy_proxy_matrix_federation_api_enabled %} +{# + This federation vhost is a little special. + It serves federation over HTTP or HTTPS, depending on `matrix_nginx_proxy_https_enabled`. +#} +server { + {% if matrix_nginx_proxy_https_enabled %} + listen 8448 ssl http2; + listen [::]:8448 ssl http2; + {% else %} + listen 8448; + {% endif %} + + server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; + server_tokens off; + + root /dev/null; + + gzip on; + gzip_types text/plain application/json; + + {% if matrix_nginx_proxy_https_enabled %} + ssl_certificate {{ matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate }}; + ssl_certificate_key {{ matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate_key }}; + + ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }}; + {% if matrix_nginx_proxy_ssl_ciphers != '' %} + ssl_ciphers {{ matrix_nginx_proxy_ssl_ciphers }}; + {% endif %} + ssl_prefer_server_ciphers {{ matrix_nginx_proxy_ssl_prefer_server_ciphers }}; + {% endif %} + + location / { + {% if matrix_nginx_proxy_enabled %} + {# Use the embedded DNS resolver in Docker containers to discover the service #} + resolver 127.0.0.11 valid=5s; + set $backend "{{ matrix_nginx_proxy_proxy_matrix_federation_api_addr_with_container }}"; + proxy_pass http://$backend; + {% else %} + {# Generic configuration for use outside of our container setup #} + proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_federation_api_addr_sans_container }}; + {% endif %} + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + + client_body_buffer_size 25M; + client_max_body_size {{ matrix_nginx_proxy_proxy_matrix_federation_api_client_max_body_size_mb }}M; + proxy_max_temp_file_size 0; + } +} +{% endif %} diff --git a/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-synapse.conf.j2 b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-synapse.conf.j2 index 5d204343d..0dcaf9a66 100644 --- a/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-synapse.conf.j2 +++ b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-synapse.conf.j2 @@ -1,109 +1,59 @@ #jinja2: lstrip_blocks: "True" -{% macro render_nginx_status_location_block(addresses) %} - {# Empty first line to make indentation prettier. #} - location /nginx_status { - stub_status on; - access_log off; - {% for address in addresses %} - allow {{ address }}; +{% set generic_workers = matrix_nginx_proxy_synapse_workers_list|selectattr('type', 'equalto', 'generic_worker')|list %} +{% set media_repository_workers = matrix_nginx_proxy_synapse_workers_list|selectattr('type', 'equalto', 'media_repository')|list %} +{% set user_dir_workers = matrix_nginx_proxy_synapse_workers_list|selectattr('type', 'equalto', 'user_dir')|list %} +{% set frontend_proxy_workers = matrix_nginx_proxy_synapse_workers_list|selectattr('type', 'equalto', 'frontend_proxy')|list %} +{% if matrix_nginx_proxy_synapse_workers_enabled %} + # Round Robin "upstream" pools for workers + + {% if generic_workers %} + upstream generic_worker_upstream { + # ensures that requests from the same client will always be passed + # to the same server (except when this server is unavailable) + ip_hash; + + {% for worker in generic_workers %} + server "matrix-synapse:{{ worker.port }}"; {% endfor %} - deny all; } -{% endmacro %} + {% endif %} + {% if frontend_proxy_workers %} + upstream frontend_proxy_upstream { + {% for worker in frontend_proxy_workers %} + server "matrix-synapse:{{ worker.port }}"; + {% endfor %} + } + {% endif %} + + {% if media_repository_workers %} + upstream media_repository_upstream { + {% for worker in media_repository_workers %} + server "matrix-synapse:{{ worker.port }}"; + {% endfor %} + } + {% endif %} + + {% if user_dir_workers %} + upstream user_dir_upstream { + {% for worker in user_dir_workers %} + server "matrix-synapse:{{ worker.port }}"; + {% endfor %} + } + {% endif %} +{% endif %} + +server { + listen 12080; + server_name {{ matrix_nginx_proxy_proxy_synapse_hostname }}; + + server_tokens off; + root /dev/null; -{% macro render_vhost_directives() %} gzip on; gzip_types text/plain application/json; - location /.well-known/matrix { - root {{ matrix_static_files_base_path }}; - {# - A somewhat long expires value is used to prevent outages - in case this is unreachable due to network failure or - due to the base domain's server completely dying. - #} - expires 4h; - default_type application/json; - add_header Access-Control-Allow-Origin *; - } - - {% if matrix_nginx_proxy_proxy_matrix_nginx_status_enabled %} - {{ render_nginx_status_location_block(matrix_nginx_proxy_proxy_matrix_nginx_status_allowed_addresses) }} - {% endif %} - - {% if matrix_nginx_proxy_proxy_matrix_corporal_api_enabled %} - location ^~ /_matrix/corporal { - {% if matrix_nginx_proxy_enabled %} - {# Use the embedded DNS resolver in Docker containers to discover the service #} - resolver 127.0.0.11 valid=5s; - set $backend "{{ matrix_nginx_proxy_proxy_matrix_corporal_api_addr_with_container }}"; - proxy_pass http://$backend; - {% else %} - {# Generic configuration for use outside of our container setup #} - proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_corporal_api_addr_sans_container }}; - {% endif %} - - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $remote_addr; - } - {% endif %} - - {% if matrix_nginx_proxy_proxy_matrix_identity_api_enabled %} - location ^~ /_matrix/identity { - {% if matrix_nginx_proxy_enabled %} - {# Use the embedded DNS resolver in Docker containers to discover the service #} - resolver 127.0.0.11 valid=5s; - set $backend "{{ matrix_nginx_proxy_proxy_matrix_identity_api_addr_with_container }}"; - proxy_pass http://$backend; - {% else %} - {# Generic configuration for use outside of our container setup #} - proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_identity_api_addr_sans_container }}; - {% endif %} - - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $remote_addr; - } - {% endif %} - - {% if matrix_nginx_proxy_proxy_matrix_user_directory_search_enabled %} - # NOTE: This redirects user lookup requests to the identity server instead of - # synapse, so user_dir_workers endpoints listed further down in this file will - # not be reached and workers of this kind should be disabled for consistency. - location ^~ /_matrix/client/r0/user_directory/search { - {% if matrix_nginx_proxy_enabled %} - {# Use the embedded DNS resolver in Docker containers to discover the service #} - resolver 127.0.0.11 valid=5s; - set $backend "{{ matrix_nginx_proxy_proxy_matrix_user_directory_search_addr_with_container }}"; - proxy_pass http://$backend; - {% else %} - {# Generic configuration for use outside of our container setup #} - proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_user_directory_search_addr_sans_container }}; - {% endif %} - - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $remote_addr; - } - {% endif %} - - {% if matrix_nginx_proxy_proxy_matrix_3pid_registration_enabled %} - location ~ ^/_matrix/client/r0/register/(email|msisdn)/requestToken$ { - {% if matrix_nginx_proxy_enabled %} - {# Use the embedded DNS resolver in Docker containers to discover the service #} - resolver 127.0.0.11 valid=5s; - set $backend "{{ matrix_nginx_proxy_proxy_matrix_3pid_registration_addr_with_container }}"; - proxy_pass http://$backend; - {% else %} - {# Generic configuration for use outside of our container setup #} - proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_3pid_registration_addr_sans_container }}; - {% endif %} - - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $remote_addr; - } - {% endif %} - {% if matrix_nginx_proxy_synapse_workers_enabled %} {# Workers redirects BEGIN #} @@ -167,7 +117,7 @@ {% endif %} - {% for configuration_block in matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks %} + {% for configuration_block in matrix_nginx_proxy_proxy_synapse_additional_server_configuration_blocks %} {{- configuration_block }} {% endfor %} @@ -193,19 +143,16 @@ } {% endif %} - {# - This handles the Matrix Client API only. - The Matrix Federation API is handled by a separate vhost. - #} - location ~* ^({{ matrix_nginx_proxy_proxy_matrix_client_api_forwarded_location_prefix_regexes|join('|') }}) { + {# Everything else just goes to the API server ##} + location / { {% if matrix_nginx_proxy_enabled %} {# Use the embedded DNS resolver in Docker containers to discover the service #} resolver 127.0.0.11 valid=5s; - set $backend "{{ matrix_nginx_proxy_proxy_matrix_client_api_addr_with_container }}"; + set $backend "{{ matrix_nginx_proxy_proxy_synapse_client_api_addr_with_container }}"; proxy_pass http://$backend; {% else %} {# Generic configuration for use outside of our container setup #} - proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_client_api_addr_sans_container }}; + proxy_pass http://{{ matrix_nginx_proxy_proxy_synapse_client_api_addr_sans_container }}; {% endif %} proxy_set_header Host $host; @@ -215,129 +162,13 @@ client_max_body_size {{ matrix_nginx_proxy_proxy_matrix_client_api_client_max_body_size_mb }}M; proxy_max_temp_file_size 0; } - - location / { - {% if matrix_nginx_proxy_proxy_matrix_client_redirect_root_uri_to_domain %} - return 302 $scheme://{{ matrix_nginx_proxy_proxy_matrix_client_redirect_root_uri_to_domain }}$request_uri; - {% else %} - rewrite ^/$ /_matrix/static/ last; - {% endif %} - } -{% endmacro %} - -{% set generic_workers = matrix_nginx_proxy_synapse_workers_list|selectattr('type', 'equalto', 'generic_worker')|list %} -{% set media_repository_workers = matrix_nginx_proxy_synapse_workers_list|selectattr('type', 'equalto', 'media_repository')|list %} -{% set user_dir_workers = matrix_nginx_proxy_synapse_workers_list|selectattr('type', 'equalto', 'user_dir')|list %} -{% set frontend_proxy_workers = matrix_nginx_proxy_synapse_workers_list|selectattr('type', 'equalto', 'frontend_proxy')|list %} -{% if matrix_nginx_proxy_synapse_workers_enabled %} - # Round Robin "upstream" pools for workers - - {% if generic_workers %} - upstream generic_worker_upstream { - # ensures that requests from the same client will always be passed - # to the same server (except when this server is unavailable) - ip_hash; - - {% for worker in generic_workers %} - server "matrix-synapse:{{ worker.port }}"; - {% endfor %} - } - {% endif %} - - {% if frontend_proxy_workers %} - upstream frontend_proxy_upstream { - {% for worker in frontend_proxy_workers %} - server "matrix-synapse:{{ worker.port }}"; - {% endfor %} - } - {% endif %} - - {% if media_repository_workers %} - upstream media_repository_upstream { - {% for worker in media_repository_workers %} - server "matrix-synapse:{{ worker.port }}"; - {% endfor %} - } - {% endif %} - - {% if user_dir_workers %} - upstream user_dir_upstream { - {% for worker in user_dir_workers %} - server "matrix-synapse:{{ worker.port }}"; - {% endfor %} - } - {% endif %} -{% endif %} - -server { - listen {{ 8080 if matrix_nginx_proxy_enabled else 80 }}; - server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; - - server_tokens off; - root /dev/null; - - {% if matrix_nginx_proxy_https_enabled %} - location /.well-known/acme-challenge { - {% if matrix_nginx_proxy_enabled %} - {# Use the embedded DNS resolver in Docker containers to discover the service #} - resolver 127.0.0.11 valid=5s; - set $backend "matrix-certbot:8080"; - proxy_pass http://$backend; - {% else %} - {# Generic configuration for use outside of our container setup #} - proxy_pass http://127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}; - {% endif %} - } - - {% if matrix_nginx_proxy_proxy_matrix_nginx_status_enabled %} - {{ render_nginx_status_location_block(matrix_nginx_proxy_proxy_matrix_nginx_status_allowed_addresses) }} - {% endif %} - - location / { - return 301 https://$http_host$request_uri; - } - {% else %} - {{ render_vhost_directives() }} - {% endif %} } -{% if matrix_nginx_proxy_https_enabled %} +{% if matrix_nginx_proxy_proxy_synapse_federation_api_enabled %} server { - listen {{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; - listen [::]:{{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; + listen 12088; - server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; - - server_tokens off; - root /dev/null; - - ssl_certificate {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/fullchain.pem; - ssl_certificate_key {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/privkey.pem; - - ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }}; - {% if matrix_nginx_proxy_ssl_ciphers != '' %} - ssl_ciphers {{ matrix_nginx_proxy_ssl_ciphers }}; - {% endif %} - ssl_prefer_server_ciphers {{ matrix_nginx_proxy_ssl_prefer_server_ciphers }}; - - {{ render_vhost_directives() }} -} -{% endif %} - -{% if matrix_nginx_proxy_proxy_matrix_federation_api_enabled %} -{# - This federation vhost is a little special. - It serves federation over HTTP or HTTPS, depending on `matrix_nginx_proxy_https_enabled`. -#} -server { - {% if matrix_nginx_proxy_https_enabled %} - listen 8448 ssl http2; - listen [::]:8448 ssl http2; - {% else %} - listen 8448; - {% endif %} - - server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; + server_name {{ matrix_nginx_proxy_proxy_synapse_hostname }}; server_tokens off; root /dev/null; @@ -345,18 +176,6 @@ server { gzip on; gzip_types text/plain application/json; - {% if matrix_nginx_proxy_https_enabled %} - ssl_certificate {{ matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate }}; - ssl_certificate_key {{ matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate_key }}; - - ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }}; - {% if matrix_nginx_proxy_ssl_ciphers != '' %} - ssl_ciphers {{ matrix_nginx_proxy_ssl_ciphers }}; - {% endif %} - ssl_prefer_server_ciphers {{ matrix_nginx_proxy_ssl_prefer_server_ciphers }}; - - {% endif %} - {% if matrix_nginx_proxy_synapse_workers_enabled %} {% if generic_workers %} # https://github.com/matrix-org/synapse/blob/master/docs/workers.md#synapseappgeneric_worker @@ -367,7 +186,6 @@ server { proxy_set_header X-Forwarded-For $remote_addr; } {% endfor %} - # FIXME: add GET ^/_matrix/federation/v1/groups/ {% endif %} {% if media_repository_workers %} # https://github.com/matrix-org/synapse/blob/master/docs/workers.md#synapseappmedia_repository @@ -389,11 +207,11 @@ server { {% if matrix_nginx_proxy_enabled %} {# Use the embedded DNS resolver in Docker containers to discover the service #} resolver 127.0.0.11 valid=5s; - set $backend "{{ matrix_nginx_proxy_proxy_matrix_federation_api_addr_with_container }}"; + set $backend "{{ matrix_nginx_proxy_proxy_synapse_federation_api_addr_with_container }}"; proxy_pass http://$backend; {% else %} {# Generic configuration for use outside of our container setup #} - proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_federation_api_addr_sans_container }}; + proxy_pass http://{{ matrix_nginx_proxy_proxy_synapse_federation_api_addr_sans_container }}; {% endif %} proxy_set_header Host $host;