Files
elevenlabs.io/swarm-report/caddy-letsencrypt-2026-09-20.md
vasyanskandClaude Opus 5 1a4ad47c77
Build Admin / Build image (push) Successful in 7s
docs: explain the 403 invalid_token case
Clients relied on /openrouter/ having no token check; v0.2.0 applies the
guard to every prefix, so the missing header now shows up everywhere.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 13:46:31 +07:00

55 lines
4.7 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.
# Переход nginx → Caddy + Let's Encrypt (proxy.bildme.ru)
Дата: 2026-09-20 · Профиль: refactoring · Репозиторий: `pub/elevenlabs.io`
## Задача
Заменить nginx на Caddy, оставить порт 8082 как есть, параллельно открыть 443 с сертификатом Let's Encrypt на `proxy.bildme.ru`. Предыстория — таймаут `api.deepseek.com` у клиента, из-за чего в прокси был добавлен маршрут `/deepseek/`.
## Аудит прода (62.84.98.250)
- 80/443 занимал хостовый nginx 1.18 (systemd): заглушка `/var/www/html` + vhost `tg.bildme.ru`, чей DNS уже указывал на `45.151.70.121`, сертификат истёк 14.07.2026 → потерь нет.
- Контейнер `api-proxy` из `/srv/elevenlabs` (не git), проброс `8082:8080`, образ из `git.realmanual.ru`.
- `docker-compose` 1.29.2 + Docker 28.2.2 → известная несовместимость (`KeyError: 'ContainerConfig'`).
## Изменения в репозитории
| Файл | Что |
|------|-----|
| `Caddyfile` | новый конфиг: сниппеты `(scrub)`, `(api)`, `(routes)`; маршруты в `route {}` — guard'ы отрабатывают до `handle_path` |
| `docker-entrypoint.sh` | генерация `matchers.caddy` / `guard.caddy` из `ALLOWED_CIDR` и `PROXY_SECRET`; обязательные `DOMAIN`, `ACME_EMAIL`; `caddy validate` перед стартом |
| `Dockerfile` | `caddy:2.11.4-alpine`, EXPOSE 80/443/8080 |
| `docker-compose.yml` | порты `80`, `443` (tcp+udp), `8082:8080`; тома `caddy_data`, `caddy_config` |
| `scripts/migrate-host-nginx.sh` | бэкап `/etc/nginx` + `/etc/letsencrypt`, отключение nginx и `certbot.timer`, проверка портов |
| `scripts/deploy.sh` | реальный прод-путь `/srv/elevenlabs`, приоритет `docker compose` v2 |
| `nginx/`, `ssl/` | удалены |
| `VERSION` | 0.2.0 |
Коммиты: `d71001a`, `e90d673`.
## Выполнено на сервере
1. Бэкап хостового nginx → `/root/nginx-backup-20260920-093758` (`nginx-T.dump`, `etc-nginx.tar.gz`, `letsencrypt.tar.gz`).
2. `systemctl disable --now nginx`, `systemctl disable --now certbot.timer`.
3. Установлен `docker-compose-v2` 2.40.3 (v1 ломался на Docker 28).
4. `/srv/elevenlabs/docker-compose.yaml` и `.env` обновлены (бэкапы `.bak-2026-09-20`), добавлены `DOMAIN=proxy.bildme.ru`, `ACME_EMAIL=vasyakrg@gmail.com`.
5. Контейнер пересоздан из образа `0.2.0` / `latest`.
## Проверки (прод)
| Проверка | Результат |
|----------|-----------|
| Сертификат | `CN=proxy.bildme.ru`, issuer Let's Encrypt YE1, до 19.12.2026 |
| `https://proxy.bildme.ru/health` | 200 |
| `http://62.84.98.250:8082/health` | 200 |
| `http://proxy.bildme.ru/health` | 308 → https |
| Без `X-Proxy-Token` | 403 `invalid_token` |
| IP вне `ALLOWED_CIDR` | 403 `ip_not_allowed` |
| `/deepseek/chat/completions` | 401 от DeepSeek (проброс работает, исходный i/o timeout снят) |
| `/telegram/`, `/openrouter/`, `/elevenlabs/` | 401 / 200 / 404 от апстримов — проброс работает |
| Неизвестный префикс | 404 `unknown_upstream` |
| Пересоздание контейнера | сертификат переиспользован из тома, повторного выпуска не было |
| Healthcheck | `healthy` |
## Риски и открытые пункты
- **8082 остаётся plain HTTP** — токен и ключи апстримов идут открытым текстом. Клиентов нужно перевести на `https://proxy.bildme.ru`, после чего порт закрыть (ufw на VM сейчас `inactive`).
- **Том `caddy_data`** содержит сертификаты и ACME-аккаунт. Его удаление = повторный выпуск и риск упереться в лимиты Let's Encrypt.
- **Хостовый nginx остановлен и отключён**, конфиги в бэкапе. Если на VM появятся новые сайты — их конфиг переносится в `Caddyfile`, а не обратно в nginx.
- **`certbot.timer` отключён** — старый серт `tg.bildme.ru` больше не обновляется (домен и так живёт на другом сервере).
- Локальный каталог `ssl/` с `tls.crt`/`tls.key` удалён — эти файлы не были в git и на проде не монтировались.