Domena, HTTPS i serwery proxy odwrotne

Umieść Antimatter na nazwie domeny z HTTPS, używając profilu Caddy z pliku compose lub własnego serwera proxy odwrotnego, oraz poprawnie ustaw adres URL witryny i adresy klientów.

Adres URL witryny

Adres URL witryny (ServiceSettings.SiteURL) to adres, którego użytkownicy używają, aby uzyskać dostęp do Antimatter, np. https://chat.example.com. Serwer używa go w linkach w e-mailach i powiadomieniach, w przekierowaniach logowania (OAuth, OpenID Connect, SAML), dla aplikacji mobilnych i desktopowych oraz do sprawdzania, skąd pochodzą żądania. Ustaw go dokładnie na adres z paska adresu przeglądarki: schemat, domena i port (jeśli nie jest domyślny), bez ukośnika na końcu.

  • W pliku compose witryny: SITE_URL w pliku .env.
  • W innym miejscu: AM_SERVICESETTINGS_SITEURL lub Konsola systemu › Środowisko › Serwer WWW › URL strony.

Jeśli adres URL witryny jest nieprawidłowy, logowanie za pomocą dostawcy tożsamości nie powiedzie się, linki w e-mailach będą wskazywać na błędne miejsce, a aplikacje mogą nie nawiązać połączenia. Po zmianie domeny zaktualizuj ją tutaj oraz w adresach URL przekierowań każdego dostawcy tożsamości.

HTTPS z dołączonym profilem Caddy

Plik compose.yaml witryny zawiera usługę Caddy w profilu https. Pobiera ona certyfikat z Let's Encrypt, odnawia go automatycznie, przekierowuje HTTP na HTTPS i przekazuje wszystko, w tym websockety, do Antimatter.

  1. Wskaż rekord DNS (A, a dla IPv6 AAAA) swojej domeny na serwer.
  2. Otwórz porty 80/tcp, 443/tcp i 443/udp (HTTP/3) w zaporze. Let's Encrypt musi mieć dostęp do portu 80 lub 443 z Internetu.
  3. Dodaj domenę do pliku .env i ustaw adres URL witryny:
    echo "DOMAIN=chat.example.com" >> .env
    sed -i 's|^SITE_URL=.*|SITE_URL=https://chat.example.com|' .env
  4. Uruchom z profilem:
    docker compose --profile https up -d

Dodaj --profile https do każdego kolejnego polecenia docker compose up lub umieść COMPOSE_PROFILES=https w pliku .env, aby zwykłe polecenie docker compose up -d uwzględniało ten profil. Caddy przechowuje swoje certyfikaty w wolumenie https.

Własny port Antimatter pozostaje udostępniony na hoście (HTTP_PORT, domyślnie 8065). Przy Caddy przed nim, utrzymuj go wyłącznie dla samego serwera:

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

Caddy komunikuje się z Antimatter przez wewnętrzną sieć edge, a nie przez ten port, więc nie ma to żadnego wpływu na Twoich użytkowników.

Z własnym serwerem proxy odwrotnym (nginx)

Jeśli serwer już uruchamia nginx lub inny proxy, wyłącz profil https i skieruj proxy do portu 8065 Antimatter. Proxy musi:

  • przekazywać uaktualnienia websocket (aplikacja webowa i aplikacje mobilne utrzymują otwarte połączenie websocket na /api/v4/websocket, a niektóre aplikacje otwierają własne);
  • akceptuj ciała żądań o rozmiarze co najmniej równym największemu plikowi do przesłania (Maksymalny rozmiar pliku, domyślnie 100 MB);
  • utrzymywać otwarte długotrwałe połączenia (websockets, duże przesyłania i pobierania);
  • przekazywać nagłówek Host oraz adres klienta.

Pełny blok serwera, dostosowany z szablonu produkcyjnego w antimatter-docker. Zamień domenę i ścieżki do certyfikatów:

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;
    }
}

Sprawdź plik poleceniem nginx -t i zastosuj zmiany poleceniem systemctl reload nginx. Serwer sam wysyła nagłówki X-Content-Type-Options, Referrer-Policy, Permissions-Policy i X-Frame-Options; tylko HSTS zależy od proxy. Podnieś wartość max-age, gdy HTTPS zacznie działać, i dodaj includeSubDomains tylko wtedy, gdy wszystkie subdomeny używają HTTPS.

Przy użyciu Docker Compose i nginx na hoście, upstream powyżej wskazuje na opublikowany port 8065. Opublikuj go tylko na 127.0.0.1 (HTTP_PORT=127.0.0.1:8065), aby nikt nie omijał proxy.

Repozytorium antimatter-docker zawiera pełną konfigurację z nginx w kontenerze i Let's Encrypt przez certbot, w deploy/compose.

Inne proxy

Dowolne proxy zadziała, jeśli spełni cztery powyższe warunki. Dzwonienie audio i wideo nigdy nie przechodzi przez proxy: używa własnego portu, patrz Rozmowy i głos.

Adresy klientów za proxy

Za proxy każde żądanie wydaje się przychodzić z proxy. Aby logować rzeczywisty adres klienta, stosować limity żądań per klient i używać filtrowania IP, powiedz serwerowi, który nagłówek zawiera adres i którym proxy może ufać. Żadna z tych ustawień nie ma pola w Konsoli systemu: ustaw je w config.json lub za pomocą zmiennych.

Klucz i zmiennaDomyślnieOpis
ServiceSettings.TrustedProxyIPHeader, AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADERpuste: serwer używa adresu połączeniaNagłówki zawierające adres klienta, na przykład X-Forwarded-For. Używany jest pierwszy z nich, który występuje w żądaniu.
ServiceSettings.TrustedProxyIPs, AM_SERVICESETTINGS_TRUSTEDPROXYIPSpustaAdresy lub zakresy CIDR twoich proxy, na przykład 172.29.71.0/28. Nagłówki są brane pod uwagę tylko dla żądań przychodzących z jednego z nich.

W zmiennej oddziel kilka wartości spacjami: AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADER="X-Forwarded-For X-Real-IP". Serwer odrzuca konfigurację, w której wpis w TrustedProxyIPs nie jest ani adresem IP, ani zakresem CIDR.

Jak serwer znajduje adres klienta

Każdy proxy dodaje adres, z którego otrzymał żądanie, po prawej stronie nagłówka X-Forwarded-For. To, co klient wysłał w samym nagłówku, pozostaje po lewej. Serwer czyta więc nagłówek od prawej strony, pomija adresy zaufanych proxy i bierze pierwszy inny adres jako adres klienta. Klient nie może wybrać własnego adresu, wysyłając własny nagłówek.

  • Za jednym proxy sam TrustedProxyIPHeader daje poprawny adres: serwer bierze najprawiejszy adres z nagłówka. Do czasu, aż ustawisz również TrustedProxyIPs, loguje ostrzeżenie przy starcie. Bez tego każdy, kto ma bezpośredni dostęp do portu 8065, może ustawić nagłówek, więc udostępniaj ten port tylko na 127.0.0.1 lub w sieci prywatnej.
  • Za kilkoma proxy, na przykład CDN lub balanserem obciążenia przed własnym proxy, wymień je wszystkie w TrustedProxyIPs. W przeciwnym razie serwer weźmie adres zewnętrznego proxy za adres klienta.
  • Proxy może zastąpić nagłówek adresem, który widzi, jak w powyższym przykładzie z nginx (X-Forwarded-For $remote_addr), albo dodać do niego wartość (nginx: $proxy_add_x_forwarded_for). Oba warianty działają.

Jakie adresy wymienić

Wymień adres, z którego przychodzą żądania proxy, tak jak go widzi Antimatter.

  • W pliku compose dla witryny z Caddy jest to już zrobione: Caddy łączy się z Antimatter przez sieć edge, a plik compose ustawia TrustedProxyIPHeader na X-Forwarded-For oraz TrustedProxyIPs na zakres tej sieci, EDGE_SUBNET (domyślnie 172.29.71.0/28, chyba że zmienisz to w .env). Zmień EDGE_SUBNET, jeśli nakłada się na którąś z Twoich sieci.
  • Konfiguracja produkcyjna w antimatter-docker robi to samo dla kontenera nginx, używając FRONTEND_SUBNET.
  • Przy nginx na hoście i Antimatter w Dockerze żądania docierają do Antimatter przez opublikowany port, zwykle z adresu bramki sieci projektu compose (możesz go sprawdzić za pomocą docker network inspect). Ustaw AM_SERVICESETTINGS_TRUSTEDPROXYIPS na ten adres w compose.override.yaml.
  • Bez Dockera, gdy nginx działa na tym samym hoście, jest to 127.0.0.1 (oraz ::1, jeśli nginx łączy się przez IPv6).

TLS bez proxy

Serwer może również samodzielnie obsługiwać HTTPS w Konsola systemu › Środowisko › Serwer WWW: ustaw Bezpieczeństwo połączenia na TLS (ServiceSettings.ConnectionSecurity), podając Plik Certyfikatu TLS i Plik z kluczem TLS (ServiceSettings.TLSCertFile, ServiceSettings.TLSKeyFile), albo zaznacz Użyj Let's Encrypt (ServiceSettings.UseLetsEncrypt). W takim przypadku serwer musi nasłuchiwać na porcie 443 (Adres nasłuchiwania, ServiceSettings.ListenAddress, domyślnie :8065), a ServiceSettings.Forward80To443 przekierowuje port 80. Proksy odwrotny jest łatwiejszy w obsłudze i odnawianiu certyfikatów, i to właśnie on jest zakładany w tym przewodniku.

Limit czasu serwera i rozmiar żądań

Ustawienia własnego serwera WWW, w Konsola systemu › Środowisko › Serwer WWW:

UstawienieKluczDomyślnie
Adres nasłuchiwaniaServiceSettings.ListenAddress:8065
Upłynięcie Limitu Czasu na OdczytServiceSettings.ReadTimeout300 sekund
Timeout ZapisuServiceSettings.WriteTimeout300 sekund
Limit czasu bezczynności (brak pola w Konsoli systemu)ServiceSettings.IdleTimeout60 sekund
Maksymalny rozmiar ładunku (bajty)ServiceSettings.MaximumPayloadSizeByteszob. Bezpieczeństwo

Ustaw limity czasu samego proxy na wartość co najmniej równą tym limitom dla zwykłych żądań, a maksymalny rozmiar treści (body) na co najmniej Maksymalny rozmiar pliku.