diff --git a/config.yaml b/config.yaml index 9e16547..75f3ee3 100644 --- a/config.yaml +++ b/config.yaml @@ -11,13 +11,14 @@ protocol: "https" bind-address: "0.0.0.0" port: 8080 -# Caddy на vps02 проксирует через WG (10.8.0.2) — после docker NAT -# source IP для контейнера = gateway docker-сети gotosocial (172.29.0.1). -# Доверяем ему, чтобы реальный клиентский IP брался из X-Forwarded-For. +# Реверс-прокси: Caddy на vps02 (87.242.100.206) → WireGuard 10.8.0.4 → bigbox 10.8.0.2:8082 +# → docker-NAT → контейнер (сеть gotosocial_default, шлюз 172.30.0.1). +# 10.8.0.4/32 — WG-адрес vps02 (реальный источник от Caddy); 172.30.0.1/16 — шлюз docker-сети. trusted-proxies: + - "10.8.0.4/32" - "127.0.0.1/32" - "::1" - - "172.29.0.1/16" + - "172.30.0.1/16" # Логи log-level: "info" diff --git a/docker-compose.yml b/docker-compose.yml index c7b33ca..85b8d42 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,8 +23,9 @@ services: GTS_DB_ADDRESS: "/gotosocial/storage/sqlite.db" # Медиа — локально (./data/storage) GTS_STORAGE_LOCAL_BASE_PATH: "/gotosocial/storage" - # Траст reverse proxy (Caddy на vps02 → WG 10.8.0.2 → docker NAT 172.29.0.1) - GTS_TRUSTED_PROXIES: "127.0.0.1/32,::1,172.29.0.1/16" + # Траст reverse proxy (Caddy на vps02 → WG 10.8.0.4 → bigbox 10.8.0.2 → docker NAT 172.30.0.1) + # 10.8.0.4/32 — WG-адрес vps02 (реальный источник от Caddy), 172.30.0.1/16 — шлюз docker-сети + GTS_TRUSTED_PROXIES: "10.8.0.4/32,127.0.0.1/32,::1,172.30.0.1/16" # Инстанс GTS_INSTANCE_TITLE: "dedinit()" GTS_INSTANCE_DESCRIPTION: "Нода для обычных людей" diff --git a/openspec/changes/fix-trusted-proxies/.openspec.yaml b/openspec/changes/fix-trusted-proxies/.openspec.yaml new file mode 100644 index 0000000..1a62d62 --- /dev/null +++ b/openspec/changes/fix-trusted-proxies/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-09-06 diff --git a/openspec/changes/fix-trusted-proxies/design.md b/openspec/changes/fix-trusted-proxies/design.md new file mode 100644 index 0000000..7193fad --- /dev/null +++ b/openspec/changes/fix-trusted-proxies/design.md @@ -0,0 +1,69 @@ +## Context + +- GoToSocial работает в Docker на bigbox (WG 10.8.0.2), конфиг — **только через env** + `GTS_*` (docker-образ не читает смонтированный config.yaml — падал «host must be set») +- Реверс-прокси: Caddy на vps02 (87.242.100.206, host net) → WireGuard 10.8.0.0/24 → + bigbox 10.8.0.2:8082 → docker-NAT → контейнер gotosocial (сеть gotosocial_default, + шлюз 172.30.0.1, контейнер 172.30.0.2) +- Caddy передаёт `X-Forwarded-For` по умолчанию; в Caddyfile блока social.dedinit.ru + только `header_up Host` и `header_up X-Forwarded-Proto https` (лишнего XFF нет) +- Warning рекомендует `10.8.0.4/32` — это WG-адрес vps02 (peer в `sudo wg show` на bigbox) +- Текущие значения: `GTS_TRUSTED_PROXIES=127.0.0.1/32,::1,172.30.0.1/16` + (compose/config полностью синхронны) +- Restart сервисов — только извне (SSH sudo) — **НЕ применимо**: bigbox локальная, + docker compose доступен напрямую + +## Goals / Non-Goals + +**Goals:** + +- Убрать предупреждение trusted-proxies (проверяется на главной странице) +- Rate limiting и федеризация используют реальный клиентский IP +- Синхронизировать compose (env) и config.yaml (reference) + +**Non-Goals:** + +- Не менять архитектуру проксирования (Caddy → WG → docker-NAT остаётся) +- Не добавлять лишние заголовки в Caddy (XFF передаётся по умолчанию, X-Real-IP не нужен) +- Не отключать rate limiting, не добавлять rate-limit exceptions + +## Decisions + +### D1: Добавить `10.8.0.4/32` в trusted-proxies + +**Решение:** В `docker-compose.yml` env `GTS_TRUSTED_PROXIES` и в `config.yaml` +`trusted-proxies` добавить `10.8.0.4/32`, сохранив `127.0.0.1/32,::1,172.30.0.1/16`. + +**Обоснование:** Предупреждение прямо указывает недостающий диапазон. 10.8.0.4 — это +WG-адрес vps02 (peer из `sudo wg show`, allowed-ips 10.8.0.4/32). Именно этот адрес +видит GtS как источник входящих соединений от Caddy (после docker-NAT source-адрес — +gateway 172.30.0.1, но GtS доверяет цепочке trusted proxies и берёт IP из XFF; чтобы +корректно определить реальный client IP, адрес прокси-хопа 10.8.0.4 должен быть в +списке доверия). Траст docker-gateway 172.30.0.1/16 тоже оставляем — он реальный +source-адрес в контейнере. + +**Альтернативы:** +- Добавить только 10.8.0.4/32 без 172.30.0.1 — недостаточно: GtS всё равно видит + docker-gateway как source и не сможет довериться XFF от него. +- 10.8.0.0/24 целиком — избыточно: единственный прокси-хоп в этой сети — vps02. + +### D2: Изменить только один файл-источник правды (compose) + синхронизировать config.yaml + +**Решение:** Правим `docker-compose.yml` (рабочий) и `config.yaml` (reference) — +оба, одинаково. + +**Обоснование:** Образ GtS читает только env. Но config.yaml хранится в git как +reference и документирует настройку; расхождение создавало бы ложное впечатление. + +### D3: Пересоздание через docker compose, без ручного удаления контейнера + +**Решение:** `docker compose up -d --force-recreate gotosocial` (env меняется → контейнер +пересоздаётся). Данные не теряются (volume ./data). + +## Risks / Trade-offs + +- **Перезапуск контейнера**: кратковременный даунтайм (секунды), инстанс поднимется сам + (restart: unless-stopped). Откат — вернуть старое значение env + recreate. +- **Неправильный IP в trusted-proxies**: если 10.8.0.4 не является фактическим source, + предупреждение останется (но поменяет SUGGESTED_IP_RANGE) — тогда добавить то, что + предложит GtS. Проверяется сразу после рестарта. \ No newline at end of file diff --git a/openspec/changes/fix-trusted-proxies/proposal.md b/openspec/changes/fix-trusted-proxies/proposal.md new file mode 100644 index 0000000..5b2a621 --- /dev/null +++ b/openspec/changes/fix-trusted-proxies/proposal.md @@ -0,0 +1,43 @@ +## Why + +GoToSocial на главной странице показывает предупреждение о неверной настройке `trusted-proxies`: +инстанс видит входящие запросы с IP, который не указан в доверенных прокси, из-за чего +rate-limiting (и, как следствие, федеризация) может работать некорректно. + +Warning выводит `SUGGESTED_IP_RANGE` = `10.8.0.4/32` — это WireGuard-адрес vps02 (Caddy, +реверс-прокси) в сети 10.8.0.0/24. Трафик от Caddy приходит на bigbox (10.8.0.2), +проходит docker-NAT и попадает в контейнер GtS с source = адресом шлюза docker-сети +Gotosocial (172.30.0.1). Текущий `trusted-proxies` (`127.0.0.1/32,::1,172.30.0.1/16`) +не охватывает реальный адрес источника, который видит GtS. + +## What Changes + +- Добавить `10.8.0.4/32` (WireGuard-адрес vps02/Caddy) в `trusted-proxies`: + - `docker-compose.yml` → `GTS_TRUSTED_PROXIES` env (рабочий конфиг — только через env) + - `config.yaml` → `trusted-proxies` (reference-конфиг, образ его не читает, но держим синхронным) +- Сохранить существующие `127.0.0.1/32`, `::1`, `172.30.0.1/16` — ничего не убирается +- Пересоздать контейнер (`docker compose up -d --force-recreate`), рестарт сервиса снаружи + не требуется (bigbox — локальная машина, compose доступен) +- Проверить, что предупреждение исчезло и rate-limit работает с реальным клиентским IP +- Закоммитить и запушить изменения в git (gitverse — источник истины) + +## Capabilities + +### New Capabilities + +- `gotosocial/trusted-proxies`: корректная настройка доверенных прокси GoToSocial — + инстанс определяет реальный IP клиента за реверс-прокси, rate-limiting и федеризация + работают штатно, предупреждение отсутствует + +### Modified Capabilities + +- `gotosocial/deploy` (существующая): уточняется требование `trusted-proxies` — добавляется + IP реверс-прокси (10.8.0.4/32, WireGuard vps02) к доверенным + +## Impact + +- **Сервисы/порты**: GoToSocial (docker, порт 8082 наружу / 8080 в контейнере); конфиг + GTS_TRUSTED_PROXIES в docker-compose.yml; reference config.yaml +- **Сеть**: WireGuard 10.8.0.0/24; docker-сеть gotosocial 172.30.0.0/16 (шлюз 172.30.0.1) +- **Rate limiting / федеризация**: должны начать использовать реальный клиентский IP +- **Rollback**: вернуть прежнее значение `GTS_TRUSTED_PROXIES` + `docker compose up -d` \ No newline at end of file diff --git a/openspec/changes/fix-trusted-proxies/specs/gotosocial/trusted-proxies/spec.md b/openspec/changes/fix-trusted-proxies/specs/gotosocial/trusted-proxies/spec.md new file mode 100644 index 0000000..6a5eca8 --- /dev/null +++ b/openspec/changes/fix-trusted-proxies/specs/gotosocial/trusted-proxies/spec.md @@ -0,0 +1,62 @@ +# GoToSocial Trusted Proxies — Delta Spec + +## Purpose + +Обеспечить корректную работу rate-limiting и федеризации GoToSocial за реверс-прокси: +инстанс должен доверять реальному адресу прокси и брать клиентский IP из +`X-Forwarded-For` / `X-Real-IP`, а не видеть все запросы с одного адреса. + +## ADDED Requirements + +### Requirement: Trusted-proxies включает реальный адрес реверс-прокси + +- **MUST**: В `docker-compose.yml` (env `GTS_TRUSTED_PROXIES`) и `config.yaml` + (`trusted-proxies`) включены: + - `10.8.0.4/32` — WireGuard-адрес vps02 (Caddy, реверс-прокси) + - `127.0.0.1/32` и `::1` — локальные адреса + - `172.30.0.1/16` — шлюз docker-сети gotosocial +- **MUST**: Рабочим конфигом является env в docker-compose.yml (`GTS_*`); + `config.yaml` — reference и держится синхронным +- **SHOULD**: Предупреждение о trusted-proxies на главной странице инстанса отсутствует + +#### Scenario: Предупреждение исчезло + +- **GIVEN** инстанс запущен с обновлённым `GTS_TRUSTED_PROXIES` +- **WHEN** открыть главную страницу `https://social.dedinit.ru/` +- **THEN** на странице нет текста «Warning! It looks like trusted-proxies is not set correctly» + +#### Scenario: Конфиг синхронизирован + +- **GIVEN** обновлён docker-compose.yml +- **WHEN** выполнить `docker compose config | grep TRUSTED` +- **THEN** в выводе присутствуют `10.8.0.4/32`, `127.0.0.1/32`, `::1`, `172.30.0.1/16` + +### Requirement: Rate limiting использует реальный клиентский IP + +- **MUST**: После настройки GtS определяет IP клиента из заголовков прокси, а не из + source-адреса docker-gateway +- **SHOULD**: Все внешние запросы к инстансу логируются с реальным IP клиента + +#### Scenario: Логи содержат реальный клиентский IP + +- **GIVEN** инстанс пересоздан с новой конфигурацией +- **WHEN** `docker compose logs gotosocial --since 5m | grep -i 'GET /' | tail -5` +- **THEN** записи содержат IP клиента, отличный от `172.30.x.x` (для внешних запросов) + +## MODIFIED Requirements + +### Requirement: GtS доверяет прокси (изменение в capability gotosocial-deploy) + +- **MODIFIED**: В требовании «GtS доверяет прокси: в `config.yaml` `trusted-proxies` + включает IP/подсеть Caddy (например `10.8.0.2`)» добавлено уточнение: + - **MUST**: `trusted-proxies` включает реальный адрес источника трафика — + `10.8.0.4/32` (WireGuard-адрес vps02, Caddy), `127.0.0.1/32`, `::1`, + `172.30.0.1/16` (шлюз docker-сети) + - Ранее указанный `172.29.0.1/16` заменён на фактический шлюз docker-сети + gotosocial `172.30.0.1/16` (подсеть сети определена в compose) + +#### Scenario: Все доверенные прокси присутствуют в конфиге + +- **GIVEN** конфигурация обновлена +- **WHEN** `docker compose config | grep -A2 TRUSTED_PROXIES` +- **THEN** в списке присутствуют `10.8.0.4/32`, `127.0.0.1/32`, `::1`, `172.30.0.1/16` \ No newline at end of file diff --git a/openspec/changes/fix-trusted-proxies/tasks.md b/openspec/changes/fix-trusted-proxies/tasks.md new file mode 100644 index 0000000..c181592 --- /dev/null +++ b/openspec/changes/fix-trusted-proxies/tasks.md @@ -0,0 +1,29 @@ +# Tasks — Fix Trusted Proxies + +## 1. Обновить конфигурацию + +- [x] 1.1 В `docker-compose.yml` env `GTS_TRUSTED_PROXIES` добавить `10.8.0.4/32` + (сохранив `127.0.0.1/32,::1,172.30.0.1/16`) + Проверка: `grep TRUSTED docker-compose.yml` +- [x] 1.2 В `config.yaml` `trusted-proxies` добавить `10.8.0.4/32` (синхронно с compose) + Проверка: `grep -A5 'trusted-proxies' config.yaml` +- [x] 1.3 `docker compose config` валиден + Проверка: `docker compose config --quiet && echo OK` + +## 2. Применить и проверить + +- [x] 2.1 Пересоздать контейнер с новой конфигурацией + Проверка: `docker compose up -d --force-recreate gotosocial` → контейнер Up +- [x] 2.2 HTTP 200 на внутреннем порту + Проверка: `curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8082/` → 200 +- [x] 2.3 Предупреждение trusted-proxies исчезло + Проверка: `curl -s https://social.dedinit.ru/ | grep -c 'trusted-proxies is not set'` → 0 +- [x] 2.4 Rate limiting/клиентский IP: в логах внешние запросы с реальным IP + Проверка: `docker compose logs gotosocial --since 5m | grep -oE '"ip":"[0-9.]+"' | sort -u | head` + +## 3. Git + +- [x] 3.1 Довести до конца все артефакты (proposal/specs/design/tasks), `openspec validate` OK + Проверка: `cd /opt/gotosocial && openspec validate fix-trusted-proxies` +- [x] 3.2 Коммит и пуш на gitverse (источник истины) + Проверка: `git log --oneline -1 && git push origin main` успешен \ No newline at end of file