docs: подробный README (разбор проекта при переносе в Gitea)
Старый README сохранён как README.upstream.md.
Этот коммит содержится в:
+100
-279
@@ -1,317 +1,138 @@
|
|||||||
# Raspi Telegram Live Chat
|
# WSChat
|
||||||
|
|
||||||
Self-hosted live chat system for Raspberry Pi with embeddable website widget, web admin panel, Telegram as the operator interface, and a separate VPS-hosted frontend.
|
Self-hosted онлайн-консультант для сайта (аналог Jivo/Tidio) с Telegram в роли интерфейса оператора. Посетитель пишет через встраиваемый виджет, сообщение попадает в бэкенд, оттуда рассылается назначенным операторам в Telegram; ответ оператора возвращается в виджет по WebSocket. Предназначен для владельца одного или нескольких сайтов, который не хочет платить за SaaS-чат и держит инфраструктуру на своём VPS с FastPanel.
|
||||||
|
|
||||||
## Goal
|
## Стек
|
||||||
|
|
||||||
Build a lightweight Jivo-like chat platform where visitors write through a website widget and only Telegram operators configured in the admin panel receive and answer messages.
|
- Node.js 20+, ESM.
|
||||||
|
- Backend: Fastify 5, `@fastify/cors`, `@fastify/rate-limit`, `@fastify/websocket`.
|
||||||
|
- БД: SQLite через `better-sqlite3` (WAL, foreign keys), схема создаётся кодом при старте.
|
||||||
|
- Telegram: `telegraf` 4, опционально через SOCKS5 (`socks-proxy-agent`, схема `socks5h://`).
|
||||||
|
- Админ-панель: React + Vite, `lucide-react`.
|
||||||
|
- Виджет: ванильный JS, сборка Vite, изоляция через Shadow DOM.
|
||||||
|
- Деплой: npm workspaces, PM2, FastPanel (nginx/Apache под управлением панели), rsync.
|
||||||
|
|
||||||
## Target deployment
|
## Структура
|
||||||
|
|
||||||
Primary target for MVP:
|
| Путь | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `package.json` | Корневой workspace: `backend`, `admin-panel`, `widget`, `deploy/deploy-agent`; скрипты сборки и деплоя |
|
||||||
|
| `backend/src/server.js` | Fastify-приложение: HTTP API, CORS по списку сайтов, rate limit, WebSocket `/ws`, старт Telegram-моста |
|
||||||
|
| `backend/src/db.js` | Подключение к SQLite, миграция схемы (`sites`, `operators`, `site_operators`, `visitors`, `conversations`, `messages`, `settings`), запросы и работа с настройками |
|
||||||
|
| `backend/src/telegram.js` | Telegraf-мост: рассылка сообщений операторам, разбор ответов (reply и inline-кнопка выбора диалога), команда `/status`, перезапуск бота на лету |
|
||||||
|
| `backend/src/config.js` | Чтение `.env`, значения по умолчанию, production-путь к базе |
|
||||||
|
| `backend/.env.example` | Шаблон переменных окружения бэкенда |
|
||||||
|
| `admin-panel/src/main.jsx` | Панель: статистика, список сайтов и операторов, embed-код, настройки Telegram/SOCKS5, лента последних сообщений, диагностика `/health` |
|
||||||
|
| `admin-panel/vite.config.js` | Сборка с `base: '/admin/'` |
|
||||||
|
| `widget/src/widget.js` | Встраиваемый виджет: Shadow DOM, localStorage-идентификатор посетителя, POST сообщения и WebSocket-подписка на ответы |
|
||||||
|
| `widget/vite.config.js` | Сборка с фиксированным именем артефакта `widget.js` |
|
||||||
|
| `deploy/vps/install.sh` | Установщик VPS: пакеты, Node.js, PM2, `npm install`, сборка фронтенда, запуск бэкенда |
|
||||||
|
| `deploy/vps/bootstrap.sh`, `deploy/raspberry/bootstrap.sh` | Первичная подготовка VPS и Raspberry Pi |
|
||||||
|
| `deploy/deploy-agent/src/deploy-frontend.js` | Агент обновления фронтенда: `git pull`, `npm ci`, сборка, rsync в webroot FastPanel с проверкой безопасности пути |
|
||||||
|
| `docs/` | Инструкции: `INSTALL.md`, `VPS_ONLY_INSTALL.md`, `FASTPANEL.md`, `FASTPANEL_MANUAL_FRONTEND.md`, `RASPBERRY_PI.md`, `UPDATE_BUNDLE.md` |
|
||||||
|
| `.sw` | Журнал разработки: текущее состояние, продовые пути, диагностика, список нерешённых задач |
|
||||||
|
| `README.upstream.md` | Исходное техническое задание проекта (сохранено при пересборке README) |
|
||||||
|
|
||||||
- Raspberry Pi 3 Model B at home
|
## Как запустить
|
||||||
- Raspberry Pi OS Lite 32-bit
|
|
||||||
- Backend API on Raspberry Pi
|
|
||||||
- Telegram bot on Raspberry Pi
|
|
||||||
- SQLite database on Raspberry Pi
|
|
||||||
- VPS with FastPanel for admin panel, widget.js, static assets, HTTPS, and public reverse proxy
|
|
||||||
- WireGuard between VPS and Raspberry Pi
|
|
||||||
- Domain/site management through FastPanel where possible
|
|
||||||
|
|
||||||
Cloudflare must not be required for this project.
|
Локально:
|
||||||
|
|
||||||
Recommended OS for Raspberry Pi 3B MVP:
|
|
||||||
|
|
||||||
- Raspberry Pi OS Lite 32-bit for maximum RAM economy and stability on 1 GB RAM
|
|
||||||
- Raspberry Pi OS Lite 64-bit can be tested later if specific ARM64 packages are needed
|
|
||||||
|
|
||||||
## Core components
|
|
||||||
|
|
||||||
```text
|
|
||||||
website widget -> VPS FastPanel/Nginx/API proxy -> WireGuard -> Raspberry Pi backend -> SQLite -> Telegram bot -> operators
|
|
||||||
|
|
||||||
VPS also serves:
|
|
||||||
- admin panel
|
|
||||||
- widget.js
|
|
||||||
- static assets
|
|
||||||
```
|
|
||||||
|
|
||||||
## MVP modules
|
|
||||||
|
|
||||||
- Backend API
|
|
||||||
- WebSocket gateway
|
|
||||||
- Telegram bot bridge
|
|
||||||
- Embeddable website widget
|
|
||||||
- Web admin panel
|
|
||||||
- SQLite storage
|
|
||||||
- Operator/site access rules
|
|
||||||
- SOCKS5 proxy settings for Telegram connectivity
|
|
||||||
- Frontend deployment management from admin panel
|
|
||||||
- FastPanel-safe frontend publishing on VPS
|
|
||||||
|
|
||||||
## Required admin settings
|
|
||||||
|
|
||||||
### Telegram bot
|
|
||||||
|
|
||||||
- Bot token
|
|
||||||
- Webhook or polling mode
|
|
||||||
- Allowed operators
|
|
||||||
- Operator-to-site mapping
|
|
||||||
|
|
||||||
### SOCKS5 proxy
|
|
||||||
|
|
||||||
The system must support optional SOCKS5 configuration for Telegram requests:
|
|
||||||
|
|
||||||
```env
|
|
||||||
TELEGRAM_PROXY_ENABLED=false
|
|
||||||
TELEGRAM_PROXY_TYPE=socks5
|
|
||||||
TELEGRAM_PROXY_HOST=127.0.0.1
|
|
||||||
TELEGRAM_PROXY_PORT=9050
|
|
||||||
TELEGRAM_PROXY_USERNAME=
|
|
||||||
TELEGRAM_PROXY_PASSWORD=
|
|
||||||
```
|
|
||||||
|
|
||||||
Admin panel should expose:
|
|
||||||
|
|
||||||
- Enable/disable SOCKS5
|
|
||||||
- Proxy host
|
|
||||||
- Proxy port
|
|
||||||
- Username
|
|
||||||
- Password
|
|
||||||
- Test connection button
|
|
||||||
|
|
||||||
Sensitive fields must be stored encrypted or kept in environment variables for MVP.
|
|
||||||
|
|
||||||
### FastPanel-safe frontend hosting
|
|
||||||
|
|
||||||
The frontend server uses FastPanel. The project deployment must not break, overwrite, restart, or bypass FastPanel-managed services.
|
|
||||||
|
|
||||||
Hard rules:
|
|
||||||
|
|
||||||
- Do not edit global FastPanel configs directly
|
|
||||||
- Do not overwrite `/etc/nginx/nginx.conf`
|
|
||||||
- Do not overwrite FastPanel-generated virtual host configs
|
|
||||||
- Do not run broad `systemctl restart nginx` from the deploy script
|
|
||||||
- Do not install packages that replace FastPanel web stack components
|
|
||||||
- Do not run frontend as root
|
|
||||||
- Do not bind frontend services to ports `80` or `443`
|
|
||||||
- Prefer static build publishing into a FastPanel-created site directory
|
|
||||||
- Use `nginx -t` before any reload if reload is unavoidable
|
|
||||||
- Prefer no reload at all for static frontend updates
|
|
||||||
|
|
||||||
Recommended FastPanel model:
|
|
||||||
|
|
||||||
```text
|
|
||||||
FastPanel creates domains/sites:
|
|
||||||
- admin.example.ru
|
|
||||||
- widget.example.ru
|
|
||||||
- api.example.ru
|
|
||||||
|
|
||||||
Deploy script only updates files inside the allowed web root:
|
|
||||||
- admin panel build files
|
|
||||||
- widget.js
|
|
||||||
- widget assets
|
|
||||||
```
|
|
||||||
|
|
||||||
Recommended FastPanel-safe paths:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/var/www/<fastpanel-user>/data/www/admin.example.ru
|
|
||||||
/var/www/<fastpanel-user>/data/www/widget.example.ru
|
|
||||||
/opt/raspi-chat/source
|
|
||||||
/opt/raspi-chat/releases/<timestamp>
|
|
||||||
/opt/raspi-chat/current -> /opt/raspi-chat/releases/<timestamp>
|
|
||||||
```
|
|
||||||
|
|
||||||
Deployment should copy or rsync built static files into the FastPanel site directories:
|
|
||||||
|
|
||||||
```text
|
|
||||||
admin-panel/dist/* -> /var/www/<fastpanel-user>/data/www/admin.example.ru/
|
|
||||||
widget/dist/* -> /var/www/<fastpanel-user>/data/www/widget.example.ru/
|
|
||||||
```
|
|
||||||
|
|
||||||
The API reverse proxy for `api.example.ru` should be configured through FastPanel custom Nginx directives if available, or through a separate include file that FastPanel will not overwrite.
|
|
||||||
|
|
||||||
FastPanel compatibility must be treated as a deployment requirement, not an afterthought.
|
|
||||||
|
|
||||||
### Frontend deployment updates
|
|
||||||
|
|
||||||
The admin panel must include a deployment section for updating the VPS-hosted frontend.
|
|
||||||
|
|
||||||
Required modes:
|
|
||||||
|
|
||||||
1. Manual update by button
|
|
||||||
2. Automatic update by webhook from GitHub
|
|
||||||
3. Optional scheduled update check
|
|
||||||
|
|
||||||
Admin panel should expose:
|
|
||||||
|
|
||||||
- Current frontend version
|
|
||||||
- Current commit hash
|
|
||||||
- Last deployment time
|
|
||||||
- Last deployment status
|
|
||||||
- Update branch, default: `main`
|
|
||||||
- Button: `Check for updates`
|
|
||||||
- Button: `Update frontend now`
|
|
||||||
- Deployment logs
|
|
||||||
- Rollback to previous frontend build
|
|
||||||
- Lock to prevent parallel deployments
|
|
||||||
- FastPanel compatibility status
|
|
||||||
- Target FastPanel web root paths
|
|
||||||
|
|
||||||
Frontend deployment flow:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Admin clicks update button
|
|
||||||
-> backend validates admin permissions
|
|
||||||
-> backend calls deploy agent on VPS
|
|
||||||
-> VPS pulls latest repository changes
|
|
||||||
-> VPS builds admin-panel and widget
|
|
||||||
-> VPS verifies FastPanel-safe target paths
|
|
||||||
-> VPS publishes new static build atomically
|
|
||||||
-> backend stores deployment result
|
|
||||||
-> admin panel shows status and logs
|
|
||||||
```
|
|
||||||
|
|
||||||
Recommended deploy command on VPS:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git fetch origin main
|
npm install
|
||||||
npm ci
|
cp backend/.env.example backend/.env # заполнить значения
|
||||||
npm run build --workspace admin-panel
|
npm run dev:backend # node --watch backend/src/server.js
|
||||||
npm run build --workspace widget
|
npm run dev:admin # Vite, админка
|
||||||
|
npm --workspace widget run dev # Vite, виджет на порту 5174
|
||||||
```
|
```
|
||||||
|
|
||||||
Publishing must be atomic and FastPanel-safe:
|
Сборка фронтенда:
|
||||||
|
|
||||||
```text
|
```bash
|
||||||
build new release directory
|
npm run build # build:admin + build:widget
|
||||||
verify build artifacts
|
|
||||||
verify target directories are inside allowed FastPanel web roots
|
|
||||||
copy files with rsync --delete only inside those roots
|
|
||||||
never delete parent web root directories
|
|
||||||
never touch FastPanel system configs
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Admin deployment permissions:
|
Отдельных миграций нет: схема SQLite создаётся функцией `migrate()` при старте бэкенда, база и каталог создаются автоматически по `DATABASE_PATH`.
|
||||||
|
|
||||||
- Only users with role `admin` can trigger frontend updates
|
Установка на VPS (скрипт ставит пакеты, Node.js, PM2, собирает фронтенд и поднимает бэкенд под PM2):
|
||||||
- Deployment endpoint must require JWT auth
|
|
||||||
- Deployment webhook must require secret token validation
|
|
||||||
- All deployment attempts must be logged
|
|
||||||
|
|
||||||
Environment variables:
|
```bash
|
||||||
|
cp deploy/vps/.env.example deploy/vps/.env
|
||||||
```env
|
sudo bash deploy/vps/install.sh
|
||||||
FRONTEND_DEPLOY_ENABLED=true
|
|
||||||
FRONTEND_DEPLOY_MODE=local-vps
|
|
||||||
FRONTEND_DEPLOY_BRANCH=main
|
|
||||||
FRONTEND_DEPLOY_SOURCE_PATH=/opt/raspi-chat/source
|
|
||||||
FRONTEND_DEPLOY_RELEASES_PATH=/opt/raspi-chat/releases
|
|
||||||
FRONTEND_DEPLOY_ADMIN_WEBROOT=/var/www/example_user/data/www/admin.example.ru
|
|
||||||
FRONTEND_DEPLOY_WIDGET_WEBROOT=/var/www/example_user/data/www/widget.example.ru
|
|
||||||
FRONTEND_DEPLOY_WEBHOOK_SECRET=
|
|
||||||
FASTPANEL_SAFE_MODE=true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
MVP implementation should run the deployment agent directly on the VPS. The deploy agent must have permissions only for the project source, release directory, and specific FastPanel web roots.
|
Публикация фронтенда в webroot FastPanel:
|
||||||
|
|
||||||
## Website widget
|
```bash
|
||||||
|
npm run deploy:frontend # deploy/deploy-agent, требует свой .env
|
||||||
|
```
|
||||||
|
|
||||||
Example embed code:
|
Проверка:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s http://127.0.0.1:3000/health
|
||||||
|
pm2 logs wschat-backend --lines 100
|
||||||
|
```
|
||||||
|
|
||||||
|
Встраивание виджета на сайт:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://widget.example.ru/widget.js" data-site-id="site_xxxxx"></script>
|
<script src="https://widget.example.ru/widget.js"
|
||||||
|
data-site-id="site_xxxxx"
|
||||||
|
data-api-url="https://api.example.ru"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
The widget must connect to the public API endpoint on VPS:
|
## Конфигурация
|
||||||
|
|
||||||
```text
|
### `backend/.env`
|
||||||
https://api.example.ru
|
|
||||||
wss://api.example.ru/ws
|
|
||||||
```
|
|
||||||
|
|
||||||
## Message flow
|
| Переменная | Назначение | Пример |
|
||||||
|
|---|---|---|
|
||||||
|
| `APP_ENV` | Режим работы; в `production` меняется путь к базе по умолчанию и отключается pino-pretty | `production` |
|
||||||
|
| `APP_HOST` | Адрес прослушивания бэкенда | `127.0.0.1` |
|
||||||
|
| `APP_PORT` | Порт бэкенда | `3000` |
|
||||||
|
| `PUBLIC_API_URL` | Публичный URL API, отдаётся виджету через `/api/config/public` | `https://api.example.ru` |
|
||||||
|
| `PUBLIC_WS_URL` | Публичный WebSocket URL | `wss://api.example.ru/ws` |
|
||||||
|
| `TRUST_PROXY` | Доверять заголовкам reverse proxy | `true` |
|
||||||
|
| `DATABASE_PATH` | Путь к файлу SQLite | `/opt/ws-chat/data/chat.sqlite` |
|
||||||
|
| `ADMIN_ORIGIN` | Origin админки для CORS | `https://admin.example.ru` |
|
||||||
|
| `WIDGET_ORIGIN` | Origin виджета для CORS и домен сайта по умолчанию | `https://widget.example.ru` |
|
||||||
|
| `TELEGRAM_BOT_TOKEN` | Токен бота; при первом старте копируется в таблицу `settings`, дальше редактируется из админки | см. `.env` |
|
||||||
|
| `TELEGRAM_PROXY_ENABLED` | Включить SOCKS5 для Telegram | `false` |
|
||||||
|
| `TELEGRAM_PROXY_TYPE` | Тип прокси; в коде поддерживается только `socks5` | `socks5` |
|
||||||
|
| `TELEGRAM_PROXY_HOST` / `TELEGRAM_PROXY_PORT` | Адрес и порт прокси | `127.0.0.1` / `9050` |
|
||||||
|
| `TELEGRAM_PROXY_USERNAME` / `TELEGRAM_PROXY_PASSWORD` | Учётные данные прокси | см. `.env` |
|
||||||
|
| `JWT_SECRET` | Объявлен в конфиге, но нигде не используется — авторизации нет | см. `.env` |
|
||||||
|
| `FRONTEND_DEPLOY_ENABLED`, `FRONTEND_DEPLOY_MODE`, `FASTPANEL_SAFE_MODE` | Объявлены в `.env.example`, бэкендом не читаются | `false` |
|
||||||
|
|
||||||
```text
|
Приоритет источников: значения Telegram/SOCKS5 после первого запуска хранятся в таблице `settings` SQLite и правятся через админку; `.env` задаёт только начальные значения.
|
||||||
Visitor sends message on website
|
|
||||||
-> widget sends message to VPS api.example.ru
|
|
||||||
-> VPS proxies request through WireGuard to Raspberry Pi backend
|
|
||||||
-> backend validates site_id and origin domain
|
|
||||||
-> backend stores message
|
|
||||||
-> backend finds active operators assigned to this site
|
|
||||||
-> Telegram bot sends message only to those operators
|
|
||||||
-> operator replies in Telegram
|
|
||||||
-> backend maps reply to conversation
|
|
||||||
-> message is delivered back to website widget through WebSocket
|
|
||||||
```
|
|
||||||
|
|
||||||
## Future Android app
|
### `deploy/vps/.env`
|
||||||
|
|
||||||
The backend must expose stable REST and WebSocket APIs so an Android app can later work as another operator interface.
|
`PROJECT_ROOT`, `SOURCE_PATH`, `DATA_PATH`, `LOGS_PATH`, `BACKUPS_PATH`, `UPDATES_PATH`, `ADMIN_WEBROOT`, `WIDGET_WEBROOT`, `BACKEND_HOST`, `BACKEND_PORT`, `PUBLIC_API_URL`, `PUBLIC_WS_URL`, `FASTPANEL_SAFE_MODE`, `PM2_PROCESS_NAME`, `NODE_MAJOR`.
|
||||||
|
|
||||||
Planned Android-ready API concepts:
|
### `deploy/deploy-agent/.env`
|
||||||
|
|
||||||
- JWT auth
|
`FRONTEND_DEPLOY_BRANCH`, `FRONTEND_DEPLOY_SOURCE_PATH`, `FRONTEND_DEPLOY_ADMIN_WEBROOT`, `FRONTEND_DEPLOY_WIDGET_WEBROOT`, `FASTPANEL_SAFE_MODE`. При `FASTPANEL_SAFE_MODE != false` webroot обязан лежать внутри `/var/www/<user>/data/www/<domain>`, иначе деплой прерывается.
|
||||||
- refresh tokens
|
|
||||||
- operator sessions
|
|
||||||
- conversation list
|
|
||||||
- message history
|
|
||||||
- push-ready notification events
|
|
||||||
- WebSocket live updates
|
|
||||||
|
|
||||||
## Initial stack
|
## Состояние
|
||||||
|
|
||||||
- Node.js
|
Рабочий MVP, разработка остановлена. 106 коммитов, все от 2026-05-08, последний коммит — 2026-05-08. По записям `.sw` система была развёрнута и работала: виджет и админка на `widget.stackworks.ru`, API на `api.stackworks.ru`, бэкенд под PM2, SQLite в `/opt/ws-chat/data/chat.sqlite`.
|
||||||
- Fastify
|
|
||||||
- WebSocket
|
|
||||||
- SQLite
|
|
||||||
- React + Vite admin panel
|
|
||||||
- Vanilla JS widget
|
|
||||||
- Telegram Bot API
|
|
||||||
- WireGuard
|
|
||||||
- FastPanel-managed web server on VPS
|
|
||||||
- PM2 preferred for Raspberry Pi 3B MVP
|
|
||||||
|
|
||||||
## Development phases
|
Сквозной сценарий реализован полностью: виджет → API → Telegram-оператор → ответ → WebSocket → виджет. Управление сайтами, операторами и настройками Telegram/SOCKS5 работает из админки.
|
||||||
|
|
||||||
### Phase 1
|
Raspberry Pi (изначальная цель проекта, см. `README.upstream.md` и `docs/RASPBERRY_PI.md`) из MVP исключён — в `.sw` указана причина: нестабильность Node.js/ОС на Pi.
|
||||||
|
|
||||||
- Website widget
|
## Что не доделано
|
||||||
- Backend API
|
|
||||||
- Telegram message forwarding
|
|
||||||
- Reply from Telegram back to website
|
|
||||||
- SQLite persistence
|
|
||||||
|
|
||||||
### Phase 2
|
Явных `TODO`/`FIXME` в коде нет; список ниже собран из кода и раздела «Current next steps» в `.sw`.
|
||||||
|
|
||||||
- Admin login
|
- Нет авторизации в админ-панели. Все эндпоинты `/api/admin/*` открыты без проверки; `JWT_SECRET` объявлен, но не используется. Это главный незакрытый риск, зафиксированный и в самом `.sw`.
|
||||||
- Site management
|
- Нет страницы диалогов в админке: есть только лента последних сообщений, нельзя открыть переписку целиком.
|
||||||
- Operator management
|
- Не реализованы статусы диалогов (`open`/`closed`) и назначение оператора «взять в работу» — поля `status` и `assigned_operator_id` в БД есть, UI и API для них нет.
|
||||||
- Site/operator permissions
|
- Нет удаления/редактирования сайтов и операторов: реализованы только `GET`/`POST` сайтов и привязка/отвязка операторов.
|
||||||
- Widget embed code generator
|
- Не реализована обещанная в ТЗ система деплоя из админки: нет ни кнопки обновления, ни GitHub-вебхука, ни откатов, ни логов деплоя. Есть только CLI-агент `deploy-frontend.js`.
|
||||||
- SOCKS5 proxy settings
|
- `test-proxy` не проверяет соединение — функция `validateSocks5Settings` только валидирует поля формы.
|
||||||
|
- Нет офлайн-режима (сбор имени/телефона/email посетителя), звуковых уведомлений и счётчиков непрочитанного.
|
||||||
### Phase 3
|
- Нет кастомизации виджета из админки (заголовок, цвет, позиция) — параметры зашиты в `widget.js`.
|
||||||
|
- Нет тестов и CI: тестовых файлов, конфигов линтера и workflow в репозитории нет.
|
||||||
- FastPanel-safe VPS frontend deployment scripts
|
- Планы, отмеченные в `.sw` как отложенные: перенос админки на отдельный поддомен, переход с SQLite на PostgreSQL, Docker Compose/установщик, JWT и API под будущее Android-приложение.
|
||||||
- Admin button for frontend update
|
|
||||||
- Deployment logs
|
|
||||||
- GitHub webhook auto-update
|
|
||||||
- Frontend rollback support
|
|
||||||
|
|
||||||
### Phase 4
|
|
||||||
|
|
||||||
- Conversation history
|
|
||||||
- Dialog statuses
|
|
||||||
- Rate limiting
|
|
||||||
- Origin/domain validation
|
|
||||||
- Backup script
|
|
||||||
- Deployment guide for Raspberry Pi, VPS, FastPanel, and WireGuard
|
|
||||||
|
|
||||||
### Phase 5
|
|
||||||
|
|
||||||
- Android app API preparation
|
|
||||||
- Push notification model
|
|
||||||
- Multi-device operator sessions
|
|
||||||
|
|||||||
@@ -0,0 +1,317 @@
|
|||||||
|
# Raspi Telegram Live Chat
|
||||||
|
|
||||||
|
Self-hosted live chat system for Raspberry Pi with embeddable website widget, web admin panel, Telegram as the operator interface, and a separate VPS-hosted frontend.
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Build a lightweight Jivo-like chat platform where visitors write through a website widget and only Telegram operators configured in the admin panel receive and answer messages.
|
||||||
|
|
||||||
|
## Target deployment
|
||||||
|
|
||||||
|
Primary target for MVP:
|
||||||
|
|
||||||
|
- Raspberry Pi 3 Model B at home
|
||||||
|
- Raspberry Pi OS Lite 32-bit
|
||||||
|
- Backend API on Raspberry Pi
|
||||||
|
- Telegram bot on Raspberry Pi
|
||||||
|
- SQLite database on Raspberry Pi
|
||||||
|
- VPS with FastPanel for admin panel, widget.js, static assets, HTTPS, and public reverse proxy
|
||||||
|
- WireGuard between VPS and Raspberry Pi
|
||||||
|
- Domain/site management through FastPanel where possible
|
||||||
|
|
||||||
|
Cloudflare must not be required for this project.
|
||||||
|
|
||||||
|
Recommended OS for Raspberry Pi 3B MVP:
|
||||||
|
|
||||||
|
- Raspberry Pi OS Lite 32-bit for maximum RAM economy and stability on 1 GB RAM
|
||||||
|
- Raspberry Pi OS Lite 64-bit can be tested later if specific ARM64 packages are needed
|
||||||
|
|
||||||
|
## Core components
|
||||||
|
|
||||||
|
```text
|
||||||
|
website widget -> VPS FastPanel/Nginx/API proxy -> WireGuard -> Raspberry Pi backend -> SQLite -> Telegram bot -> operators
|
||||||
|
|
||||||
|
VPS also serves:
|
||||||
|
- admin panel
|
||||||
|
- widget.js
|
||||||
|
- static assets
|
||||||
|
```
|
||||||
|
|
||||||
|
## MVP modules
|
||||||
|
|
||||||
|
- Backend API
|
||||||
|
- WebSocket gateway
|
||||||
|
- Telegram bot bridge
|
||||||
|
- Embeddable website widget
|
||||||
|
- Web admin panel
|
||||||
|
- SQLite storage
|
||||||
|
- Operator/site access rules
|
||||||
|
- SOCKS5 proxy settings for Telegram connectivity
|
||||||
|
- Frontend deployment management from admin panel
|
||||||
|
- FastPanel-safe frontend publishing on VPS
|
||||||
|
|
||||||
|
## Required admin settings
|
||||||
|
|
||||||
|
### Telegram bot
|
||||||
|
|
||||||
|
- Bot token
|
||||||
|
- Webhook or polling mode
|
||||||
|
- Allowed operators
|
||||||
|
- Operator-to-site mapping
|
||||||
|
|
||||||
|
### SOCKS5 proxy
|
||||||
|
|
||||||
|
The system must support optional SOCKS5 configuration for Telegram requests:
|
||||||
|
|
||||||
|
```env
|
||||||
|
TELEGRAM_PROXY_ENABLED=false
|
||||||
|
TELEGRAM_PROXY_TYPE=socks5
|
||||||
|
TELEGRAM_PROXY_HOST=127.0.0.1
|
||||||
|
TELEGRAM_PROXY_PORT=9050
|
||||||
|
TELEGRAM_PROXY_USERNAME=
|
||||||
|
TELEGRAM_PROXY_PASSWORD=
|
||||||
|
```
|
||||||
|
|
||||||
|
Admin panel should expose:
|
||||||
|
|
||||||
|
- Enable/disable SOCKS5
|
||||||
|
- Proxy host
|
||||||
|
- Proxy port
|
||||||
|
- Username
|
||||||
|
- Password
|
||||||
|
- Test connection button
|
||||||
|
|
||||||
|
Sensitive fields must be stored encrypted or kept in environment variables for MVP.
|
||||||
|
|
||||||
|
### FastPanel-safe frontend hosting
|
||||||
|
|
||||||
|
The frontend server uses FastPanel. The project deployment must not break, overwrite, restart, or bypass FastPanel-managed services.
|
||||||
|
|
||||||
|
Hard rules:
|
||||||
|
|
||||||
|
- Do not edit global FastPanel configs directly
|
||||||
|
- Do not overwrite `/etc/nginx/nginx.conf`
|
||||||
|
- Do not overwrite FastPanel-generated virtual host configs
|
||||||
|
- Do not run broad `systemctl restart nginx` from the deploy script
|
||||||
|
- Do not install packages that replace FastPanel web stack components
|
||||||
|
- Do not run frontend as root
|
||||||
|
- Do not bind frontend services to ports `80` or `443`
|
||||||
|
- Prefer static build publishing into a FastPanel-created site directory
|
||||||
|
- Use `nginx -t` before any reload if reload is unavoidable
|
||||||
|
- Prefer no reload at all for static frontend updates
|
||||||
|
|
||||||
|
Recommended FastPanel model:
|
||||||
|
|
||||||
|
```text
|
||||||
|
FastPanel creates domains/sites:
|
||||||
|
- admin.example.ru
|
||||||
|
- widget.example.ru
|
||||||
|
- api.example.ru
|
||||||
|
|
||||||
|
Deploy script only updates files inside the allowed web root:
|
||||||
|
- admin panel build files
|
||||||
|
- widget.js
|
||||||
|
- widget assets
|
||||||
|
```
|
||||||
|
|
||||||
|
Recommended FastPanel-safe paths:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/var/www/<fastpanel-user>/data/www/admin.example.ru
|
||||||
|
/var/www/<fastpanel-user>/data/www/widget.example.ru
|
||||||
|
/opt/raspi-chat/source
|
||||||
|
/opt/raspi-chat/releases/<timestamp>
|
||||||
|
/opt/raspi-chat/current -> /opt/raspi-chat/releases/<timestamp>
|
||||||
|
```
|
||||||
|
|
||||||
|
Deployment should copy or rsync built static files into the FastPanel site directories:
|
||||||
|
|
||||||
|
```text
|
||||||
|
admin-panel/dist/* -> /var/www/<fastpanel-user>/data/www/admin.example.ru/
|
||||||
|
widget/dist/* -> /var/www/<fastpanel-user>/data/www/widget.example.ru/
|
||||||
|
```
|
||||||
|
|
||||||
|
The API reverse proxy for `api.example.ru` should be configured through FastPanel custom Nginx directives if available, or through a separate include file that FastPanel will not overwrite.
|
||||||
|
|
||||||
|
FastPanel compatibility must be treated as a deployment requirement, not an afterthought.
|
||||||
|
|
||||||
|
### Frontend deployment updates
|
||||||
|
|
||||||
|
The admin panel must include a deployment section for updating the VPS-hosted frontend.
|
||||||
|
|
||||||
|
Required modes:
|
||||||
|
|
||||||
|
1. Manual update by button
|
||||||
|
2. Automatic update by webhook from GitHub
|
||||||
|
3. Optional scheduled update check
|
||||||
|
|
||||||
|
Admin panel should expose:
|
||||||
|
|
||||||
|
- Current frontend version
|
||||||
|
- Current commit hash
|
||||||
|
- Last deployment time
|
||||||
|
- Last deployment status
|
||||||
|
- Update branch, default: `main`
|
||||||
|
- Button: `Check for updates`
|
||||||
|
- Button: `Update frontend now`
|
||||||
|
- Deployment logs
|
||||||
|
- Rollback to previous frontend build
|
||||||
|
- Lock to prevent parallel deployments
|
||||||
|
- FastPanel compatibility status
|
||||||
|
- Target FastPanel web root paths
|
||||||
|
|
||||||
|
Frontend deployment flow:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Admin clicks update button
|
||||||
|
-> backend validates admin permissions
|
||||||
|
-> backend calls deploy agent on VPS
|
||||||
|
-> VPS pulls latest repository changes
|
||||||
|
-> VPS builds admin-panel and widget
|
||||||
|
-> VPS verifies FastPanel-safe target paths
|
||||||
|
-> VPS publishes new static build atomically
|
||||||
|
-> backend stores deployment result
|
||||||
|
-> admin panel shows status and logs
|
||||||
|
```
|
||||||
|
|
||||||
|
Recommended deploy command on VPS:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git fetch origin main
|
||||||
|
npm ci
|
||||||
|
npm run build --workspace admin-panel
|
||||||
|
npm run build --workspace widget
|
||||||
|
```
|
||||||
|
|
||||||
|
Publishing must be atomic and FastPanel-safe:
|
||||||
|
|
||||||
|
```text
|
||||||
|
build new release directory
|
||||||
|
verify build artifacts
|
||||||
|
verify target directories are inside allowed FastPanel web roots
|
||||||
|
copy files with rsync --delete only inside those roots
|
||||||
|
never delete parent web root directories
|
||||||
|
never touch FastPanel system configs
|
||||||
|
```
|
||||||
|
|
||||||
|
Admin deployment permissions:
|
||||||
|
|
||||||
|
- Only users with role `admin` can trigger frontend updates
|
||||||
|
- Deployment endpoint must require JWT auth
|
||||||
|
- Deployment webhook must require secret token validation
|
||||||
|
- All deployment attempts must be logged
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
|
||||||
|
```env
|
||||||
|
FRONTEND_DEPLOY_ENABLED=true
|
||||||
|
FRONTEND_DEPLOY_MODE=local-vps
|
||||||
|
FRONTEND_DEPLOY_BRANCH=main
|
||||||
|
FRONTEND_DEPLOY_SOURCE_PATH=/opt/raspi-chat/source
|
||||||
|
FRONTEND_DEPLOY_RELEASES_PATH=/opt/raspi-chat/releases
|
||||||
|
FRONTEND_DEPLOY_ADMIN_WEBROOT=/var/www/example_user/data/www/admin.example.ru
|
||||||
|
FRONTEND_DEPLOY_WIDGET_WEBROOT=/var/www/example_user/data/www/widget.example.ru
|
||||||
|
FRONTEND_DEPLOY_WEBHOOK_SECRET=
|
||||||
|
FASTPANEL_SAFE_MODE=true
|
||||||
|
```
|
||||||
|
|
||||||
|
MVP implementation should run the deployment agent directly on the VPS. The deploy agent must have permissions only for the project source, release directory, and specific FastPanel web roots.
|
||||||
|
|
||||||
|
## Website widget
|
||||||
|
|
||||||
|
Example embed code:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="https://widget.example.ru/widget.js" data-site-id="site_xxxxx"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
The widget must connect to the public API endpoint on VPS:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://api.example.ru
|
||||||
|
wss://api.example.ru/ws
|
||||||
|
```
|
||||||
|
|
||||||
|
## Message flow
|
||||||
|
|
||||||
|
```text
|
||||||
|
Visitor sends message on website
|
||||||
|
-> widget sends message to VPS api.example.ru
|
||||||
|
-> VPS proxies request through WireGuard to Raspberry Pi backend
|
||||||
|
-> backend validates site_id and origin domain
|
||||||
|
-> backend stores message
|
||||||
|
-> backend finds active operators assigned to this site
|
||||||
|
-> Telegram bot sends message only to those operators
|
||||||
|
-> operator replies in Telegram
|
||||||
|
-> backend maps reply to conversation
|
||||||
|
-> message is delivered back to website widget through WebSocket
|
||||||
|
```
|
||||||
|
|
||||||
|
## Future Android app
|
||||||
|
|
||||||
|
The backend must expose stable REST and WebSocket APIs so an Android app can later work as another operator interface.
|
||||||
|
|
||||||
|
Planned Android-ready API concepts:
|
||||||
|
|
||||||
|
- JWT auth
|
||||||
|
- refresh tokens
|
||||||
|
- operator sessions
|
||||||
|
- conversation list
|
||||||
|
- message history
|
||||||
|
- push-ready notification events
|
||||||
|
- WebSocket live updates
|
||||||
|
|
||||||
|
## Initial stack
|
||||||
|
|
||||||
|
- Node.js
|
||||||
|
- Fastify
|
||||||
|
- WebSocket
|
||||||
|
- SQLite
|
||||||
|
- React + Vite admin panel
|
||||||
|
- Vanilla JS widget
|
||||||
|
- Telegram Bot API
|
||||||
|
- WireGuard
|
||||||
|
- FastPanel-managed web server on VPS
|
||||||
|
- PM2 preferred for Raspberry Pi 3B MVP
|
||||||
|
|
||||||
|
## Development phases
|
||||||
|
|
||||||
|
### Phase 1
|
||||||
|
|
||||||
|
- Website widget
|
||||||
|
- Backend API
|
||||||
|
- Telegram message forwarding
|
||||||
|
- Reply from Telegram back to website
|
||||||
|
- SQLite persistence
|
||||||
|
|
||||||
|
### Phase 2
|
||||||
|
|
||||||
|
- Admin login
|
||||||
|
- Site management
|
||||||
|
- Operator management
|
||||||
|
- Site/operator permissions
|
||||||
|
- Widget embed code generator
|
||||||
|
- SOCKS5 proxy settings
|
||||||
|
|
||||||
|
### Phase 3
|
||||||
|
|
||||||
|
- FastPanel-safe VPS frontend deployment scripts
|
||||||
|
- Admin button for frontend update
|
||||||
|
- Deployment logs
|
||||||
|
- GitHub webhook auto-update
|
||||||
|
- Frontend rollback support
|
||||||
|
|
||||||
|
### Phase 4
|
||||||
|
|
||||||
|
- Conversation history
|
||||||
|
- Dialog statuses
|
||||||
|
- Rate limiting
|
||||||
|
- Origin/domain validation
|
||||||
|
- Backup script
|
||||||
|
- Deployment guide for Raspberry Pi, VPS, FastPanel, and WireGuard
|
||||||
|
|
||||||
|
### Phase 5
|
||||||
|
|
||||||
|
- Android app API preparation
|
||||||
|
- Push notification model
|
||||||
|
- Multi-device operator sessions
|
||||||
Ссылка в новой задаче
Block a user