opencode-config/docs/decisions/021-pr-51-docker-port-expose.md
Sergey 655a98d077
fix(docker): expose port 4096 on 0.0.0.0 for NPM proxy (#51)
* fix(docker): expose port 4096 on 0.0.0.0 for NPM proxy

* test(docker): add docker-compose port exposure test

* docs(handoff): set PR number for docker port expose

---------

Co-authored-by: opencode-agent <agent@slaid098.dev>
2026-07-24 20:27:37 +03:00

38 lines
No EOL
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-021 (PR #51): Expose opencode port 4096 on 0.0.0.0 for cross-host NPM proxy
## Статус
Accepted (2026-07-24)
## Контекст
opencode-config мигрирует на linux-1 (`193.3.168.35`). Web UI opencode слушает порт 4096 (`opencode serve --hostname 0.0.0.0 --port 4096`). Публичный доступ к домену `opencode.slaid098.dev` идёт через NPM (Nginx Proxy Manager, контейнер `jc21/nginx-proxy-manager`), который живёт на linux-2 (`92.119.114.77`) и проксирует `opencode.slaid098.dev``193.3.168.35:4096`.
Текущий `docker-compose.yml` биндит порт как `127.0.0.1:4096:4096` (localhost-only). Это работало, пока opencode жил на linux-2: Cloudflare named tunnel (`cloudflared`) запускался на том же хосте и обращался к `127.0.0.1:4096` локально. После миграции на linux-1 NPM на linux-2 должен стучаться на публичный IP linux-1 — localhost-only биндинг отвергает соединение на loopback-интерфейсе, NPM не достучится.
Топология подтверждена SSH-аудитом (memory `technical/opencode-config-migration-state-2026-07-24.md`): NPM на linux-2, opencode мигрирует на linux-1 (раньше Cloudflare tunnel, теперь NPM-прокси).
## Решение
Перевязать порт 4096 в `docker-compose.yml` с `127.0.0.1:4096:4096` на `0.0.0.0:4096:4096`:
```yaml
ports:
- "0.0.0.0:4096:4096"
```
`0.0.0.0:4096` биндит контейнерный порт 4096 на все интерфейсы хоста, NPM на linux-2 достучится через публичный IP linux-1 (`193.3.168.35:4096`).
Дополнительно — 5 тестов в `tests/test_docker_compose.py` (parsed + raw check на оба условия), чтобы предотвратить регрессию обратно к localhost-only.
### Альтернативы
- **Оставить `127.0.0.1:4096` + Cloudflare named tunnel на linux-1** — отклонено: миграционный план переводит публичный доступ на NPM-прокси (centralized SSL-termination + domain management на linux-2), Cloudflare tunnel на linux-1 потребовал бы отдельной настройки и токена. NPM уже управляет 9 доменами `*.slaid098.dev`, добавить `opencode.slaid098.dev` проще, чем поднимать второй tunnel.
- **Биндить на конкретный публичный IP linux-1 (`193.3.168.35:4096:4096`)** — отклонено: hardcoded IP в compose хрупок (при смене хоста/IP потребует правки файла). `0.0.0.0` переносим между хостами; доступ ограничивается firewall на linux-1 (ufw/iptables, разрешить 4096 только с linux-2 IP), что конфигурируется вне compose и не требует правок при миграции.
- **Не открывать, проксировать через SSH-туннель linux-2→linux-1** — отклонено: SSH-туннель — ручная/хрупкая инфраструктура (restart, no systemd unit, no health-check), NPM → прямой TCP — стандартный паттерн reverse proxy. Дополнительный слой без выгоды.
- **Поднять NPM на linux-1 (чтобы NPM и opencode на одном хосте, localhost-only OK)** — отклонено: linux-1 не имеет NPM, установка дублирует инфраструктуру (9 доменов уже на linux-2 NPM, SSL-сертификаты, database.sqlite). Миграция opencode не должна тянуть за собой миграцию NPM.
## Альтернативы
См. блок «Альтернативы» выше (включён в Решение для единого контекста). Кратко: отклонены — Cloudflare tunnel на linux-1, hardcoded public IP, SSH-туннель, NPM на linux-1. Выбран `0.0.0.0` + firewall на linux-1 (переносимость + security на уровне хоста, не compose).