Домен, HTTPS и обратни прокси

Поставете Antimatter на доменно име с HTTPS, използвайки профила на Caddy от compose файла или собствен обратен прокси, и задайте правилно адреса на сайта и клиентските адреси.

Адресът на сайта

Адресът на сайта (ServiceSettings.SiteURL) е адресът, който хората използват, за да стигнат до Antimatter, например https://chat.example.com. Сервърът го използва в линковете в имейли и известия, в пренасочванията при вход (OAuth, OpenID Connect, SAML), за мобилните и десктоп приложенията, както и за проверка откъде идват заявките. Задайте го точно на адреса в адресната лента на браузъра: схема, домен и порт, ако не е по подразбиране, без коса черта в края.

  • С compose файла на сайта: SITE_URL в .env.
  • На друго място: AM_SERVICESETTINGS_SITEURL или Системна конзола › Обкръжение › Уеб сървър › URL адрес на сайта.

Ако адресът на сайта е грешен, входът с идентификационен доставчик ще се провали, линковете в имейлите ще водят на грешно място, а приложенията може да не се свържат. След смяна на домена, актуализирайте го тук и в адресите за пренасочване на всеки идентификационен доставчик.

HTTPS с включения профил на Caddy

Файлът compose.yaml на сайта включва услуга Caddy в профила https. Тя получава сертификат от Let's Encrypt, го подновява автоматично, пренасочва HTTP към HTTPS и препраща всичко, включително websocket-и, към Antimatter.

  1. Посочете DNS запис (A, и AAAA за IPv6) на вашия домен към сървъра.
  2. Отворете портове 80/tcp, 443/tcp и 443/udp (HTTP/3) във firewall-а. Let's Encrypt трябва да има достъп до порт 80 или 443 от интернет.
  3. Добавете домена в .env и задайте адреса на сайта:
    echo "DOMAIN=chat.example.com" >> .env
    sed -i 's|^SITE_URL=.*|SITE_URL=https://chat.example.com|' .env
  4. Стартирайте с профила:
    docker compose --profile https up -d

Добавете --profile https към всяко по-късно docker compose up, или поставете COMPOSE_PROFILES=https в .env, за да се включи и при обикновено docker compose up -d. Caddy пази сертификатите си в обема https.

Собственият порт на Antimatter остава публикуван на хоста (HTTP_PORT, по подразбиране 8065). С Caddy отпред, оставете го само за самия сървър:

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

Caddy достъпва Antimatter през вътрешната мрежа edge, а не през този порт, така че това не променя нищо за вашите потребители.

С собствен обратен прокси (nginx)

Ако сървърът вече изпълнява nginx или друг прокси, изключете профила https и насочете прокси-я към порт 8065 на Antimatter. Прокси-ят трябва да:

  • пропуска надграждането на websocket (уеб приложението и мобилните приложения поддържат отворен websocket на /api/v4/websocket, а някои приложения отварят собствени);
  • приема тела на заявки, поне толкова големи, колкото е най-големият файл за качване (Максимален размер на файла, по подразбиране 100 MB);
  • поддържа отворени дълготрайни връзки (websockets, големи качвания и изтегляния);
  • пропуска заглавието Host и адреса на клиента.

Пълен блок на сървъра, адаптиран от производствения шаблон в antimatter-docker. Заменете домейна и пътищата към сертификатите:

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

Проверете файла с nginx -t и го приложете с systemctl reload nginx. Сървърът сам изпраща X-Content-Type-Options, Referrer-Policy, Permissions-Policy и X-Frame-Options; само HSTS е отговорност на прокси-я. Повишете неговия max-age, след като HTTPS работи, и добавете includeSubDomains само ако всеки поддомейн използва HTTPS.

При Docker Compose и nginx на хоста, upstream по-горе сочи към публикувания порт 8065. Публикувайте го само на 127.0.0.1 (HTTP_PORT=127.0.0.1:8065), за да не може никой да заобиколи прокси-я.

Репозиторията antimatter-docker съдържа пълна конфигурация с nginx в контейнер и Let's Encrypt чрез certbot, в deploy/compose.

Други прокси-и

Всеки прокси ще работи, ако отговаря на четирите точки по-горе. Аудио и видео обикновено не минават през прокси-я: те използват собствен порт, вижте Обаждания и глас.

Адреси на клиенти зад прокси

Зад прокси всяка заявка изглежда, че идва от прокси-я. За да се записва реалният адрес на клиента, да се прилагат ограничения на скоростта на клиент и да се използва филтриране по IP, кажете на сървъра кое заглавие носи адреса и на кои прокси-и може да вярва. Нито едно от тези настройки няма поле в Системната конзола: задайте ги в config.json или с променливи.

Ключ и променливаПо подразбиранеКакво прави
ServiceSettings.TrustedProxyIPHeader, AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADERпразно: сървърът използва адреса на връзкатаЗаглавията, които носят адреса на клиента, например X-Forwarded-For. Използва се първото, присъстващо в заявката.
ServiceSettings.TrustedProxyIPs, AM_SERVICESETTINGS_TRUSTEDPROXYIPSпразноАдресите или CIDR обхватите на вашите прокси-и, например 172.29.71.0/28. Заглавията се вземат предвид само за заявки, идващи от един от тях.

В променлива отделете няколко стойности с интервали: AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADER="X-Forwarded-For X-Real-IP". Сервърът отхвърля конфигурация, в която TrustedProxyIPs съдържа елемент, който не е нито IP адрес, нито CIDR обхват.

Как сервърът намира адреса на клиента

Всяка прокси добавя адреса, от който е получил заявката, в дясната част на X-Forwarded-For. Каквото клиентът е изпратил в самата заглавна част остава вляво. Така сервърът чете заглавната част от дясно, пропуска адресите на доверените прокси и взима първия друг адрес като този на клиента. Клиентът не може да избере свой адрес, като изпрати собствена заглавна част.

  • Зад една прокси, TrustedProxyIPHeader сам по себе си дава правилния адрес: сервърът взима най-десния адрес от заглавната част. При стартиране той записва предупреждение, докато не зададете и TrustedProxyIPs. Без него всеки, който достигне порт 8065 директно, може да зададе заглавната част, така че публикувайте този порт само на 127.0.0.1 или в частна мрежа.
  • Зад няколко прокси, например CDN или балансир на натоварването пред собствената ви прокси, изредете всички в TrustedProxyIPs. В противен случай сервърът ще приеме адреса на външната прокси за този на клиента.
  • Прокси може да замени заглавната част с адреса, който вижда, както в примера с nginx по-горе (X-Forwarded-For $remote_addr), или да добави към нея (nginx $proxy_add_x_forwarded_for). И двата варианта работят.

Кои адреси да изредете

Изредете адреса, от който заявките на прокси идват, както Antimatter го вижда.

  • С compose файла на сайта и Caddy това вече е направено: Caddy достига Antimatter през мрежата edge, а compose файла задава TrustedProxyIPHeader на X-Forwarded-For и TrustedProxyIPs на обхвата на тази мрежа, EDGE_SUBNET (172.29.71.0/28, освен ако не го промените в .env). Променете EDGE_SUBNET, ако се припокрива с някоя от вашите мрежи.
  • Продукционната конфигурация в antimatter-docker прави същото за контейнера с nginx, използвайки FRONTEND_SUBNET.
  • С nginx на хоста и Antimatter в Docker, заявките достигат Antimatter през публикувания порт, обикновено от адрес на гейтуея на мрежата на compose проекта (docker network inspect го показва). Задайте AM_SERVICESETTINGS_TRUSTEDPROXYIPS на този адрес в compose.override.yaml.
  • Без Docker, с nginx на същия хост, стойността е 127.0.0.1 (и ::1, ако nginx се свързва през IPv6).

TLS без прокси

Сървърът може сам да обслужва HTTPS в Системна конзола › Обкръжение › Уеб сървър: Защита на връзката е зададена на TLS (ServiceSettings.ConnectionSecurity), с Файл за TLS сертификат и Файл с ключове на TLS (ServiceSettings.TLSCertFile, ServiceSettings.TLSKeyFile) или Използвай Let's Encrypt (ServiceSettings.UseLetsEncrypt). Тогава сървърът трябва да слуша на порт 443 (Адрес на слушане, ServiceSettings.ListenAddress, по подразбиране :8065), а ServiceSettings.Forward80To443 пренасочва порт 80. Обърнатият прокси е по-лесен за поддръжка и обновяване и е предпоставката на това ръководство.

Изчаквания и размер на заявките на сървъра

Настройки на собствения уеб сървър, в Системна конзола › Обкръжение › Уеб сървър:

НастройкаКлючПо подразбиране
Адрес на слушанеServiceSettings.ListenAddress:8065
Време на изчакване при четенеServiceSettings.ReadTimeout300 секунди
Време на изчакване при записServiceSettings.WriteTimeout300 секунди
Изчакване при бездействие (няма поле в Системната конзола)ServiceSettings.IdleTimeout60 секунди
Максимален размер на полезния товар (байтове)ServiceSettings.MaximumPayloadSizeBytesвижте Сигурност

Задръжте собствените времена на изчакване на прокси-то поне толкова дълго, колкото тези, за обикновени заявки, а размера на тялото поне Максимален размер на файла.