# RU-шлюз и EU ai-hub

Дополнение к полному `ai-hub` из `../deployment/`: 9router, Open WebUI и Caddy уже работают на EU. На отдельном RU-сервере HAProxy передаёт HTTP и исходный TLS через WireGuard в тот же Caddy. Пример рассчитан на Debian/Ubuntu с systemd, свободный интерфейс `wg-ai` и свободные TCP 80/443 на RU.

| Адрес | Значение в примере | Назначение |
|---|---|---|
| Публичный IPv4 RU | `198.51.100.10` | DNS RU-доменов и источник UDP для firewall EU |
| Публичный IPv4 EU | `203.0.113.20` | `Endpoint` в RU WireGuard |
| Приватный IPv4 RU | `10.77.0.1` | Интерфейс `wg-ai` на RU |
| Приватный IPv4 EU | `10.77.0.2` | Интерфейс `wg-ai` на EU и upstream HAProxy |

Публичные IP здесь документационные: замените своими. Приватную пару используйте, если она не пересекается с вашими сетями; при замене исправьте оба WG-файла и оба upstream в HAProxy.

Создайте A-записи `router-ru.example.com` и `chat-ru.example.com` на публичный IPv4 RU. Замените эти два домена в `ru/haproxy.cfg` и `eu/.env.example`. Прямые `router.example.com` и `chat.example.com` из исходного `.env` продолжают указывать на EU. AAAA для новых имён добавляйте только при настроенном IPv6-входе.

В действующем firewall и правилах облачного провайдера разрешите:

| Где | Входящий трафик |
|---|---|
| RU, публичный интерфейс | TCP 80/443 от клиентов и ACME |
| EU, публичный интерфейс | UDP 51820 только от публичного IPv4 RU; прежние TCP 80/443 сохранить |
| EU, `wg-ai` | TCP 80/443 от `10.77.0.1` |

Исходящий UDP с RU к EU:51820 и ответный трафик должны проходить. Порты приложений 20128/8080 остаются только внутри Docker. Для WireGuard не нужны default route, дополнительные правила NAT или пересылка клиентского трафика: HAProxy сам подключается к соседнему адресу.

Если на серверах включён [UFW](https://wiki.ubuntu.com/UFW), разрешите SSH на обоих. На RU также откройте TCP 80/443 для HAProxy; на EU эти порты публикует Docker, и правила UFW для них не нужны. В `SSH_PORT` укажите свой порт SSH (в примере `22`):

```sh
sudo apt-get update
sudo apt-get install -y ufw
SSH_PORT=22
sudo ufw allow "${SSH_PORT}/tcp"
# только RU:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
```

На EU добавим разрешение для WireGuard с RU-сервера. В `RU_PUBLIC_IP` укажите публичный IP RU:

```sh
RU_PUBLIC_IP='REPLACE_WITH_RU_PUBLIC_IP'
sudo ufw allow from "$RU_PUBLIC_IP" to any port 51820 proto udp
```

Порты 80/443 Caddy на EU уже опубликованы в Compose. Их доступность настраивает Docker; обычные правила UFW не фильтруют [опубликованные порты контейнеров](https://docs.docker.com/engine/network/packet-filtering-firewalls/#docker-and-ufw). В сетевом firewall хостера на EU также разрешите UDP 51820 от публичного IP RU.

Порядок: подготовить WireGuard на обеих сторонах → запустить туннель на обеих → обновить [ai-hub на EU](eu/README.md) → включить [RU HAProxy](ru/README.md). Публичные ключи передаются соседнему серверу, приватные остаются на своём.

TLS завершается только в EU Caddy. Через RU проходят и HTTP-01 ACME, и HTTPS; Host и SNI сохраняются. Caddy обслуживает четыре имени, передаёт запросы только двум заданным приложениям, поддерживает WebSocket и не буферизует потоковые ответы. Пароль панели 9router, API-ключи и вход в Open WebUI остаются обязательными.

Файлы по сторонам:

- RU: [WireGuard](ru/wg-ai.conf.example), [HAProxy](ru/haproxy.cfg), [команды](ru/README.md).
- EU: [WireGuard](eu/wg-ai.conf.example), [.env.example](eu/env.example), [compose.yml](eu/compose.yml), [Caddyfile](eu/Caddyfile.txt), [команды](eu/README.md).

Официальные справочники: [WireGuard](https://www.wireguard.com/quickstart/), [wg-quick](https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8), [HAProxy](https://docs.haproxy.org/3.2/configuration.html), [Caddy reverse_proxy](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy), [Compose merge](https://docs.docker.com/compose/how-tos/multiple-compose-files/merge/), [Open WebUI CORS](https://docs.openwebui.com/reference/env-configuration/#cors_allow_origin).
