Initial work on Synapse 0.99/1.0 preparation

This commit is contained in:
Slavi Pantaleev
2019-02-05 11:07:08 +02:00
parent e06e5dd208
commit f6ebd4ce62
19 changed files with 416 additions and 130 deletions

View File

@ -12,10 +12,13 @@
with_items:
- "{{ matrix_static_files_base_path }}/.well-known/matrix"
- name: Ensure Matrix /.well-known/matrix/client configured
- name: Ensure Matrix /.well-known/matrix files configured
template:
src: "{{ role_path }}/templates/static-files/well-known/matrix-client.j2"
dest: "{{ matrix_static_files_base_path }}/.well-known/matrix/client"
src: "{{ role_path }}/templates/static-files/well-known/matrix-{{ item }}.j2"
dest: "{{ matrix_static_files_base_path }}/.well-known/matrix/{{ item }}"
mode: 0644
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"
with_items:
- "client"
- "server"

View File

@ -0,0 +1,3 @@
{
"m.server": "{{ hostname_matrix }}:8448"
}

View File

@ -36,6 +36,7 @@
mode: 0644
when: "matrix_corporal_enabled"
#
# Tasks related to getting rid of matrix-corporal (if it was previously enabled)
#

View File

@ -57,8 +57,14 @@ matrix_nginx_proxy_proxy_matrix_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: 25
# 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_client_max_body_size_mb: "{{ matrix_nginx_proxy_proxy_matrix_client_api_client_max_body_size_mb * 3 }}"
# 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_client_api_client_max_body_size_mb * 50 }}"
matrix_nginx_proxy_tmp_directory_size_mb: "{{ matrix_nginx_proxy_proxy_matrix_federation_api_client_max_body_size_mb * 50 }}"
# A list of strings containing additional configuration blocks to add to the matrix domain's server configuration.
matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks: []

View File

@ -1,65 +1,13 @@
---
- set_fact:
well_known_url_matrix: "https://{{ hostname_matrix }}/.well-known/matrix/client"
well_known_url_identity: "https://{{ hostname_identity }}/.well-known/matrix/client"
# These well-known files may be served without a `Content-Type: application/json` header,
# so we can't rely on the uri module's automatic parsing of JSON.
- name: Check .well-known on the matrix hostname
uri:
url: "{{ well_known_url_matrix }}"
follow_redirects: false
return_content: true
register: result_well_known_matrix
ignore_errors: true
- name: Fail if .well-known not working on the matrix hostname
fail:
msg: "Failed checking that well-known is configured at `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`). Is port 443 open in your firewall? Full error: {{ result_well_known_matrix }}"
when: "result_well_known_matrix.failed"
- name: Parse JSON for well-known payload at the matrix hostname
set_fact:
well_known_matrix_payload: "{{ result_well_known_matrix.content|from_json }}"
- name: Fail if .well-known not CORS-aware on the matrix hostname
fail:
msg: "Well-known serving for `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`) is not CORS-aware. The file needs to be served with an Access-Control-Allow-Origin header set."
when: "'access_control_allow_origin' not in result_well_known_matrix"
- name: Report working .well-known on the matrix hostname
debug:
msg: "well-known is configured correctly for `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`)"
- name: Check .well-known on the identity hostname
uri:
url: "{{ well_known_url_identity }}"
follow_redirects: false
return_content: true
register: result_well_known_identity
ignore_errors: true
- name: Fail if .well-known not working on the identity hostname
fail:
msg: "Failed checking that well-known is configured at `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`). Is port 443 open in your firewall? Full error: {{ result_well_known_identity }}"
when: "result_well_known_identity.failed"
- name: Parse JSON for well-known payload at the identity hostname
set_fact:
well_known_identity_payload: "{{ result_well_known_identity.content|from_json }}"
- name: Fail if .well-known not CORS-aware on the identity hostname
fail:
msg: "Well-known serving for `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`) is not CORS-aware. The file needs to be served with an Access-Control-Allow-Origin header set. See docs/configuring-well-known.md"
when: "'access_control_allow_origin' not in result_well_known_identity"
# For people who manually copy the well-known file, try to detect if it's outdated
- name: Fail if well-known is different on matrix hostname and identity hostname
fail:
msg: "The well-known files at `{{ hostname_matrix }}` and `{{ hostname_identity }}` are different. Perhaps you copied the file manually before and now it's outdated?"
when: "well_known_matrix_payload != well_known_identity_payload"
- name: Report working .well-known on the identity hostname
debug:
msg: "well-known is configured correctly for `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`)"
- name: Perform well-known checks
include_tasks: "{{ role_path }}/tasks/self_check_well_known_file.yml"
with_items:
- path: /.well-known/matrix/server
purpose: Server Discovery
cors: false
- path: /.well-known/matrix/client
purpose: Client Discovery
cors: true
loop_control:
loop_var: well_known_file_check

View File

@ -0,0 +1,65 @@
---
- set_fact:
well_known_url_matrix: "https://{{ hostname_matrix }}{{ well_known_file_check.path }}"
well_known_url_identity: "https://{{ hostname_identity }}{{ well_known_file_check.path }}"
# These well-known files may be served without a `Content-Type: application/json` header,
# so we can't rely on the uri module's automatic parsing of JSON.
- name: Check .well-known on the matrix hostname
uri:
url: "{{ well_known_url_matrix }}"
follow_redirects: false
return_content: true
register: result_well_known_matrix
ignore_errors: true
- name: Fail if .well-known not working on the matrix hostname
fail:
msg: "Failed checking that the well-known file for {{ well_known_file_check.purpose }} is configured at `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`). Is port 443 open in your firewall? Full error: {{ result_well_known_matrix }}"
when: "result_well_known_matrix.failed"
- name: Parse JSON for well-known payload at the matrix hostname
set_fact:
well_known_matrix_payload: "{{ result_well_known_matrix.content|from_json }}"
- name: Fail if .well-known not CORS-aware on the matrix hostname
fail:
msg: "The well-known file for {{ well_known_file_check.purpose }} on `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`) is not CORS-aware. The file needs to be served with an Access-Control-Allow-Origin header set."
when: "well_known_file_check.cors and 'access_control_allow_origin' not in result_well_known_matrix"
- name: Report working .well-known on the matrix hostname
debug:
msg: "well-known for {{ well_known_file_check.purpose }} is configured correctly for `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`)"
- name: Check .well-known on the identity hostname
uri:
url: "{{ well_known_url_identity }}"
follow_redirects: false
return_content: true
register: result_well_known_identity
ignore_errors: true
- name: Fail if .well-known not working on the identity hostname
fail:
msg: "Failed checking that the well-known file for {{ well_known_file_check.purpose }} is configured at `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`). Is port 443 open in your firewall? Full error: {{ result_well_known_identity }}"
when: "result_well_known_identity.failed"
- name: Parse JSON for well-known payload at the identity hostname
set_fact:
well_known_identity_payload: "{{ result_well_known_identity.content|from_json }}"
- name: Fail if .well-known not CORS-aware on the identity hostname
fail:
msg: "The well-known file for {{ well_known_file_check.purpose }} on `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`) is not CORS-aware. The file needs to be served with an Access-Control-Allow-Origin header set. See docs/configuring-well-known.md"
when: "well_known_file_check.cors and 'access_control_allow_origin' not in result_well_known_identity"
# For people who manually copy the well-known file, try to detect if it's outdated
- name: Fail if well-known is different on matrix hostname and identity hostname
fail:
msg: "The well-known files for {{ well_known_file_check.purpose }} at `{{ hostname_matrix }}` and `{{ hostname_identity }}` are different. Perhaps you copied the file ({{ well_known_file_check.path }}) manually before and now it's outdated?"
when: "well_known_matrix_payload != well_known_identity_payload"
- name: Report working .well-known on the identity hostname
debug:
msg: "well-known for {{ well_known_file_check.purpose }} ({{ well_known_file_check.path }}) is configured correctly for `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`)"

View File

@ -39,7 +39,7 @@ server {
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
location /.well-known/matrix/client {
location /.well-known/matrix {
root {{ matrix_static_files_base_path }};
expires 1m;
default_type application/json;
@ -101,6 +101,10 @@ server {
{{- configuration_block }}
{% endfor %}
{#
This handles the Matrix Client API only.
The Matrix Federation API is handled by a separate vhost.
#}
location /_matrix {
{% if matrix_nginx_proxy_enabled %}
{# Use the embedded DNS resolver in Docker containers to discover the service #}
@ -146,3 +150,43 @@ server {
rewrite ^/$ /_matrix/static/ last;
}
}
{% if matrix_nginx_proxy_proxy_matrix_federation_api_enabled %}
server {
listen 8448 ssl http2;
listen [::]:8448 ssl http2;
server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }};
server_tokens off;
root /dev/null;
gzip on;
gzip_types text/plain application/json;
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 }};
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
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 %}

View File

@ -22,6 +22,9 @@ ExecStart=/usr/bin/docker run --rm --name matrix-nginx-proxy \
--network={{ matrix_docker_network }} \
-p 80:8080 \
-p 443:8443 \
{% if matrix_nginx_proxy_proxy_matrix_federation_api_enabled %}
-p 8448:8448 \
{% endif %}
-v {{ matrix_nginx_proxy_data_path }}/nginx.conf:/etc/nginx/nginx.conf:ro \
-v {{ matrix_nginx_proxy_confd_path }}:/etc/nginx/conf.d:ro \
-v {{ matrix_ssl_config_dir_path }}:{{ matrix_ssl_config_dir_path }}:ro \

View File

@ -8,7 +8,12 @@ matrix_synapse_media_store_path: "{{ matrix_synapse_storage_path }}/media-store"
matrix_synapse_ext_path: "{{ matrix_synapse_base_path }}/ext"
# Controls whether the Synapse container exposes the Client/Server API port (tcp/8008).
matrix_synapse_container_expose_client_server_api_port: false
matrix_synapse_container_expose_client_api_port: false
# Controls whether the Synapse container exposes the Server/Server (Federation) API port (tcp/8048).
# This is for the plain HTTP API. If you need Synapse to handle TLS encryption,
# that would be on another port (tcp/8448) controlled by `matrix_synapse_tls_federation_listener_enabled`.
matrix_synapse_container_expose_federation_api_port: false
# Controls whether the Appservice IRC container exposes the Client/Server API port (tcp/9999).
matrix_appservice_irc_container_expose_client_server_api_port: false
@ -60,6 +65,17 @@ matrix_synapse_root_log_level: "INFO"
matrix_synapse_rc_messages_per_second: 0.2
matrix_synapse_rc_message_burst_count: 10.0
# If you're serving Synapse behind an HTTPS-capable reverse-proxy,
# you can disable TLS completely (`matrix_synapse_no_tls: true`).
# Otherwise, you would need to provide certificate files to it.
matrix_synapse_no_tls: false
# Controls whether the TLS federation listener is enabled (tcp/8448).
# Note that federation may potentially be enabled on tcp/8008 as well.
# Only makes sense if federation is not disabled (`matrix_synapse_federation_enabled`).
matrix_synapse_tls_federation_listener_enabled: "{{ not matrix_synapse_no_tls }}"
matrix_synapse_tls_certificate_path: "/data/{{ hostname_matrix }}.tls.crt"
matrix_synapse_tls_private_key_path: "/data/{{ hostname_matrix }}.tls.key"
# Enable this to allow Synapse to report utilization statistics about your server to matrix.org
# (things like number of users, number of messages sent, uptime, load, etc.)
matrix_synapse_report_stats: false
@ -95,6 +111,8 @@ matrix_synapse_cache_factor: 0.5
# Controls whether Matrix Synapse will federate at all.
# Disable this to completely isolate your server from the rest of the Matrix network.
# Also see: `matrix_synapse_tls_federation_listener_enabled` if you wish to keep federation enabled,
# but want to stop the TLS listener (port 8448).
matrix_synapse_federation_enabled: true
# A list of domain names that are allowed to federate with the given Matrix Synapse server.

View File

@ -58,6 +58,61 @@
dest: "{{ matrix_synapse_config_dir_path }}/{{ hostname_matrix }}.log.config"
mode: 0644
#
# To make Synapse 0.99 happy, we need to generate a valid (self-signed is OK) certificate file that we provide to it.
# It won't be used for anything important, but it needs to be there.
# See https://github.com/matrix-org/synapse/issues/4554
#
# Previously, Synapse would generate such certificate files and actually use them.
# So existing installations already have them.
#
- name: Check if Synapse certificate exists
stat:
path: "{{ matrix_synapse_config_dir_path }}/{{ hostname_matrix }}.tls.crt"
register: matrix_synapse_certificate_stat
- name: Ensure OpenSSL installed (RedHat)
yum:
name:
- openssl
state: present
update_cache: no
when: "not matrix_synapse_certificate_stat.stat.exists and ansible_os_family == 'RedHat'"
- name: Ensure OpenSSL installed (Debian)
apt:
name:
- openssl
state: present
update_cache: no
when: "not matrix_synapse_certificate_stat.stat.exists and ansible_os_family == 'Debian'"
# The proper way to do this is by using a sequence of
# `openssl_privatekey`, `openssl_csr` and `openssl_certificate`.
#
# Unfortunately, `openssl_csr` and `openssl_certificate` require `PyOpenSSL>=0.15` to work,
# which is not available on CentOS 7 (at least).
#
# We'll do it in a more manual way.
- name: Generate SSL certificate
command: |
openssl req -x509 \
-sha256 \
-newkey rsa:4096 \
-nodes \
-subj "/CN={{ hostname_matrix }}" \
-keyout {{ matrix_synapse_config_dir_path }}/{{ hostname_matrix }}.tls.key \
-out {{ matrix_synapse_config_dir_path }}/{{ hostname_matrix }}.tls.crt \
-days 3650
become: true
become_user: "{{ matrix_user_username }}"
when: "not matrix_synapse_certificate_stat.stat.exists"
#
# End of tasks related to making Synapse 0.99 happy.
#
- name: Ensure matrix-synapse.service installed
template:
src: "{{ role_path }}/templates/synapse/systemd/matrix-synapse.service.j2"

View File

@ -6,4 +6,14 @@
You need to define a required configuration setting (`{{ item }}`) for using Synapse.
when: "vars[item] == ''"
with_items:
- "matrix_synapse_macaroon_secret_key"
- "matrix_synapse_macaroon_secret_key"
- name: (Deprecation) Catch and report renamed settings
fail:
msg: >
Your configuration contains a variable, which now has a different name.
Please change your configuration to rename the variable (`{{ item.old }}` -> `{{ item.new }}`).
when: "item.old in vars"
with_items:
- {'old': 'matrix_synapse_container_expose_api_port', 'new': 'matrix_synapse_container_expose_client_api_port'}

View File

@ -1,19 +1,70 @@
# vim:ft=yaml
# PEM encoded X509 certificate for TLS.
# You can replace the self-signed certificate that synapse
# autogenerates on launch with your own SSL certificate + key pair
# if you like. Any required intermediary certificates can be
# appended after the primary certificate in hierarchical order.
tls_certificate_path: "/data/{{ hostname_matrix }}.tls.crt"
# PEM-encoded X509 certificate for TLS.
# This certificate, as of Synapse 1.0, will need to be a valid and verifiable
# certificate, signed by a recognised Certificate Authority.
#
# See 'ACME support' below to enable auto-provisioning this certificate via
# Let's Encrypt.
#
tls_certificate_path: "{{ matrix_synapse_tls_certificate_path }}"
# PEM encoded private key for TLS
tls_private_key_path: "/data/{{ hostname_matrix }}.tls.key"
# PEM-encoded private key for TLS
tls_private_key_path: "{{ matrix_synapse_tls_private_key_path }}"
# PEM dh parameters for ephemeral keys
tls_dh_params_path: "/data/{{ hostname_matrix }}.tls.dh"
# ACME support: This will configure Synapse to request a valid TLS certificate
# for your configured `server_name` via Let's Encrypt.
#
# Note that provisioning a certificate in this way requires port 80 to be
# routed to Synapse so that it can complete the http-01 ACME challenge.
# By default, if you enable ACME support, Synapse will attempt to listen on
# port 80 for incoming http-01 challenges - however, this will likely fail
# with 'Permission denied' or a similar error.
#
# There are a couple of potential solutions to this:
#
# * If you already have an Apache, Nginx, or similar listening on port 80,
# you can configure Synapse to use an alternate port, and have your web
# server forward the requests. For example, assuming you set 'port: 8009'
# below, on Apache, you would write:
#
# ProxyPass /.well-known/acme-challenge http://localhost:8009/.well-known/acme-challenge
#
# * Alternatively, you can use something like `authbind` to give Synapse
# permission to listen on port 80.
#
acme:
# ACME support is disabled by default. Uncomment the following line
# to enable it.
#
# enabled: true
# Don't bind to the https port
no_tls: False
# Endpoint to use to request certificates. If you only want to test,
# use Let's Encrypt's staging url:
# https://acme-staging.api.letsencrypt.org/directory
#
# url: https://acme-v01.api.letsencrypt.org/directory
# Port number to listen on for the HTTP-01 challenge. Change this if
# you are forwarding connections through Apache/Nginx/etc.
#
# port: 80
# Local addresses to listen on for incoming connections.
# Again, you may want to change this if you are forwarding connections
# through Apache/Nginx/etc.
#
# bind_addresses: ['::', '0.0.0.0']
# How many days remaining on a certificate before it is renewed.
#
# reprovision_threshold: 30
# If your server runs behind a reverse-proxy which terminates TLS connections
# (for both client and federation connections), it may be useful to disable
# All TLS support for incoming connections. Setting no_tls to True will
# do so (and avoid the need to give synapse a TLS private key).
#
no_tls: {{ matrix_synapse_no_tls|to_json }}
# List of allowed TLS fingerprints for this server to publish along
# with the signing keys for this server. Other matrix servers that
@ -133,7 +184,8 @@ listeners:
bind_addresses:
- '0.0.0.0'
{% endif %}
{% if matrix_synapse_federation_enabled %}
{% if matrix_synapse_federation_enabled and matrix_synapse_tls_federation_listener_enabled %}
# Main HTTPS listener
# For when matrix traffic is sent directly to synapse.
-
@ -168,7 +220,7 @@ listeners:
# config: {}
{% endif %}
# Unsecure HTTP listener,
# Unsecure HTTP listener for the Client API,
# For when matrix traffic passes through loadbalancer that unwraps TLS.
- port: 8008
tls: false
@ -181,6 +233,21 @@ listeners:
- names: [client]
compress: false
{% if matrix_synapse_federation_enabled %}
# Unsecure HTTP listener for the Federation API,
# For when matrix traffic passes through loadbalancer that unwraps TLS.
- port: 8048
tls: false
bind_addresses: ['::']
type: http
x_forwarded: true
resources:
- names: [federation]
compress: false
{% endif %}
# Turn on the twisted ssh manhole service on localhost on the given
# port.
# - port: 9000

View File

@ -28,11 +28,14 @@ ExecStart=/usr/bin/docker run --rm --name matrix-synapse \
--tmpfs=/tmp:rw,noexec,nosuid,size={{ matrix_synapse_tmp_directory_size_mb }}m \
--network={{ matrix_docker_network }} \
-e SYNAPSE_CACHE_FACTOR={{ matrix_synapse_cache_factor }} \
{% if matrix_synapse_federation_enabled %}
{% if matrix_synapse_container_expose_client_api_port %}
-p 127.0.0.1:8008:8008 \
{% endif %}
{% if matrix_synapse_federation_enabled and matrix_synapse_tls_federation_listener_enabled %}
-p 8448:8448 \
{% endif %}
{% if matrix_synapse_container_expose_client_server_api_port %}
-p 127.0.0.1:8008:8008 \
{% if matrix_synapse_federation_enabled and matrix_synapse_container_expose_federation_api_port %}
-p 127.0.0.1:8048:8048 \
{% endif %}
{% if matrix_synapse_container_expose_metrics_port %}
-p 127.0.0.1:{{ matrix_synapse_metrics_port }}:{{ matrix_synapse_metrics_port }} \