forked from Fediversity/Fediversity
284 lines
8 KiB
Markdown
284 lines
8 KiB
Markdown
---
|
|
gitea: none
|
|
include_toc: true
|
|
---
|
|
|
|
# Reverse proxy with nginx
|
|
|
|
Clients connecting from the Internet to our Matrix environment will usually
|
|
use SSL/TLS to encrypt whatever they want to send. This is one thing that
|
|
nginx does better than Synapse.
|
|
|
|
Furthermore, granting or denying access to specific endpoints is much easier
|
|
in nginx.
|
|
|
|
Synapse listens only on localhost, so nginx has to pass connections on from
|
|
the wild west that is the Internet to our server listening on the inside.
|
|
|
|
|
|
# Installing
|
|
|
|
Installing nginx and the [Let's Encrypt](https://letsencrypt.org/) plugin is
|
|
easy:
|
|
|
|
```
|
|
apt install nginx python3-certbot-nginx
|
|
```
|
|
|
|
Get your certificate:
|
|
|
|
```
|
|
certbot certonly --nginx --agree-tos -m systeemmail@procolix.com --non-interactive -d matrixdev.procolix.com
|
|
```
|
|
|
|
Substitute the correct e-mailaddress and FQDN, or course.
|
|
|
|
|
|
# Configuration
|
|
|
|
Almost all traffic should be encrypted, so a redirect from http to https seems
|
|
like a good idea.
|
|
|
|
However, `.well-known/matrix/client` has to be available via http and https,
|
|
so that should *NOT* be redirected to https. Some clients don't understand the
|
|
redirect and will therefore not find the server if you redirect everything.
|
|
|
|
Under the `server_name` (the "domain name", the part after the username) you
|
|
will need a configuration like this:
|
|
|
|
```
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/matrixdev.procolix.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/matrixdev.procolix.com/privkey.pem;
|
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
ssl_dhparam /etc/ssl/dhparams.pem;
|
|
|
|
server_name matrixdev.procolix.com;
|
|
|
|
location /.well-known/matrix/client {
|
|
return 200 '{
|
|
"m.homeserver": {"base_url": "https://vm02199.procolix.com"},
|
|
"org.matrix.msc3575.proxy": {"url": "https://vm02199.procolix.com"}
|
|
}';
|
|
default_type application/json;
|
|
|
|
add_header 'Access-Control-Allow-Origin' '*';
|
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
|
|
add_header 'Access-Control-Allow-Headers' 'X-Requested-With, Content-Type, Authorization';
|
|
}
|
|
|
|
location /.well-known/matrix/server {
|
|
return 200 '{"m.server": "vm02199.procolix.com"}';
|
|
default_type application/json;
|
|
}
|
|
|
|
location / {
|
|
if ($scheme = http) {
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
}
|
|
|
|
access_log /var/log/nginx/matrixdev-access.log;
|
|
error_log /var/log/nginx/matrixdev-error.log;
|
|
|
|
}
|
|
```
|
|
|
|
This defines a server that listens on both http and https. It hands out two
|
|
.well-known entries over both http and https, and every other request over
|
|
http is forwarded to https.
|
|
|
|
Be sure to substitute the correct values for `server_name`, `base_url` and the
|
|
certificate files.
|
|
|
|
The three `add_header` lines are absolutely necessary, but probably need some
|
|
tweaking. This is a TODO for this page.
|
|
|
|
For the actual proxy in front of Synapse, this is what you need:
|
|
|
|
```
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
|
|
# For the federation port
|
|
listen 8448 ssl default_server;
|
|
listen [::]:8448 ssl default_server;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/vm02199.procolix.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/vm02199.procolix.com/privkey.pem;
|
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
ssl_dhparam /etc/ssl/dhparams.pem;
|
|
|
|
server_name vm02199.procolix.com;
|
|
|
|
location ~ ^(/_matrix|/_synapse/client) {
|
|
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;
|
|
client_max_body_size 50M;
|
|
proxy_http_version 1.1;
|
|
}
|
|
|
|
}
|
|
```
|
|
|
|
Again, substitute the correct values. Don't forget to open the relevant ports
|
|
in the firewall. Ports 80 and 443 may already be open, 8448 is probably not.
|
|
|
|
|
|
# Synapse-admin {#synapse-admin}
|
|
|
|
If you also [install Synapse-Admin](../synapse-admin), you'll want to create
|
|
another vhost, something like this:
|
|
|
|
```
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/admin.example.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/admin.example.com/privkey.pem;
|
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
ssl_dhparam /etc/ssl/dhparams.pem;
|
|
|
|
server_name admin.example.com;
|
|
|
|
root /var/www/synapse-admin;
|
|
|
|
access_log /var/log/nginx/admin-access.log;
|
|
error_log /var/log/nginx/admin-error.log;
|
|
}
|
|
```
|
|
|
|
You'll need an SSL certificate for this, of course. But you'll also need to
|
|
give it access to the `/_synapse/admin` endpoint in Synapse.
|
|
|
|
You don't want this endpoint to be available for just anybody on the Internet,
|
|
so restrict access to the IP-addresses from which you expect to use
|
|
Synapse-Admin.
|
|
|
|
In `/etc/nginx/sites-available/synapse` you want to add this bit:
|
|
|
|
```
|
|
location ~ ^/_synapse/admin {
|
|
allow 127.0.0.1;
|
|
allow ::1;
|
|
allow 111.222.111.222;
|
|
allow dead:beef::/64;
|
|
deny all;
|
|
|
|
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;
|
|
client_max_body_size 50M;
|
|
proxy_http_version 1.1;
|
|
}
|
|
```
|
|
|
|
This means access to `/_synapse/admin` is only allowed for the addresses
|
|
mentioned, but will be forwarded to Synapse in exactly the same way as
|
|
"normal" requests.
|
|
|
|
|
|
# LiveKit {#livekit}
|
|
|
|
If you run an SFU for Element Call, you need a virtual host for LiveKit. Make
|
|
sure you install, configure and run [Element Call LiveKit](../element-call#livekit).
|
|
Then create a virtual host much like this:
|
|
|
|
```
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/livekit.example.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/livekit.example.com/privkey.pem;
|
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
ssl_dhparam /etc/ssl/dhparams.pem;
|
|
|
|
server_name livekit.example.com;
|
|
|
|
# This is lk-jwt-service
|
|
location ~ ^(/sfu/get|/healthz) {
|
|
proxy_pass http://[::1]:8080;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
location / {
|
|
proxy_pass http://[::1]:7880;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
#add_header Access-Control-Allow-Origin "*" always;
|
|
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
access_log /var/log/nginx/livekit-access.log;
|
|
error_log /var/log/nginx/livekit-error.log;
|
|
}
|
|
```
|
|
|
|
|
|
# Element Call widget {#callwidget}
|
|
|
|
If you self-host the [Element Call widget](../element-call#widget), this
|
|
should be the configuration to publish that:
|
|
|
|
```
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/call.example.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/call.example.com/privkey.pem;
|
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
ssl_dhparam /etc/ssl/dhparams.pem;
|
|
|
|
server_name call.example.com;
|
|
|
|
root /var/www/element-call;
|
|
|
|
location /assets {
|
|
add_header Cache-Control "public, immutable, max-age=31536000";
|
|
}
|
|
|
|
location /apple-app-site-association {
|
|
default_type application/json;
|
|
}
|
|
|
|
location /^config.json$ {
|
|
alias public/config.json;
|
|
default_type application/json;
|
|
}
|
|
|
|
location / {
|
|
try_files $uri /$uri /index.html;
|
|
add_header Cache-Control "public, max-age=30, stale-while-revalidate=30";
|
|
}
|
|
|
|
access_log /var/log/nginx/call-access.log;
|
|
error_log /var/log/nginx/call-error.log;
|
|
}
|
|
```
|
|
|
|
|
|
# Firewall
|
|
|
|
For normal use, at least ports 80 and 443 must be openend, see [Firewall](../firewall).
|