forked from MirrorHub/synapse
8d20b1ba1e
* Broken link "request_id_header" The link above leads to an ERROR 404 * Update docs/reverse_proxy.md Co-authored-by: reivilibre <olivier@librepush.net>
265 lines
9.5 KiB
Markdown
265 lines
9.5 KiB
Markdown
# Using a reverse proxy with Synapse
|
|
|
|
It is recommended to put a reverse proxy such as
|
|
[nginx](https://nginx.org/en/docs/http/ngx_http_proxy_module.html),
|
|
[Apache](https://httpd.apache.org/docs/current/mod/mod_proxy_http.html),
|
|
[Caddy](https://caddyserver.com/docs/quick-starts/reverse-proxy),
|
|
[HAProxy](https://www.haproxy.org/) or
|
|
[relayd](https://man.openbsd.org/relayd.8) in front of Synapse. One advantage
|
|
of doing so is that it means that you can expose the default https port
|
|
(443) to Matrix clients without needing to run Synapse with root
|
|
privileges.
|
|
|
|
You should configure your reverse proxy to forward requests to `/_matrix` or
|
|
`/_synapse/client` to Synapse, and have it set the `X-Forwarded-For` and
|
|
`X-Forwarded-Proto` request headers.
|
|
|
|
You should remember that Matrix clients and other Matrix servers do not
|
|
necessarily need to connect to your server via the same server name or
|
|
port. Indeed, clients will use port 443 by default, whereas servers default to
|
|
port 8448. Where these are different, we refer to the 'client port' and the
|
|
'federation port'. See [the Matrix
|
|
specification](https://matrix.org/docs/spec/server_server/latest#resolving-server-names)
|
|
for more details of the algorithm used for federation connections, and
|
|
[Delegation](delegate.md) for instructions on setting up delegation.
|
|
|
|
**NOTE**: Your reverse proxy must not `canonicalise` or `normalise`
|
|
the requested URI in any way (for example, by decoding `%xx` escapes).
|
|
Beware that Apache *will* canonicalise URIs unless you specify
|
|
`nocanon`.
|
|
|
|
Let's assume that we expect clients to connect to our server at
|
|
`https://matrix.example.com`, and other servers to connect at
|
|
`https://example.com:8448`. The following sections detail the configuration of
|
|
the reverse proxy and the homeserver.
|
|
|
|
|
|
## Homeserver Configuration
|
|
|
|
The HTTP configuration will need to be updated for Synapse to correctly record
|
|
client IP addresses and generate redirect URLs while behind a reverse proxy.
|
|
|
|
In `homeserver.yaml` set `x_forwarded: true` in the port 8008 section and
|
|
consider setting `bind_addresses: ['127.0.0.1']` so that the server only
|
|
listens to traffic on localhost. (Do not change `bind_addresses` to `127.0.0.1`
|
|
when using a containerized Synapse, as that will prevent it from responding
|
|
to proxied traffic.)
|
|
|
|
Optionally, you can also set
|
|
[`request_id_header`](./usage/configuration/config_documentation.md#listeners)
|
|
so that the server extracts and re-uses the same request ID format that the
|
|
reverse proxy is using.
|
|
|
|
## Reverse-proxy configuration examples
|
|
|
|
**NOTE**: You only need one of these.
|
|
|
|
### nginx
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl http2;
|
|
listen [::]:443 ssl http2;
|
|
|
|
# For the federation port
|
|
listen 8448 ssl http2 default_server;
|
|
listen [::]:8448 ssl http2 default_server;
|
|
|
|
server_name matrix.example.com;
|
|
|
|
location ~ ^(/_matrix|/_synapse/client) {
|
|
# note: do not add a path (even a single /) after the port in `proxy_pass`,
|
|
# otherwise nginx will canonicalise the URI and cause signature verification
|
|
# errors.
|
|
proxy_pass http://localhost:8008;
|
|
proxy_set_header X-Forwarded-For $remote_addr;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header Host $host;
|
|
|
|
# Nginx by default only allows file uploads up to 1M in size
|
|
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
|
|
client_max_body_size 50M;
|
|
|
|
# Synapse responses may be chunked, which is an HTTP/1.1 feature.
|
|
proxy_http_version 1.1;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Caddy v2
|
|
|
|
```
|
|
matrix.example.com {
|
|
reverse_proxy /_matrix/* localhost:8008
|
|
reverse_proxy /_synapse/client/* localhost:8008
|
|
}
|
|
|
|
example.com:8448 {
|
|
reverse_proxy localhost:8008
|
|
}
|
|
```
|
|
|
|
[Delegation](delegate.md) example:
|
|
|
|
```
|
|
example.com {
|
|
header /.well-known/matrix/* Content-Type application/json
|
|
header /.well-known/matrix/* Access-Control-Allow-Origin *
|
|
respond /.well-known/matrix/server `{"m.server": "matrix.example.com:443"}`
|
|
respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://matrix.example.com"},"m.identity_server":{"base_url":"https://identity.example.com"}}`
|
|
}
|
|
|
|
matrix.example.com {
|
|
reverse_proxy /_matrix/* localhost:8008
|
|
reverse_proxy /_synapse/client/* localhost:8008
|
|
}
|
|
```
|
|
|
|
### Apache
|
|
|
|
```apache
|
|
<VirtualHost *:443>
|
|
SSLEngine on
|
|
ServerName matrix.example.com
|
|
|
|
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
|
|
AllowEncodedSlashes NoDecode
|
|
ProxyPreserveHost on
|
|
ProxyPass /_matrix http://127.0.0.1:8008/_matrix nocanon
|
|
ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix
|
|
ProxyPass /_synapse/client http://127.0.0.1:8008/_synapse/client nocanon
|
|
ProxyPassReverse /_synapse/client http://127.0.0.1:8008/_synapse/client
|
|
</VirtualHost>
|
|
|
|
<VirtualHost *:8448>
|
|
SSLEngine on
|
|
ServerName example.com
|
|
|
|
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
|
|
AllowEncodedSlashes NoDecode
|
|
ProxyPass /_matrix http://127.0.0.1:8008/_matrix nocanon
|
|
ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix
|
|
</VirtualHost>
|
|
```
|
|
|
|
**NOTE**: ensure the `nocanon` options are included.
|
|
|
|
**NOTE 2**: It appears that Synapse is currently incompatible with the ModSecurity module for Apache (`mod_security2`). If you need it enabled for other services on your web server, you can disable it for Synapse's two VirtualHosts by including the following lines before each of the two `</VirtualHost>` above:
|
|
|
|
```apache
|
|
<IfModule security2_module>
|
|
SecRuleEngine off
|
|
</IfModule>
|
|
```
|
|
|
|
**NOTE 3**: Missing `ProxyPreserveHost on` can lead to a redirect loop.
|
|
|
|
### HAProxy
|
|
|
|
```
|
|
frontend https
|
|
bind *:443,[::]:443 ssl crt /etc/ssl/haproxy/ strict-sni alpn h2,http/1.1
|
|
http-request set-header X-Forwarded-Proto https if { ssl_fc }
|
|
http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
|
|
http-request set-header X-Forwarded-For %[src]
|
|
|
|
# Matrix client traffic
|
|
acl matrix-host hdr(host) -i matrix.example.com matrix.example.com:443
|
|
acl matrix-path path_beg /_matrix
|
|
acl matrix-path path_beg /_synapse/client
|
|
|
|
use_backend matrix if matrix-host matrix-path
|
|
|
|
frontend matrix-federation
|
|
bind *:8448,[::]:8448 ssl crt /etc/ssl/haproxy/synapse.pem alpn h2,http/1.1
|
|
http-request set-header X-Forwarded-Proto https if { ssl_fc }
|
|
http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
|
|
http-request set-header X-Forwarded-For %[src]
|
|
|
|
default_backend matrix
|
|
|
|
backend matrix
|
|
server matrix 127.0.0.1:8008
|
|
```
|
|
|
|
|
|
[Delegation](delegate.md) example:
|
|
```
|
|
frontend https
|
|
acl matrix-well-known-client-path path /.well-known/matrix/client
|
|
acl matrix-well-known-server-path path /.well-known/matrix/server
|
|
use_backend matrix-well-known-client if matrix-well-known-client-path
|
|
use_backend matrix-well-known-server if matrix-well-known-server-path
|
|
|
|
backend matrix-well-known-client
|
|
http-after-response set-header Access-Control-Allow-Origin "*"
|
|
http-after-response set-header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
|
|
http-after-response set-header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"
|
|
http-request return status 200 content-type application/json string '{"m.homeserver":{"base_url":"https://matrix.example.com"},"m.identity_server":{"base_url":"https://identity.example.com"}}'
|
|
|
|
backend matrix-well-known-server
|
|
http-after-response set-header Access-Control-Allow-Origin "*"
|
|
http-after-response set-header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
|
|
http-after-response set-header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"
|
|
http-request return status 200 content-type application/json string '{"m.server":"matrix.example.com:443"}'
|
|
```
|
|
|
|
### Relayd
|
|
|
|
```
|
|
table <webserver> { 127.0.0.1 }
|
|
table <matrixserver> { 127.0.0.1 }
|
|
|
|
http protocol "https" {
|
|
tls { no tlsv1.0, ciphers "HIGH" }
|
|
tls keypair "example.com"
|
|
match header set "X-Forwarded-For" value "$REMOTE_ADDR"
|
|
match header set "X-Forwarded-Proto" value "https"
|
|
|
|
# set CORS header for .well-known/matrix/server, .well-known/matrix/client
|
|
# httpd does not support setting headers, so do it here
|
|
match request path "/.well-known/matrix/*" tag "matrix-cors"
|
|
match response tagged "matrix-cors" header set "Access-Control-Allow-Origin" value "*"
|
|
|
|
pass quick path "/_matrix/*" forward to <matrixserver>
|
|
pass quick path "/_synapse/client/*" forward to <matrixserver>
|
|
|
|
# pass on non-matrix traffic to webserver
|
|
pass forward to <webserver>
|
|
}
|
|
|
|
relay "https_traffic" {
|
|
listen on egress port 443 tls
|
|
protocol "https"
|
|
forward to <matrixserver> port 8008 check tcp
|
|
forward to <webserver> port 8080 check tcp
|
|
}
|
|
|
|
http protocol "matrix" {
|
|
tls { no tlsv1.0, ciphers "HIGH" }
|
|
tls keypair "example.com"
|
|
block
|
|
pass quick path "/_matrix/*" forward to <matrixserver>
|
|
pass quick path "/_synapse/client/*" forward to <matrixserver>
|
|
}
|
|
|
|
relay "matrix_federation" {
|
|
listen on egress port 8448 tls
|
|
protocol "matrix"
|
|
forward to <matrixserver> port 8008 check tcp
|
|
}
|
|
```
|
|
|
|
|
|
## Health check endpoint
|
|
|
|
Synapse exposes a health check endpoint for use by reverse proxies.
|
|
Each configured HTTP listener has a `/health` endpoint which always returns
|
|
200 OK (and doesn't get logged).
|
|
|
|
## Synapse administration endpoints
|
|
|
|
Endpoints for administering your Synapse instance are placed under
|
|
`/_synapse/admin`. These require authentication through an access token of an
|
|
admin user. However as access to these endpoints grants the caller a lot of power,
|
|
we do not recommend exposing them to the public internet without good reason.
|