Domen, HTTPS și proxii inversi

Pune Antimatter pe un nume de domeniu cu HTTPS, folosind profilul Caddy din fișierul de compunere sau un proxy invers propriu, și configurează corect URL-ul site-ului și adresele clientului.

URL-ul site-ului

URL-ul site-ului (ServiceSettings.SiteURL) este adresa pe care o folosesc utilizatorii pentru a accesa Antimatter, de exemplu https://chat.example.com. Serverul îl utilizează în linkurile din e-mailuri și notificări, în redirecționările de autentificare (OAuth, OpenID Connect, SAML), pentru aplicațiile mobile și de desktop, și pentru a verifica de unde provin cererile. Configurează-l exact cu adresa din bara de adrese a browserului: schemă, domeniu și port (dacă nu este cel implicit), fără bară oblică la final.

  • Cu fișierul de compunere al site-ului: SITE_URL în .env.
  • În orice alt loc: AM_SERVICESETTINGS_SITEURL, sau Consola de sistem › Mediu de execuție › Server web › URL site.

Dacă URL-ul site-ului este incorect, autentificarea cu un furnizor de identitate va eșua, linkurile din e-mailuri vor indica un loc greșit, iar aplicațiile s-ar putea să nu se conecteze. După ce ai schimbat domeniul, actualizează-l aici și în URL-urile de redirecționare ale fiecărui furnizor de identitate.

HTTPS cu profilul Caddy inclus

Fișierul compose.yaml al site-ului include un serviciu Caddy în profilul https. Acesta obține un certificat de la Let's Encrypt, îl reînnoiește automat, redirecționează HTTP către HTTPS și transmite totul, inclusiv websocket-urile, către Antimatter.

  1. Indică un înregistrare DNS (A, și AAAA pentru IPv6) a domeniului către server.
  2. Deschide porturile 80/tcp, 443/tcp și 443/udp (HTTP/3) în firewall. Let's Encrypt trebuie să poată accesa portul 80 sau 443 de pe Internet.
  3. Adaugă domeniul în .env și configurează URL-ul site-ului:
    echo "DOMAIN=chat.example.com" >> .env
    sed -i 's|^SITE_URL=.*|SITE_URL=https://chat.example.com|' .env
  4. Pornește cu profilul:
    docker compose --profile https up -d

Adaugă --profile https la fiecare apel ulterior docker compose up, sau pune COMPOSE_PROFILES=https în .env pentru ca un simplu docker compose up -d să includă profilul. Caddy își păstrează certificatele în volumul https.

Portul propriu al Antimatter rămâne publicat pe gazdă (HTTP_PORT, implicit 8065). Cu Caddy în față, păstrează-l doar pentru serverul însuși:

echo "HTTP_PORT=127.0.0.1:8065" >> .env
docker compose --profile https up -d

Caddy accesează Antimatter prin rețeaua internă edge, nu prin acel port, deci acest lucru nu schimbă nimic pentru utilizatorii tăi.

Cu un proxy invers propriu (nginx)

Dacă serverul rulează deja nginx sau un alt proxy, dezactivați profilul https și configurați proxy-ul să indice portul 8065 al Antimatter. Proxy-ul trebuie:

  • să permită upgrade-urile websocket (aplicația web și aplicațiile mobile mențin deschis un websocket pe /api/v4/websocket, iar unele aplicații își deschid unul propriu);
  • acceptați corpuri de cerere cel puțin la fel de mari ca cel mai mare fișier încărcat (Dimensiunea maximă a fișierului, implicit 100 MB);
  • să mențină deschise conexiunile de lungă durată (websockets, încărcări și descărcări mari);
  • să transmită antetul Host și adresa clientului.

Un bloc de server complet, adaptat din șablonul de producție din antimatter-docker. Înlocuiți domeniul și căile către certificate:

upstream antimatter {
    server 127.0.0.1:8065;
    keepalive 64;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      '';
}

proxy_cache_path /var/cache/nginx/antimatter levels=1:2 keys_zone=antimatter_cache:10m
                 max_size=3g inactive=120m use_temp_path=off;

server {
    listen 80;
    listen [::]:80;
    server_name chat.example.com;
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name chat.example.com;

    ssl_certificate     /etc/ssl/chat.example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/chat.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_timeout 1d;
    ssl_session_cache shared:AntimatterSSL:10m;
    ssl_session_tickets off;

    add_header Strict-Transport-Security "max-age=31536000" always;

    # At least FileSettings.MaxFileSize (100 MB by default).
    client_max_body_size 100M;

    proxy_http_version 1.1;
    proxy_set_header Host              $host;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Upgrade           $http_upgrade;
    proxy_set_header Connection        $connection_upgrade;
    proxy_buffers 256 16k;
    proxy_buffer_size 16k;

    location ~ ^/api/v[0-9]+/(users/)?websocket$ {
        client_body_timeout 60s;
        send_timeout 300s;
        lingering_timeout 5s;
        proxy_connect_timeout 90s;
        proxy_send_timeout 300s;
        proxy_read_timeout 90s;
        proxy_pass http://antimatter;
    }

    location / {
        proxy_read_timeout 600s;
        proxy_cache antimatter_cache;
        proxy_cache_revalidate on;
        proxy_cache_min_uses 2;
        proxy_cache_use_stale timeout;
        proxy_cache_lock on;
        proxy_pass http://antimatter;
    }
}

Verificați fișierul cu nginx -t și aplicați-l cu systemctl reload nginx. Serverul trimite singur antetele X-Content-Type-Options, Referrer-Policy, Permissions-Policy și X-Frame-Options; doar HSTS este responsabilitatea proxy-ului. Creșteți valoarea max-age după ce HTTPS funcționează și adăugați includeSubDomains doar dacă toate subdomeniile folosesc HTTPS.

Cu Docker Compose și nginx pe gazdă, upstream-ul de mai sus indică portul publicat 8065. Publicați-l doar pe 127.0.0.1 (HTTP_PORT=127.0.0.1:8065), astfel încât nimeni să nu ocolească proxy-ul.

Depozitoriul antimatter-docker conține o configurație completă cu nginx într-un container și Let's Encrypt prin certbot, în deploy/compose.

Alte proxy-uri

Orice proxy funcționează dacă îndeplinește cele patru puncte de mai sus. Apelurile audio și video nu trec niciodată prin proxy: folosesc propriul port, consultați Apeluri și voce.

Adresele clientului din spatele unui proxy

Din spatele unui proxy, fiecare cerere pare să vină de la proxy. Pentru a înregistra adresa reală a clientului, pentru a aplica limite de rată per client și pentru a folosi filtrarea IP, indicați serverului care antet conține adresa și de la ce proxy-uri poate încrede. Niciuna dintre aceste setări nu are un câmp în Consola de sistem: configurați-le în config.json sau cu variabile.

Cheie și variabilăImplicitCe face
ServiceSettings.TrustedProxyIPHeader, AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADERgol: serverul folosește adresa conexiuniiAntetele care conțin adresa clientului, de exemplu X-Forwarded-For. Se folosește primul prezent într-o cerere.
ServiceSettings.TrustedProxyIPs, AM_SERVICESETTINGS_TRUSTEDPROXYIPSgolAdresele sau intervalele CIDR ale proxy-urilor dumneavoastră, de exemplu 172.29.71.0/28. Antetele sunt luate în considerare doar pentru cererile care vin de la unul dintre ele.

Într-o variabilă, separați mai multe valori cu spații: AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADER="X-Forwarded-For X-Real-IP". Serverul refuză o configurație care conține în TrustedProxyIPs o intrare care nu este nici o adresă IP, nici un interval CIDR.

Cum identifică serverul adresa clientului

Fiecare proxy adaugă adresa de la care a primit cererea la dreapta în X-Forwarded-For. Ce a trimis clientul în antet rămâne la stânga. Astfel, serverul citește antetul de la dreapta, sare peste adresele proxy-urilor de încredere și ia prima adresă diferită ca adresă a clientului. Un client nu își poate alege adresa trimițând propriul antet.

  • În spatele unui singur proxy, TrustedProxyIPHeader este suficient pentru a obține adresa corectă: serverul ia adresa cea mai din dreapta a antetului. Înregistrează un avertisment la pornire până când configurați și TrustedProxyIPs. Fără acesta, oricine care accesează direct portul 8065 poate seta antetul, deci publicați acel port doar pe 127.0.0.1 sau pe un rețea privată.
  • În spatele mai multor proxy-uri, de exemplu un CDN sau un echilibrator de încărcare în fața propriului proxy, enumerați-le pe toate în TrustedProxyIPs. În caz contrar, serverul va lua adresa proxy-ului extern ca adresă a clientului.
  • Proxy-ul poate înlocui antetul cu adresa pe care o vede, așa cum face exemplul nginx de mai sus (X-Forwarded-For $remote_addr), sau poate adăuga la acesta (nginx's $proxy_add_x_forwarded_for). Ambele funcționează.

Ce adrese trebuie enumerate

Enumerați adresa de la care vin cererile proxy-ului, așa cum o vede Antimatter.

  • Cu fișierul compose al site-ului și Caddy, acest lucru este deja făcut: Caddy accesează Antimatter prin rețeaua edge, iar fișierul compose setează TrustedProxyIPHeader la X-Forwarded-For și TrustedProxyIPs la intervalul acelei rețele, EDGE_SUBNET (172.29.71.0/28, dacă nu îl modificați în .env). Modificați EDGE_SUBNET dacă se suprapune cu una dintre rețelele dumneavoastră.
  • Configurația de producție din antimatter-docker face același lucru pentru containerul nginx, folosind FRONTEND_SUBNET.
  • Cu nginx pe gazdă și Antimatter în Docker, cererile ajung la Antimatter prin portul publicat, de obicei de la adresa gateway a rețelei proiectului compose (poate fi văzută cu docker network inspect). Setează AM_SERVICESETTINGS_TRUSTEDPROXYIPS la acea adresă în compose.override.yaml.
  • Fără Docker, cu nginx pe același gazdă, este 127.0.0.1 (și ::1 dacă nginx se conectează prin IPv6).

TLS fără proxy

Serverul poate servi și HTTPS direct, din Consola de sistem › Mediu › Server Web: Siguranța conexiunii setată pe TLS (ServiceSettings.ConnectionSecurity), cu Fișier certificat TLS și Fișier cheie TLS (ServiceSettings.TLSCertFile, ServiceSettings.TLSKeyFile), sau Utilizare Let's Encrypt (ServiceSettings.UseLetsEncrypt). În acest caz, serverul trebuie să asculte pe portul 443 (Ascultați adresa, ServiceSettings.ListenAddress, implicit :8065), iar ServiceSettings.Forward80To443 redirecționează portul 80. Un proxy invers este mai ușor de administrat și de reînnoit, și este ceea ce presupune acest ghid.

Timere de expirare și dimensiunea cererilor

Setările propriului server web, în Consola de sistem › Mediu de execuție › Server web:

SetareCheieImplicit
Ascultați adresaServiceSettings.ListenAddress:8065
Timpul de citireServiceSettings.ReadTimeout300 de secunde
Scurtă perioadă de scriereServiceSettings.WriteTimeout300 de secunde
Timer de expirare la inactivitate (fără câmp în Consola de sistem)ServiceSettings.IdleTimeout60 de secunde
Dimensiunea maximă a încărcăturii (octeți)ServiceSettings.MaximumPayloadSizeBytesa se vedea Securitate

Păstrați timpii de așteptare proprii ai proxy-ului cel puțin la fel de lungi ca acești timpi pentru cererile normale, iar dimensiunea corpului cel puțin Dimensiunea maximă a fișierului.