Домен, 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 перенаправления каждого провайдера идентификации.
HTTPS с помощью встроенного профиля Caddy
В compose.yaml сайта есть служба Caddy в профиле https. Она получает сертификат от Let's Encrypt, обновляет его автоматически, перенаправляет HTTP на HTTPS и передаёт все запросы, включая websocket, в Antimatter.
- Настройте DNS-записи (A, и AAAA для IPv6) вашего домена на сервер.
- Откройте в файрволе порты 80/tcp, 443/tcp и 443/udp (HTTP/3). Let's Encrypt должен иметь доступ к порту 80 или 443 из интернета.
- Добавьте домен в
.envи задайте URL сайта:echo "DOMAIN=chat.example.com" >> .env sed -i 's|^SITE_URL=.*|SITE_URL=https://chat.example.com|' .env - Запустите с профилем:
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. Обратный прокси проще настраивать и обновлять, и именно его предполагает данное руководство.
Тайм-ауты сервера и размер запроса
Параметры собственного веб-сервера, в разделе Системная консоль › Окружение › Веб-сервер:
| Параметр | Ключ | Значение по умолчанию |
|---|---|---|
| Прослушиваемый адрес | ServiceSettings.ListenAddress | :8065 |
| Тайм-аут чтения | ServiceSettings.ReadTimeout | 300 секунд |
| Тайм-аут записи | ServiceSettings.WriteTimeout | 300 секунд |
| Тайм-аут простоя (нет поля в Системной консоли) | ServiceSettings.IdleTimeout | 60 секунд |
| Максимальный размер полезной нагрузки (байты) | ServiceSettings.MaximumPayloadSizeBytes | см. Безопасность |
Убедитесь, что тайм-ауты самого прокси не короче указанных значений для обычных запросов, а максимальный размер тела запроса не меньше Максимального размера файла.