Nginx
Reverse proxy с терминацией HTTPS. Единственный компонент, слушающий публичные
интерфейсы: все остальные сервисы доступны только на 127.0.0.1.
Установлен на хосте, не в контейнере — отсюда proxy_pass на loopback-порты,
куда docker публикует контейнеры.
Версия: nginx/1.22.1 (пакет Debian).
Файлы
| Путь | Назначение |
|---|---|
/etc/nginx/sites-enabled/default | единственный конфиг, три виртуальных хоста |
/etc/nginx/conf.d/upload_size.conf | client_max_body_size 100M |
/var/log/nginx/error.log | ошибки, в т.ч. отказы allow-листа |
/var/log/nginx/access.log | запросы |
client_max_body_size вынесен в drop-in, чтобы действовать глобально. Без него
загрузка медиа в вики крупнее 1 МБ отбивается с 413.
Виртуальные хосты
entrypoint.ve-playground.ai.zevgen.com
DokuWiki. Открыт всем.
/→127.0.0.1:8080- Заголовки:
X-Frame-Options: SAMEORIGIN,X-Content-Type-Options, HSTS proxy_hide_header X-Powered-By— скрывает версию PHP, которую отдаёт DokuWiki- Пробрасывается
Authorization— нужен для JSON-RPC под Basic Auth
api.ve-playground.ai.zevgen.com
Webhook Telegram-бота.
/webhook→127.0.0.1:8443- Всё остальное →
404
Дополнительно порт 8443 планируется ограничить CIDR-диапазонами Telegram
(91.108.4.0/22, 149.154.160.0/20) на уровне цепочки DOCKER-USER в iptables —
на момент написания не сделано, см. risks.
mcp.ve-playground.ai.zevgen.com
ToolMesh. Два уровня доступа:
| Location | Доступ | Зачем |
|---|---|---|
/authorize, /token | все | OAuth 2.1 flow |
/ (включая /mcp, /.well-known/, /register) | allow-лист | MCP-эндпоинт |
Allow-лист:
allow 160.79.104.0/21; # Anthropic IPv4 allow 2607:6bc0::/48; # Anthropic IPv6 allow 127.0.0.1; allow <IP сотрудников>; # для mcp-remote, добавляются индивидуально deny all;
Таймауты подняты до proxy_read_timeout 300s — агентные вызовы с цепочкой
инструментов идут долго.
Про необходимость добавлять IP сотрудников — ограничение по ip.
SSL
Один SAN-сертификат Let's Encrypt на все три домена. Лежит в каталоге первого домена:
/etc/letsencrypt/live/entrypoint.ve-playground.ai.zevgen.com/ fullchain.pem privkey.pem
Все три server-блока ссылаются на этот же путь. Отдельных каталогов
api… и mcp… не существует — при попытке указать их nginx не стартует
с ошибкой cannot load certificate … No such file or directory.
Автопродление — certbot.timer. Управление сертификатом описано в
ssl-сертификаты.
Настройка с нуля
Порядок важен: финальный конфиг ссылается на сертификаты, которых до выпуска не существует, и nginx с ним не запустится.
- Проверить, что A/AAAA-записи всех трёх поддоменов указывают на этот сервер
- Установить:
apt install nginx certbot python3-certbot-nginx - Положить временный HTTP-only конфиг с
server_nameна все три домена и
location /.well-known/acme-challenge/ { root /var/www/html; }
- Выпустить сертификат:
certbot –nginx -d entrypoint… -d api… -d mcp… - Заменить конфиг на финальный с тремя раздельными
server-блоками nginx -t && systemctl reload nginx
Замечание по шагу 4: certbot –nginx правит тот конфиг, который видит. Если во
временном конфиге один server-блок на три домена, certbot допишет в него SSL для
одного домена и добавит return 404 в HTTP-блок. Поэтому финальный конфиг
пишется целиком заново, а не дописывается поверх.