commit
fca9e8f0b8
@ -0,0 +1,147 @@
|
|||||||
|
# Server Delegation
|
||||||
|
|
||||||
|
To have a server on a subdomain (e.g. `matrix.<your-domain>`) handle Matrix federation traffic for the base domain (`<your-domain>`), we need to instruct the Matrix network of such a delegation.
|
||||||
|
|
||||||
|
By default, this playbook guides you into setting up [Server Delegation via a well-known file](#server-delegation-via-a-well-known-file).
|
||||||
|
However, that method may have some downsides that are not to your liking. Hence this guide about alternative ways to set up Server Delegation.
|
||||||
|
|
||||||
|
It is a complicated matter, so unless you are affected by the [Downsides of well-known-based Server Delegation](#downsides-of-well-known-based-server-delegation), we suggest you stay on the simple/default path.
|
||||||
|
|
||||||
|
|
||||||
|
## Server Delegation via a well-known file
|
||||||
|
|
||||||
|
Serving a `/.well-known/matrix/server` file from the base domain is the most straightforward way to set up server delegation, but it suffers from the following problems:
|
||||||
|
|
||||||
|
As we already mention in [Configuring DNS](configuring-dns.md) and [Configuring Service Discovery via .well-known](configuring-well-known.md),
|
||||||
|
this playbook already properly guides you into setting up such delegation by means of a `/.well-known/matrix/server` file served from the base domain (`<your-domain>`).
|
||||||
|
|
||||||
|
If this is okay with you, feel free to not read ahead.
|
||||||
|
|
||||||
|
|
||||||
|
### Downsides of well-known-based Server Delegation
|
||||||
|
|
||||||
|
Server Delegation by means of a `/.well-known/matrix/server` file is the most straightforward, but suffers from the following downsides:
|
||||||
|
|
||||||
|
- you need to have a working HTTPS server for the base domain (`<your-domain>`)
|
||||||
|
|
||||||
|
- any downtime on the base domain (`<your-domain>`) or network trouble between the matrix subdomain (`matrix.<your-domain>`) and the base `<domain>` may cause Matrix Federation outages. As the [Server-Server spec says](https://matrix.org/docs/spec/server_server/r0.1.0.html#server-discovery):
|
||||||
|
|
||||||
|
> Errors are recommended to be cached for up to an hour, and servers are encouraged to exponentially back off for repeated failures.
|
||||||
|
|
||||||
|
If this is not a concern for you, feel free to not read ahead.
|
||||||
|
|
||||||
|
Otherwise, you can decide to go against the default for this playbook, and instead set up [Server Delegation via a DNS SRV record (advanced)](#server-delegation-via-a-dns-srv-record-advanced).
|
||||||
|
|
||||||
|
|
||||||
|
## Server Delegation via a DNS SRV record (advanced)
|
||||||
|
|
||||||
|
**NOTE**: doing Server Delegation via a DNS SRV record is a more advanced way to do it and is not the default for this playbook.
|
||||||
|
|
||||||
|
As per the [Server-Server spec](https://matrix.org/docs/spec/server_server/r0.1.0.html#server-discovery), it's possible to do Server Delegation using only a SRV record (without a `/.well-known/matrix/server` file).
|
||||||
|
|
||||||
|
This prevents you from suffering the [Downsides of well-known-based Server Delegation](#downsides-of-well-known-based-server-delegation).
|
||||||
|
|
||||||
|
To use DNS SRV record validation, you need to:
|
||||||
|
|
||||||
|
- ensure that no `/.well-known/matrix/server` is served from the base domain, as that would interfere with DNS SRV record Server Delegation. To make the playbook **not** generate and serve the file, use the following configuration: `matrix_well_known_matrix_server_enabled: false`.
|
||||||
|
|
||||||
|
- ensure that you have a `_matrix._tcp` DNS SRV record for your base domain (`<your-domain>`) with a value of `10 0 8448 matrix.<your-domain>`
|
||||||
|
|
||||||
|
- ensure that you are serving the Matrix Federation API (tcp/8448) with a certificate for `<your-domain>` (not `matrix.<your-domain>`!). See below.
|
||||||
|
|
||||||
|
|
||||||
|
### Obtaining certificates
|
||||||
|
|
||||||
|
How you can obtain a valid certificate for `<your-domain>` on the `matrix.<your-domain>` server is up to you.
|
||||||
|
|
||||||
|
If `<your-domain>` and `matrix.<your-domain>` is the same machine, you can let the playbook obtain the certificate for you by redefining the `matrix_ssl_domains_to_obtain_certificates_for` variable. Example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
matrix_ssl_domains_to_obtain_certificates_for:
|
||||||
|
- '{{ hostname_matrix }}'
|
||||||
|
- '{{ hostname_riot }}'
|
||||||
|
- '{{ hostname_identity }}'
|
||||||
|
```
|
||||||
|
|
||||||
|
This way, the playbook would obtain certificates for your base domain as well (referred to by the `hostname_identity` variable).
|
||||||
|
The certificate files would be available in `/matrix/ssl/config/live/<your-domain>/...`.
|
||||||
|
|
||||||
|
If `<your-domain>` and `matrix.<your-domain>` are not the same machine, you can copy over the certificate files manually.
|
||||||
|
If they get renewed automatically, you may also have to transfer them periodically. How often you do that is up to you, as long as the certificate files don't expire.
|
||||||
|
|
||||||
|
|
||||||
|
### Serving the Federation API with your certificates
|
||||||
|
|
||||||
|
Regardless of which method for obtaining certificates you've used, once you've managed to get certificates for your base domain onto the `matrix.<your-domain>` machine you can put them to use.
|
||||||
|
|
||||||
|
Based on your setup, you have different ways to go about it:
|
||||||
|
|
||||||
|
- [Serving the Federation API with your certificates and matrix-nginx-proxy](#serving-the-federation-api-with-your-certificates-and-matrix-nginx-proxy)
|
||||||
|
|
||||||
|
- [Serving the Federation API with your certificates and another webserver](#serving-the-federation-api-with-your-certificates-and-another-webserver)
|
||||||
|
|
||||||
|
- [Serving the Federation API with your certificates and Synapse handling Federation](#serving-the-federation-api-with-your-certificates-and-synapse-handling-federation)
|
||||||
|
|
||||||
|
|
||||||
|
### Serving the Federation API with your certificates and matrix-nginx-proxy
|
||||||
|
|
||||||
|
**If you are using matrix-nginx-proxy**, a reverse-proxy webserver used by default in this playbook, you only need to override the certificates used for the Matrix Federation API. You can do that using:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Adjust paths below to point to your certificate.
|
||||||
|
#
|
||||||
|
# NOTE: these are in-container paths. `/matrix/ssl` on the host is mounted into the container
|
||||||
|
# at the same path (`/matrix/ssl`) by default, so if that's the path you need, it would be seamless.
|
||||||
|
matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate: /matrix/ssl/config/live/<your-domain>/fullchain.pem
|
||||||
|
matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate_key: /matrix/ssl/config/live/<your-domain>/privkey.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
If your files are not in `/matrix/ssl` but in some other location, you would need to mount them into the container:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
matrix_nginx_proxy_container_additional_volumes:
|
||||||
|
- src: /some/path/on/the/host
|
||||||
|
dst: /some/path/inside/the/container
|
||||||
|
options: ro
|
||||||
|
```
|
||||||
|
|
||||||
|
You then refer to them (for `matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate` and `matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate_key`) by using `/some/path/inside/the/container`.
|
||||||
|
|
||||||
|
Make sure to reload matrix-nginx-proxy once in a while (`systemctl reload matrix-nginx-proxy`), so that newer certificates can kick in.
|
||||||
|
Reloading doesn't cause any downtime.
|
||||||
|
|
||||||
|
|
||||||
|
### Serving the Federation API with your certificates and another webserver
|
||||||
|
|
||||||
|
**If you are NOT using matrix-nginx-proxy**, but rather some other webserver, you can set up reverse-proxying for the `tcp/8448` port by yourself.
|
||||||
|
Make sure to use the proper certificates for `<your-domain>` (not for `matrix.<your-domain>`) when serving the `tcp/8448` port.
|
||||||
|
|
||||||
|
Proxying needs to happen to `127.0.0.1:8048` (unencrypted Synapse federation listener).
|
||||||
|
|
||||||
|
Make sure to reload/restart your webserver once in a while, so that newer certificates can kick in.
|
||||||
|
|
||||||
|
|
||||||
|
### Serving the Federation API with your certificates and Synapse handling Federation
|
||||||
|
|
||||||
|
**Alternatively**, if you are **NOT using matrix-nginx-proxy** and **would rather not use your own webserver for Federation traffic**, you can let Synapse handle Federation by itself.
|
||||||
|
|
||||||
|
To do that, make sure the certificate files are mounted into the Synapse container:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
matrix_synapse_container_additional_volumes:
|
||||||
|
- src: /some/path/on/the/host
|
||||||
|
dst: /some/path/inside/the/container
|
||||||
|
options: ro
|
||||||
|
```
|
||||||
|
|
||||||
|
You can then tell Synapse to serve Federation traffic over TLS on `tcp/8448`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
matrix_synapse_no_tls: false
|
||||||
|
matrix_synapse_tls_federation_listener_enabled: true
|
||||||
|
matrix_synapse_tls_certificate_path: /some/path/inside/the/container/certificate.crt
|
||||||
|
matrix_synapse_tls_private_key_path: /some/path/inside/the/container/private.key
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure to reload Synapse once in a while (`systemctl reload matrix-synapse`), so that newer certificates can kick in.
|
||||||
|
Reloading doesn't cause any downtime.
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"m.server": "{{ hostname_matrix }}:8448"
|
||||||
|
}
|
@ -1,65 +1,26 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
- set_fact:
|
- name: Determine well-known files to check (Matrix)
|
||||||
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:
|
set_fact:
|
||||||
well_known_matrix_payload: "{{ result_well_known_matrix.content|from_json }}"
|
well_known_file_checks:
|
||||||
|
- path: /.well-known/matrix/client
|
||||||
- name: Fail if .well-known not CORS-aware on the matrix hostname
|
purpose: Client Discovery
|
||||||
fail:
|
cors: true
|
||||||
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"
|
- block:
|
||||||
|
- set_fact:
|
||||||
- name: Report working .well-known on the matrix hostname
|
well_known_file_check_matrix_server:
|
||||||
debug:
|
path: /.well-known/matrix/server
|
||||||
msg: "well-known is configured correctly for `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`)"
|
purpose: Server Discovery
|
||||||
|
cors: false
|
||||||
- name: Check .well-known on the identity hostname
|
|
||||||
uri:
|
- name: Determine domains that we require certificates for (mxisd)
|
||||||
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:
|
set_fact:
|
||||||
well_known_identity_payload: "{{ result_well_known_identity.content|from_json }}"
|
well_known_file_checks: "{{ well_known_file_checks + [well_known_file_check_matrix_server] }}"
|
||||||
|
when: "matrix_well_known_matrix_server_enabled"
|
||||||
- name: Fail if .well-known not CORS-aware on the identity hostname
|
|
||||||
fail:
|
- name: Perform well-known checks
|
||||||
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"
|
include_tasks: "{{ role_path }}/tasks/self_check_well_known_file.yml"
|
||||||
when: "'access_control_allow_origin' not in result_well_known_identity"
|
with_items: "{{ well_known_file_checks }}"
|
||||||
|
loop_control:
|
||||||
# For people who manually copy the well-known file, try to detect if it's outdated
|
loop_var: well_known_file_check
|
||||||
- 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 }}`)"
|
|
||||||
|
@ -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 }}`)"
|
Loading…
Reference in new issue