# Деплой nika-gallery (1nika.ru) Полный runbook подъёма сайта Ники на VPS: Docker Compose (backend Express + Next.js фронт + Postgres 16 + nginx), вход через Яндекс ID и подключение к единому боту флота (`@servaki_online_bot`) через сайт-адаптер `/api/bot/*`. > ⚠️ **Живой VPS-деплой — решение владельца** (выбор ноды и DNS). Этот документ — > команды и чек-лист; агент репо готовит, но на боевой узел не раскатывает. --- ## 0. Что уже готово в репо - `docker-compose.yml` — db / backend / frontend / nginx. - `db/schema.sql` (+ `db/migrations/club_access.sql`, `db/migrations/bot_adapter.sql`). - Вход через Яндекс ID (`backend/src/routes/oauth.js`), redirect на `1nika.ru`. - Сайт-адаптер бота (`backend/src/routes/bot.js`, `middleware/botAuth.js`). - nginx для `1nika.ru` / `www.1nika.ru`. --- ## 1. DNS На домен **1nika.ru** (регистратор/DNS владельца) добавить A-записи на IP выбранной ноды: ``` 1nika.ru. A www.1nika.ru. A ``` Дождаться распространения (`dig +short 1nika.ru` должен вернуть ``). --- ## 2. Подготовка сервера Нужны: Docker + docker compose plugin, открытые порты 80/443. ```bash git clone http://192.168.1.120/german/nika-gallery.git /opt/nika-gallery cd /opt/nika-gallery git checkout main # либо feat/bot-adapter до мержа cp .env.example .env ``` --- ## 3. Заполнить `.env` (боевые значения — только на сервере, НЕ в git) | Переменная | Значение | Откуда | |---|---|---| | `POSTGRES_PASSWORD` | сильный пароль | сгенерировать | | `DATABASE_URL` | `postgresql://postgres:@db:5432/nika_gallery` | собрать | | `JWT_SECRET` / `JWT_REFRESH_SECRET` | `openssl rand -hex 32` (каждый свой) | сгенерировать | | `YANDEX_CLIENT_ID` | `1f64f6ebcd9c45f9af78987204af8e36` | Я.Диск `YANDEX-OAUTH-APPS.secret.txt` [NIKA ART] | | `YANDEX_CLIENT_SECRET` | `a2b737fc…` | там же | | `YANDEX_REDIRECT_URI` | `https://1nika.ru/api/auth/yandex/callback` | (уже в .env.example) | | `FRONTEND_URL` / `SITE_URL` | `https://1nika.ru` | — | | `BOT_API_TOKEN` | `openssl rand -hex 32` | сгенерировать; **тот же** токен → в реестр бота (`sites.api_token`) + Я.Диск | | `BOT_SITE_KEY` | `nika` | — | | `NEXT_PUBLIC_API_URL` | `https://1nika.ru/api` | — | | `OWNER_EMAIL`, `SMTP_*`, `TELEGRAM_*` | по факту | владелец | ⚠️ **Секреты не коммитить.** В git — только `.env.example` с пустыми полями. `YANDEX_REDIRECT_URI` должен **точно** совпадать со значением в кабинете `oauth.yandex.ru` (приложение NIKA ART) — иначе Яндекс вернёт `redirect_uri_mismatch`. --- ## 4. SSL-сертификат (Let's Encrypt) nginx ждёт `nginx/certs/fullchain.pem` и `nginx/certs/privkey.pem`. Выпустить certbot'ом (standalone до старта nginx, либо webroot): ```bash # порт 80 должен быть свободен docker run --rm -p 80:80 \ -v /opt/nika-gallery/letsencrypt:/etc/letsencrypt \ certbot/certbot certonly --standalone \ -d 1nika.ru -d www.1nika.ru --agree-tos -m --no-eff-email mkdir -p /opt/nika-gallery/nginx/certs cp /opt/nika-gallery/letsencrypt/live/1nika.ru/fullchain.pem nginx/certs/ cp /opt/nika-gallery/letsencrypt/live/1nika.ru/privkey.pem nginx/certs/ ``` Продление — cron/systemd-timer с `certbot renew` + копированием в `nginx/certs/` и `docker compose exec nginx nginx -s reload`. --- ## 5. Старт и миграции `db/schema.sql` и `db/seed.sql` применяются автоматически при **первой** инициализации тома Postgres (см. `docker-entrypoint-initdb.d` в compose). Миграции из `db/migrations/` надо применить вручную (они аддитивны и идемпотентны). ```bash docker compose build docker compose up -d db # дождаться healthy: docker compose exec db pg_isready -U postgres # Миграции (клуб + Яндекс ID, затем адаптер бота): docker compose exec -T db psql -U postgres -d nika_gallery < db/migrations/club_access.sql docker compose exec -T db psql -U postgres -d nika_gallery < db/migrations/bot_adapter.sql docker compose up -d # поднять backend + frontend + nginx ``` Назначить владельца (Ника) ролью `owner`: ```bash docker compose exec -T db psql -U postgres -d nika_gallery \ -c "UPDATE users SET role='owner' WHERE email='';" ``` --- ## 6. Проверка ```bash curl -s https://1nika.ru/api/health # {status:ok} curl -s https://1nika.ru/api/bot/health # {ok:true, site:"nika"} curl -s -o /dev/null -w '%{http_code}\n' \ https://1nika.ru/api/bot/publications # 401 (без токена) curl -s -H "Authorization: Bearer $BOT_API_TOKEN" \ https://1nika.ru/api/bot/publications # [] или список ``` Вход через Яндекс: открыть `https://1nika.ru/api/auth/yandex` → авторизация → редирект на `https://1nika.ru/club#token=…`. --- ## 7. Подключение к боту флота После деплоя владелец в реестре бота (`sites` на finik, `/var/lib/webhub-bot/state.db`) выставляет для `site_key='nika'`: - `base_url = https://1nika.ru` - `api_token = ` - `status = live` (сейчас `soon`). Бот дергает `/api/bot/*` с заголовком `Authorization: Bearer `. Контракт — `servaki-webhub-bot/SPEC.md`. --- ## 8. Обновления ```bash cd /opt/nika-gallery && git pull && docker compose build && docker compose up -d ``` (автоматизировано в `.gitea/workflows/deploy.yml` при push в `main`; требует секретов раннера `DEPLOY_HOST`, `DEPLOY_KEY`). ## Приложение: карта ручек адаптера | Метод | Путь | Auth | Ника | |---|---|---|---| | GET | `/api/bot/health` | — | `{ok,site}` | | GET | `/api/bot/publications?status=&limit=` | Bearer | список works | | POST | `/api/bot/publications` `{title,body,media[]}` | Bearer | works(draft) → `{id}` | | POST | `/api/bot/publications/:id/publish` | Bearer | works.status=published → `{id,url}` | | DELETE | `/api/bot/publications/:id` | Bearer | delete works (+media cascade) | | POST | `/api/bot/materials` (multipart `file`) | Bearer | media → `{id,url}` |