Dodici build

Un homeserver Matrix la cui federazione funziona davvero

Synapse su una piccola istanza Ryzen con Postgres, delega fatta tramite file well-known piuttosto che record SRV, e verifica che raggiunge altri server.

Cosa si costruisce

Un homeserver su example.com, in esecuzione su matrix.example.com, federato correttamente con tutti gli altri. Postgres sotto, nginx davanti, delega gestita da due piccoli file JSON e registrazione chiusa affinché il vostro server non diventi un relay gratuito per qualcun altro entro una settimana.

La federazione è il punto in cui queste installazioni di solito falliscono, e quasi mai per colpa di Synapse. Il server funziona, i messaggi locali funzionano, e poi non arriva nulla dall'esterno. In pratica, la causa è quasi sempre la delega: l'identità del server e l'indirizzo in cui vive sono due cose diverse, e il meccanismo che le collega è facile da sbagliare in modo sottile.

Prima di iniziare

  • Un R-4 basta per qualche decina di utenti. Synapse consuma più memoria che CPU, e unirsi a grandi stanze federate è l'unica cosa che lo fa sudare.
  • Due nomi nel DNS: example.com, che è l'identità del vostro server e appare in ogni id utente, e matrix.example.com, dove il software ascolta effettivamente.
  • Certificati per entrambi. Il primo deve solo servire due file statici.

1. Database, con la giusta collation

apt update && apt install -y postgresql matrix-synapse nginx certbot
sudo -u postgres psql -c "CREATE USER synapse_user WITH PASSWORD '<a long password>';"
sudo -u postgres psql -c "CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE=template0 OWNER synapse_user;"

La collation non è un dettaglio. Synapse si rifiuta di avviarsi su un database creato con una collation diversa da C, e l'errore che stampa quando sbagliate arriva dopo che avete già importato i dati. Fatelo ora, correttamente, una volta sola.

2. Configurazione dell'homeserver

Il pacchetto Debian chiede il nome del server durante l'installazione; rispondete example.com, non l'hostname della macchina. Quella risposta diventa parte di ogni id utente e di ogni id stanza sul server e non può essere cambiata in seguito senza abbandonare il server.

Poi modificate /etc/matrix-synapse/homeserver.yaml:

server_name: "example.com"
public_baseurl: "https://matrix.example.com/"
pid_file: /run/matrix-synapse.pid

listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    bind_addresses: ['127.0.0.1']
    resources:
      - names: [client, federation]
        compress: false

database:
  name: psycopg2
  args:
    user: synapse_user
    password: "<a long password>"
    database: synapse
    host: 127.0.0.1
    cp_min: 5
    cp_max: 10

enable_registration: false
registration_shared_secret: "<a long random string>"
report_stats: false
suppress_key_server_warning: true
url_preview_enabled: false

media_store_path: /var/lib/matrix-synapse/media
max_upload_size: 100M
media_retention:
  remote_media_lifetime: 30d

rc_message:
  per_second: 0.5
  burst_count: 15

Due di queste impostazioni vi faranno risparmiare spazio su disco e grattacapi. La conservazione dei media remoti scarta le copie cache dei file degli altri server dopo un mese, e senza di essa il vostro archivio media cresce per sempre con contenuti che non avete mai richiesto. Le anteprime URL sono disattivate perché fanno sì che il vostro server recuperi indirizzi arbitrari per conto di chiunque possa pubblicare un link, il che è un motore di richiesta di falsificazione con un'interfaccia chat attaccata.

x_forwarded: true conta anche: senza di essa, Synapse limita la velocità di ogni utente nel mondo come se fossero un unico client, perché ogni richiesta sembra provenire da nginx.

3. Delega

La vostra identità è example.com e il vostro server è su matrix.example.com. Due file colmano il divario. Serviteli da example.com, su HTTPS, con il tipo di contenuto giusto.

/.well-known/matrix/server:

{ "m.server": "matrix.example.com:443" }

/.well-known/matrix/client:

{ "m.homeserver": { "base_url": "https://matrix.example.com" } }

La porta nel primo file è obbligatoria. Se la omettete, gli altri server ripiegano sulla porta 8448, non trovano nulla in ascolto e rinunciano silenziosamente; i vostri utenti poi riferiscono che la federazione è rotta mentre ogni log sulla vostra macchina sembra perfettamente sano.

server {
  listen 443 ssl;
  server_name example.com;
  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  location /.well-known/matrix/ {
    root /var/www/wellknown;
    default_type application/json;
    add_header Access-Control-Allow-Origin *;
  }
}

server {
  listen 443 ssl;
  listen [::]:443 ssl;
  server_name matrix.example.com;
  ssl_certificate     /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
  client_max_body_size 100m;

  location ~ ^(/_matrix|/_synapse/client) {
    proxy_pass http://127.0.0.1:8008;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host;
  }
}

L'header Access-Control-Allow-Origin sulla posizione well-known è richiesto dai client web e dimenticato da praticamente tutti. Senza di esso, i client desktop funzionano e i client browser non riescono a trovare il vostro server.

mkdir -p /var/www/wellknown/.well-known/matrix
systemctl restart matrix-synapse nginx

4. Un utente

register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://127.0.0.1:8008

Rispondete alle domande, fate del primo account un admin e lasciate la registrazione aperta disattivata. Un homeserver con registrazione aperta diventa una fonte di spam in pochi giorni, e gli altri server cominceranno a rifiutare il vostro traffico molto prima che ve ne accorgiate.

Verifica

Procedete dall'interno verso l'esterno. Primo, il software risponde:

curl -s https://matrix.example.com/_matrix/client/versions | head -c 200
curl -s https://matrix.example.com/_matrix/federation/v1/version

Poi, la delega viene servita correttamente, con la porta presente e il tipo di contenuto giusto:

curl -si https://example.com/.well-known/matrix/server | grep -E "content-type|m.server"
curl -s https://example.com/.well-known/matrix/client

Poi, la vostra chiave di firma si risolve. Gli altri server la recuperano prima di parlare con voi:

curl -s https://matrix.example.com/_matrix/key/v2/server | head -c 300

Infine, l'unico test che conta. Accedete con un client, unitevi a una stanza pubblica ospitata su un homeserver che non è il vostro e inviate un messaggio. Poi leggete lo stato della federazione dall'API amministrativa, usando il token di accesso che il vostro client mostra nelle sue impostazioni:

curl -s -H "Authorization: Bearer <admin token>" \
  "https://matrix.example.com/_synapse/admin/v1/federation/destinations" | head -c 400

Ogni destinazione dovrebbe mostrare una transazione riuscita recente e nessun intervallo di nuovo tentativo. Le destinazioni con retry_interval crescente sono server che non riuscite a raggiungere; se ogni destinazione sembra così, il problema è la delega piuttosto che la rete, e il passo tre è dove guardare.

journalctl -u matrix-synapse --since "10 min ago" | grep -i "federation" | tail -20

Dopo

Unirsi a una stanza molto grande la prima volta bloccherà un core per diversi minuti e scaricherà una grande quantità di stato. Questo è normale, succede una volta per stanza, ed è il motivo principale per cui la gente conclude che Synapse è lento. Voce e video richiedono un server TURN accanto a questo; coturn sulla stessa istanza gestisce una piccola comunità, anche se vuole la sua gamma di porte UDP nel firewall. La federazione è loquace in entrambe le direzioni, il che vale la pena ricordare quando si sceglie il sito: il nostro indice delle posizioni elenca i tempi di andata e ritorno che misuriamo noi stessi.

Pronto quando lo sei

Scegli una città. Scegli una dimensione. Paga in criptovaluta.

Nessun modulo su chi sei, nessuna attesa per l'approvazione di una persona, nessuna chiamata per verificare nulla. La fattura viene saldata e le credenziali arrivano nella tua casella di posta.