Домен, HTTPS і зворотні проксі

Розмістіть Antimatter на доменному імені з HTTPS, використовуючи профіль Caddy з файлу compose або власний зворотний проксі, і правильно встановіть URL сайту та адреси клієнтів.

URL сайту

URL сайту (ServiceSettings.SiteURL) — це адреса, за якою користувачі доступляться до Antimatter, наприклад https://chat.example.com. Сервер використовує її в посиланнях у електронних листах і сповіщеннях, при перенаправленні під час входу (OAuth, OpenID Connect, SAML), для мобільних та десктопних застосунків, а також для перевірки джерела запитів. Встановіть її точно як адресу в адресному рядку браузера: протокол, домен і порт (якщо не стандартний), без символу «/» наприкінці.

  • У файлі compose сайту: SITE_URL у .env.
  • Інше місце: AM_SERVICESETTINGS_SITEURL або Системна консоль › Середовище › Веб-сервер › URL-адреса сайту.

Якщо URL сайту неправильний, вхід через провайдера ідентичності не спрацює, посилання в електронних листах вказуватимуть на неправильне місце, а застосунки можуть не підключитися. Після зміни домену оновіть його тут та в URL перенаправлення кожного провайдера ідентичності.

HTTPS із вбудованим профілем Caddy

Файл compose.yaml сайту містить службу Caddy у профілі https. Вона отримує сертифікат від Let's Encrypt, оновлює його автоматично, перенаправляє HTTP на HTTPS і передає весь трафік, включно з вебсокетами, до Antimatter.

  1. Накажіть DNS-запис (A, а також AAAA для IPv6) вашого домену на сервер.
  2. Відкрийте порти 80/tcp, 443/tcp та 443/udp (HTTP/3) у брандмауері. Let's Encrypt має мати доступ до порту 80 або 443 з Інтернету.
  3. Додайте домен у .env та встановіть URL сайту:
    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 МБ);
  • тримати довгоживучі з’єднання відкритими (websocket, великі завантаження та завантаження);
  • передавати заголовок 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. Простіше працювати з reverse proxy та оновлювати його, і саме це припускає цей гід.

Час очікування сервера та розмір запитів

Налаштування власного веб-сервера сервера, у Системна консоль › Середовище › Веб-сервер:

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

Тримайте власні таймаути проксі не коротшими за ці для звичайних запитів, а розмір тіла — не меншим за Максимальний розмір файлу.