From ea19a74c127c0bb455bb2604698467c99c7225f9 Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Wed, 9 Sep 2026 00:26:08 +0300 Subject: [PATCH] Configure the instance domain from .env instead of compose.yml compose.yml was tracked but had to be edited per deployment, so every update collided with the local change ("your local changes would be overwritten by merge"). The domain now comes from STOAT_DOMAIN via compose interpolation, and host.docker.internal is mapped unconditionally so a host-side proxy needs no edit either. Nothing in compose.yml has to be touched any more. Co-Authored-By: Claude Opus 5 --- .env.example | 5 +++++ README.md | 18 +++++++----------- compose.yml | 43 ++++++++++++++++++++++--------------------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/.env.example b/.env.example index 18e2365..2713dd8 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,11 @@ # extra_hosts в compose.yml, поэтому TLS валидный и NAT loopback не нужен. STOAT_API_URL=https://chat.example.com/api +# Домен вашего Stoat — тот же, что в STOAT_API_URL, без схемы. +# Используется в compose.yml: контейнер резолвит его в сам хост, где внешний +# Caddy держит валидный TLS. Сам compose.yml править не нужно. +STOAT_DOMAIN=chat.example.com + # Токен бота: Settings → My Bots → создать бота → скопировать токен. STOAT_BOT_TOKEN= diff --git a/README.md b/README.md index e0a1978..c715bc0 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,8 @@ openssl rand -hex 32 # → JWT_SECRET Минимум, что нужно указать: ```dotenv -STOAT_API_URL=https://stoat.example.com/api +STOAT_API_URL=https://chat.example.com/api +STOAT_DOMAIN=chat.example.com STOAT_BOT_TOKEN=<токен бота> PUBLIC_URL=https://music.example.com JWT_SECRET=<случайные 32 байта> @@ -80,18 +81,13 @@ JWT_SECRET=<случайные 32 байта> `STOAT_API_URL` указывается публичный (`https://домен/api`): бот ведёт себя как обычный клиент — ходит в API, gateway и LiveKit через тот же внешний прокси с валидным TLS, что и браузеры. -### 4. Указать домен инстанса в `compose.yml` +### 4. Про `STOAT_DOMAIN` Бот запускается **отдельным compose-проектом** и с внутренним Caddy инстанса никак не связан. -В [compose.yml](compose.yml) поправьте одну строку — домен вашего Stoat: - -```yaml - extra_hosts: - - "chat.example.com:host-gateway" -``` - -Эта запись заставляет контейнер резолвить домен инстанса в сам хост, где внешний Caddy держит -443 с валидным сертификатом. Так бот не зависит от NAT loopback на роутере. +`STOAT_DOMAIN` из `.env` подставляется в `extra_hosts`, и контейнер резолвит домен инстанса +в сам хост, где внешний Caddy держит 443 с валидным сертификатом — так бот не зависит от +NAT loopback на роутере. **Сам [compose.yml](compose.yml) править не нужно**, иначе `git pull` +будет конфликтовать с обновлениями. ### 5. Повесить панель на внешний Caddy diff --git a/compose.yml b/compose.yml index 8c330b8..5f74a51 100644 --- a/compose.yml +++ b/compose.yml @@ -1,21 +1,22 @@ -name: stoat-mbot - -services: - mbot: - build: . - restart: always - env_file: .env - ports: - # Наружу не торчит: домен вешается на внешний Caddy хоста. - - "127.0.0.1:3005:3005" - extra_hosts: - # Домен Stoat резолвится в хост, где внешний Caddy держит валидный TLS. - # Так бот ходит в API, gateway и LiveKit ровно как обычный клиент, - # без зависимости от NAT loopback на роутере. - # Замените на свой домен: - - "chat.example.com:host-gateway" - # Раскомментируйте, если YTDLP_PROXY указывает на прокси, поднятый на хосте: - # - "host.docker.internal:host-gateway" - volumes: - # cookies.txt для yt-dlp и/или локальная медиатека - - ./data:/data +name: stoat-mbot + +# Этот файл править не нужно: всё настраивается в .env, который docker compose +# читает и для подстановки переменных, и как env_file сервиса. +services: + mbot: + build: . + restart: always + env_file: .env + ports: + # Наружу не торчит: домен вешается на внешний Caddy хоста. + - "127.0.0.1:3005:3005" + extra_hosts: + # Домен Stoat (STOAT_DOMAIN в .env) резолвится в сам хост, где внешний + # Caddy держит валидный TLS. Так бот ходит в API, gateway и LiveKit ровно + # как обычный клиент, без зависимости от NAT loopback на роутере. + - "${STOAT_DOMAIN:-stoat.invalid}:host-gateway" + # Для YTDLP_PROXY, указывающего на прокси, поднятый на хосте. + - "host.docker.internal:host-gateway" + volumes: + # cookies.txt для yt-dlp и/или локальная медиатека + - ./data:/data