docs: add deployment guides, audit reports, and production sync scripts
- BRAINYCP_DEPLOY_GUIDE.md: complete human deployment guide - AI_DEPLOY_CONTEXT.md: machine-readable deploy instructions for AI agents - sync-production.sh: universal deployment script (full/quick/status/logs/backup) - DEPLOY_PLAN.md: step-by-step deployment plan - DEPLOY_AUDIT_REPORT.md: server audit results - MIGRATION_AUDIT_REPORT.md: MySQL migration complexity analysis - SERVER_AUDIT_REPORT.md: server environment audit - Update README.md with BrainyCP deploy workflow and Git sync instructions Refs: production server 46.175.149.131, domain tenerifeprop.es
This commit is contained in:
214
DEPLOY_AUDIT_REPORT.md
Normal file
214
DEPLOY_AUDIT_REPORT.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Отчёт об аудите проекта TenerifeProp
|
||||
|
||||
## Дата аудита: 2026-05-13
|
||||
|
||||
## 1. Архитектура проекта
|
||||
|
||||
### Стек проекта
|
||||
| Компонент | Реализация |
|
||||
|-----------|-----------|
|
||||
| **Runtime** | Bun (1.1.0) |
|
||||
| **HTTP Framework** | Hono v4.0 |
|
||||
| **База данных** | SQLite (через `bun:sqlite`) — WAL mode |
|
||||
| **Статика** | `serveStatic` из `hono/bun` |
|
||||
| **Auth** | Сессии в SQLite, bcrypt через Bun.password.hashSync |
|
||||
| **Rate Limit** | In-memory Map |
|
||||
| **API** | REST JSON, Hono middleware (cors, logger, csrf) |
|
||||
|
||||
### Критические зависимости от Bun
|
||||
```
|
||||
import { Database } from 'bun:sqlite'
|
||||
import { serveStatic } from 'hono/bun'
|
||||
Bun.password.hashSync(...) // Строка 583
|
||||
Bun.password.verify(...) // Ожидается в auth
|
||||
```
|
||||
|
||||
**Bun является обязательным runtime.** Node.js НЕ может запустить этот код без переписывания:
|
||||
- `bun:sqlite` → `better-sqlite3`
|
||||
- `hono/bun` → `hono/node-server`
|
||||
- `Bun.password` → `bcrypt`
|
||||
|
||||
### Структура данных
|
||||
База данных SQLite содержит таблицы:
|
||||
- `properties` — объекты недвижимости (поля title_es/title_ru, images JSON, geolocation)
|
||||
- `leads` — заявки клиентов
|
||||
- `testimonials` — отзывы
|
||||
- `faq` — вопросы/ответы
|
||||
- `services` — услуги
|
||||
- `settings` — настройки сайта
|
||||
- `users` — пользователи админки
|
||||
- `sessions` — авторизационные сессии
|
||||
- `analytics_events` / `analytics_daily` — аналитика
|
||||
|
||||
### API Endpoints
|
||||
```
|
||||
GET /api/properties — список объектов (с фильтрами)
|
||||
GET /api/properties/featured — избранные объекты
|
||||
GET /api/properties/:slug — детальная страница
|
||||
POST /api/leads — создание заявки
|
||||
GET /api/testimonials — отзывы
|
||||
GET /api/faq — FAQ
|
||||
GET /api/services — услуги
|
||||
GET /api/settings — настройки сайта
|
||||
GET /api/cities — список городов
|
||||
GET /api/stats — статистика
|
||||
POST /api/analytics/event — трекинг событий
|
||||
POST /api/auth/login — вход в админку
|
||||
POST /api/auth/logout — выход
|
||||
```
|
||||
|
||||
### Админ панель
|
||||
Путь: `/admin` — SPA с HTML-страницами (`public/admin/*.html`)
|
||||
|
||||
## 2. Архитектура сервера (BrainyCP)
|
||||
|
||||
### Обнаруженная конфигурация
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| **OS** | Ubuntu 22.04 LTS |
|
||||
| **IP** | 46.175.149.131 |
|
||||
| **Панель** | BrainyCP |
|
||||
| **Пользователь** | nero (uid=1002) |
|
||||
| **Web-сервер** | Nginx 1.27.0 |
|
||||
| **SSL** | Let's Encrypt (активен) |
|
||||
| **PHP** | 5.2–8.3 (множество версий, не используется) |
|
||||
| **Node.js** | v20.10.0 (установлен BrainyCP, `/home/nero/usr/bin/node`) |
|
||||
| **Порт** | 3003 (занят заглушкой) |
|
||||
|
||||
### Nginx конфигурация
|
||||
BrainyCP настроила два vhost:
|
||||
- **HTTP**: `tenerifeprop.es:80` → `proxy_pass http://46.175.149.131:3003`
|
||||
- **HTTPS**: `tenerifeprop.es:443` → `proxy_pass http://46.175.149.131:3003` + SSL
|
||||
|
||||
Проксирование уже работает. Nginx терминирует SSL и отправляет HTTP к backend.
|
||||
|
||||
### Systemd unit
|
||||
```
|
||||
nodejs@3003.service — запускает /home/nero/usr/bin/node index.js
|
||||
WorkingDirectory: /home/nero/sites/tenerifeprop.es
|
||||
Environment: NODE_PORT=3003
|
||||
Статус: active (running)
|
||||
PID: 1233379
|
||||
```
|
||||
|
||||
## 3. Конфликт стеков
|
||||
|
||||
### BrainyCP предоставляет
|
||||
- Node.js (v20) — **работает только через кнопку "NodeJS" в панели**
|
||||
- Nginx + SSL — уже настроено
|
||||
- PHP-FPM — избыточно для этого проекта
|
||||
- Apache — избыточно
|
||||
|
||||
### Проект требует
|
||||
- **Bun runtime** — Node.js не поддерживает `bun:sqlite`, `hono/bun`, `Bun.password`
|
||||
- Порт 3003 (или другой) — свободен
|
||||
- PM2 для процесс-менеджмента
|
||||
|
||||
### Решение
|
||||
**Нужно установить Bun на сервере.** Это не конфликтует с системным Node.js — Bun устанавливается в `$HOME/.bun` и не трогает системные пакеты.
|
||||
|
||||
## 4. Файлы, необходимые для деплоя
|
||||
|
||||
### Что нужно скопировать на сервер
|
||||
```
|
||||
src/ (TypeScript код сервера)
|
||||
public/ (HTML, CSS, JS, изображения)
|
||||
data/ (SQLite база данных — если переносим)
|
||||
package.json (зависимости)
|
||||
bun.lock (lock-файл)
|
||||
.env (переменные окружения)
|
||||
```
|
||||
|
||||
### Файлы НЕ нужны
|
||||
```
|
||||
Dockerfile (не используется в production на BrainyCP)
|
||||
docker-compose.yml (не используется)
|
||||
.kilo/ (конфигурация агентов — dev-only)
|
||||
tests/ (тесты — dev-only)
|
||||
node_modules/ (установятся на сервере)
|
||||
```
|
||||
|
||||
## 5. План деплоя (пошаговый)
|
||||
|
||||
### Перед деплоем — подготовка
|
||||
1. Дамп БД: скопировать `data/tenerifeprop.db` с локального Docker
|
||||
2. Создать `.env` с production значениями:
|
||||
```
|
||||
NODE_ENV=production
|
||||
PORT=3003
|
||||
RESEND_API_KEY=
|
||||
TELEGRAM_BOT_TOKEN=
|
||||
TELEGRAM_CHAT_ID=
|
||||
```
|
||||
3. Запаковать файлы в архив или подготовить для scp
|
||||
|
||||
### На сервере (через SSH)
|
||||
```bash
|
||||
# 1. Установить Bun
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
source ~/.bashrc
|
||||
|
||||
# 2. Остановить заглушку BrainyCP
|
||||
sudo systemctl stop nodejs@3003.service
|
||||
sudo systemctl disable nodejs@3003.service
|
||||
|
||||
# 3. Очистить папку сайта (кроме .well-known для SSL)
|
||||
cd /home/nero/sites/tenerifeprop.es
|
||||
sudo rm -f index.js app.js app.css
|
||||
# Создать папки
|
||||
mkdir -p src public data
|
||||
|
||||
# 4. Загрузить файлы (с локальной машины)
|
||||
scp -r src public package.json bun.lock .env root@46.175.149.131:/home/nero/sites/tenerifeprop.es/
|
||||
# Загрузить БД (если переносим)
|
||||
scp data/tenerifeprop.db root@46.175.149.131:/home/nero/sites/tenerifeprop.es/data/
|
||||
|
||||
# 5. Установить зависимости
|
||||
bun install --production
|
||||
|
||||
# 6. Назначить права
|
||||
sudo chown -R nero:nero /home/nero/sites/tenerifeprop.es
|
||||
sudo chmod 755 /home/nero/sites/tenerifeprop.es
|
||||
sudo chmod 600 .env
|
||||
|
||||
# 7. Установить PM2
|
||||
bun add -g pm2
|
||||
|
||||
# 8. Запустить через PM2
|
||||
pm2 start "bun run src/server/index.ts" --name tenerifeprop
|
||||
pm2 save
|
||||
pm2 startup systemd
|
||||
|
||||
# 9. Проверить
|
||||
curl http://localhost:3003/api/settings
|
||||
```
|
||||
|
||||
### В BrainyCP
|
||||
- Кнопка "Перезапустить хост" в панели → НЕ нажимать (перезапустит заглушку)
|
||||
- Nginx уже настроен, SSL работает
|
||||
- Нужно только убедиться, что PM2-автозапуск настроен
|
||||
|
||||
## 6. Риски
|
||||
|
||||
| Риск | Уровень | Митигация |
|
||||
|------|---------|-----------|
|
||||
| BrainyCP может перезаписать Nginx-конфиг | Средний | Не редактировать `/etc/nginx` руками; использовать панель |
|
||||
| Обновление BrainyCP сбрасывает systemd unit | Средний | PM2 автозапуск не зависит от BrainyCP |
|
||||
| Bun не в репозиториях Ubuntu | Низкий | Устанавливается curl скриптом, обновляется `bun upgrade` |
|
||||
| SQLite WAL mode и NFS | Низкий | BrainyCP использует ext4, WAL работает |
|
||||
| Перезагрузка сервера | Низкий | PM2 + systemd обеспечат автозапуск |
|
||||
|
||||
## 7. Итог
|
||||
|
||||
**Проект готов к деплою при условии установки Bun.**
|
||||
|
||||
Текущая конфигурация BrainyCP (Nginx + SSL + порт 3003) идеально подходит под наш проект. Нужно:
|
||||
1. Установить Bun
|
||||
2. Остановить BrainyCP-заглушку
|
||||
3. Загрузить файлы проекта
|
||||
4. Запустить через PM2
|
||||
|
||||
Nginx уже проксирует домен на порт 3003 — всё будет работать сразу после запуска Bun-процесса.
|
||||
|
||||
---
|
||||
*Отчёт подготовлен после полного аудита сервера и кода проекта.*
|
||||
180
DEPLOY_PLAN.md
Normal file
180
DEPLOY_PLAN.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# План деплоя TenerifeProp на BrainyCP (v2)
|
||||
|
||||
## Условия на сервере
|
||||
- Панель: **BrainyCP**
|
||||
- Папка проекта: **уже создана** панелью (например, `/var/www/{user}/data/www/{domain}/`)
|
||||
- Выделен порт: **3003**
|
||||
- Runtime: **Bun**
|
||||
- БД: **SQLite** (WAL mode)
|
||||
- Web-сервер: **Nginx** (управляется BrainyCP)
|
||||
- SSL: настраивается через BrainyCP (Let's Encrypt)
|
||||
|
||||
## Архитектура деплоя
|
||||
|
||||
```
|
||||
Интернет → Nginx (BrainyCP: 80/443) → Reverse Proxy → Bun (localhost:3003)
|
||||
↑ ↑
|
||||
SSL от BrainyCP PM2 / Systemd
|
||||
```
|
||||
|
||||
Bun работает как standalone backend на `localhost:3003`. Nginx терминирует SSL и проксирует HTTP-запросы.
|
||||
|
||||
## Пошаговая инструкция
|
||||
|
||||
### 1. SSH на сервер
|
||||
```bash
|
||||
ssh user@your_server_ip
|
||||
```
|
||||
|
||||
### 2. Установка Bun
|
||||
```bash
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
source ~/.bashrc
|
||||
bun --version
|
||||
```
|
||||
|
||||
### 3. Загрузка проекта в папку BrainyCP
|
||||
Если папка уже создана панелью (например, `/var/www/user/data/www/tenerifeprop.ru`):
|
||||
- Загрузи туда файлы проекта (через FTP, SCP или Git).
|
||||
- Убедись, что папка `data/` существует и доступна для записи.
|
||||
|
||||
```bash
|
||||
cd /var/www/user/data/www/tenerifeprop.ru
|
||||
# Если через git:
|
||||
git clone https://git.softuniq.eu/UniqueSoft/TenerifeProp.git .
|
||||
# Установка зависимостей:
|
||||
bun install --production
|
||||
```
|
||||
|
||||
### 4. Создание .env (PORT = 3003)
|
||||
```bash
|
||||
cat > .env <<'EOF'
|
||||
NODE_ENV=production
|
||||
PORT=3003
|
||||
RESEND_API_KEY=your_key_here
|
||||
TELEGRAM_BOT_TOKEN=your_token_here
|
||||
TELEGRAM_CHAT_ID=your_chat_id_here
|
||||
GITEA_API_URL=https://git.softuniq.eu/api/v1
|
||||
GITEA_TOKEN=your_gitea_token_here
|
||||
EOF
|
||||
chmod 600 .env
|
||||
```
|
||||
|
||||
### 5. Инициализация базы данных (если нужно)
|
||||
```bash
|
||||
# Создание БД и сидов
|
||||
bun run src/db/init.ts
|
||||
bun run src/db/seed.ts
|
||||
# Убедись, что файл появился:
|
||||
ls -la data/tenerifeprop.db
|
||||
```
|
||||
|
||||
### 6. Запуск через PM2
|
||||
```bash
|
||||
bun add -g pm2
|
||||
pm2 start "bun run src/server/index.ts" --name tenerifeprop
|
||||
pm2 save
|
||||
pm2 startup systemd
|
||||
# Выполни команду, которую предложит pm2 (обычно sudo systemctl ...)
|
||||
```
|
||||
|
||||
Проверка:
|
||||
```bash
|
||||
curl http://localhost:3003/api/settings
|
||||
```
|
||||
|
||||
### 7. Настройка Nginx в BrainyCP
|
||||
Зайди в панель BrainyCP:
|
||||
- **WWW-домены** → твой домен → **Редактировать конфиг Nginx** (или "Дополнительные настройки / Пользовательский конфиг").
|
||||
|
||||
Добавь внутрь секции `server` (перед закрывающей скобкой или в начале):
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3003;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_read_timeout 86400;
|
||||
}
|
||||
```
|
||||
|
||||
> **Важно:** не редактируй `/etc/nginx/nginx.conf` напрямую — BrainyCP может перезаписать его.
|
||||
|
||||
### 8. Перезапуск Nginx
|
||||
Через BrainyCP:
|
||||
- **Сервисы** → **Nginx** → **Перезапустить**
|
||||
|
||||
Или по SSH:
|
||||
```bash
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### 9. Проверка
|
||||
- Открой домен в браузере: `https://твой-домен.ru`
|
||||
- Проверь API: `https://твой-домен.ru/api/settings`
|
||||
- Проверь админку: `https://твой-домен.ru/admin/login`
|
||||
- Войди с демо-данными: `admin@clinic.ru` / `admin123`
|
||||
|
||||
## Автоматизация обновлений
|
||||
|
||||
Скрипт `deploy.sh` в корне проекта:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
cd /var/www/user/data/www/tenerifeprop.ru
|
||||
git pull origin dev
|
||||
bun install --production
|
||||
pm2 restart tenerifeprop
|
||||
```
|
||||
|
||||
```bash
|
||||
chmod +x deploy.sh
|
||||
```
|
||||
|
||||
## Риски и нюансы
|
||||
|
||||
| Проблема | Решение |
|
||||
|----------|---------|
|
||||
| BrainyCP перезаписывает Nginx-конфиг | Редактировать только через панель (WWW-домены) |
|
||||
| Порт 3003 занят | `lsof -i :3003` → найди и убей процесс, или укажи другой порт |
|
||||
| Нет root-прав | Установка Bun в `$HOME/.bun`, PM2 глобально через `bun add -g` |
|
||||
| SQLite не переживает перенос | Копируй `data/tenerifeprop.db` через `rsync` или `scp` |
|
||||
| SSL | BrainyCP → SSL → Let's Encrypt. Nginx терминирует SSL, Bun работает по HTTP |
|
||||
|
||||
## Альтернатива без PM2 (systemd unit)
|
||||
|
||||
Если PM2 недоступен, создай systemd-сервис:
|
||||
|
||||
```bash
|
||||
sudo tee /etc/systemd/system/tenerifeprop.service <<'EOF'
|
||||
[Unit]
|
||||
Description=TenerifeProp Bun Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=www-data
|
||||
WorkingDirectory=/var/www/user/data/www/tenerifeprop.ru
|
||||
Environment=NODE_ENV=production
|
||||
Environment=PORT=3003
|
||||
ExecStart=/home/user/.bun/bin/bun run src/server/index.ts
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable tenerifeprop
|
||||
sudo systemctl start tenerifeprop
|
||||
```
|
||||
|
||||
> Адаптируй пути `User`, `WorkingDirectory` и `ExecStart` под реальные на сервере.
|
||||
170
MIGRATION_AUDIT_REPORT.md
Normal file
170
MIGRATION_AUDIT_REPORT.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# Аудит возможности миграции TenerifeProp с SQLite/Bun на MySQL/Node.js
|
||||
|
||||
## Дата: 2026-05-13
|
||||
|
||||
## 1. Краткий вывод
|
||||
|
||||
**Миграция возможна, но трудоёмкая.** Проект жёстко завязан на Bun (`bun:sqlite`, `hono/bun`, `Bun.password`, `crypto.randomUUID` для SQLite primary keys). Нужно переписывать код под совместимость с Node.js + MySQL/PostgreSQL.
|
||||
|
||||
Сложность: **Высокая (~15-20 часов работы)**.
|
||||
|
||||
---
|
||||
|
||||
## 2. Анализ Bun-зависимостей
|
||||
|
||||
### 2.1 `bun:sqlite` (SQLite-специфика)
|
||||
|
||||
**Использование:** 117 SQL-запросов в `src/server/index.ts`, дублирование в `src/modules/database.ts`.
|
||||
|
||||
**Проблемы для MySQL/PostgreSQL:**
|
||||
|
||||
| SQLite фича | MySQL эквивалент | PostgreSQL эквивалент | Сложность |
|
||||
|-------------|-----------------|----------------------|-----------|
|
||||
| `PRAGMA journal_mode=WAL` | Не применимо | Не применимо | Легко (убрать) |
|
||||
| `PRAGMA busy_timeout=5000` | Не применимо | Не применимо | Легко (убрать) |
|
||||
| `INTEGER PRIMARY KEY AUTOINCREMENT` | `INT AUTO_INCREMENT PRIMARY KEY` | `SERIAL PRIMARY KEY` | Легко |
|
||||
| `TEXT DEFAULT (datetime('now'))` | `DATETIME DEFAULT CURRENT_TIMESTAMP` | `TIMESTAMPTZ DEFAULT NOW()` | Легко |
|
||||
| `datetime('now')` в запросах | `NOW()` | `NOW()` | Легко |
|
||||
| `ON CONFLICT(...) DO UPDATE SET` (upsert) | `INSERT ... ON DUPLICATE KEY UPDATE` | `INSERT ... ON CONFLICT DO UPDATE` | Средне |
|
||||
| `JSON` поля (images, videos, badges) | `JSON` тип (MySQL 5.7+) | `JSONB` | Средне |
|
||||
| `crypto.randomUUID()` для `id` | `UUID()` MySQL или `gen_random_uuid()` PG | `gen_random_uuid()` | Средне |
|
||||
| `TEXT` для JSON строк | `JSON` тип | `JSONB` | Легко |
|
||||
|
||||
### 2.2 `hono/bun` → `hono/node-server`
|
||||
|
||||
Причина: `serveStatic` из `hono/bun` использует Bun-специфичные API для чтения файлов.
|
||||
|
||||
**Затронуто:**
|
||||
```typescript
|
||||
import { serveStatic } from 'hono/bun'
|
||||
// 25+ вызовов serveStatic в src/server/index.ts
|
||||
// + src/server/routes-static.ts
|
||||
```
|
||||
|
||||
**Решение:** Заменить на `serveStatic` из `@hono/node-server` или настроить Nginx отдавать статику напрямую, а Hono — только API.
|
||||
|
||||
**Оценка:** Средне. ~10 строк кода + проверка совместимости путей.
|
||||
|
||||
### 2.3 `Bun.password` → `bcrypt`
|
||||
|
||||
**Использование:** 7 мест, включая:
|
||||
```typescript
|
||||
Bun.password.hashSync(password, { algorithm: 'bcrypt', cost: 10 })
|
||||
await Bun.password.verify(password, hash)
|
||||
```
|
||||
|
||||
**Решение:** Заменить на `bcrypt.hashSync(password, 10)` и `bcrypt.compare(password, hash)`.
|
||||
|
||||
**Важно:** `bcrypt` уже есть в `package.json`! Просто переключиться с `Bun.password` на `bcrypt`.
|
||||
|
||||
**Оценка:** Легко. ~7 строк.
|
||||
|
||||
### 2.4 `crypto.randomUUID()`
|
||||
|
||||
Используется 23 раза для генерации UUID первичных ключей.
|
||||
|
||||
**Решение:** Можно оставить `crypto.randomUUID()` — оно работает в Node.js 16+. Или заменить на модуль `uuid` (уже в зависимостях).
|
||||
|
||||
**Оценка:** Легко.
|
||||
|
||||
### 2.5 `bun:test` → `jest` / `vitest`
|
||||
|
||||
5 файлов используют `import { describe, it, expect } from 'bun:test'`.
|
||||
|
||||
**Решение:** Заменить на `import { describe, it, expect } from '@jest/globals'` или использовать встроенный `node:test`.
|
||||
|
||||
**Оценка:** Легко. ~5 строк.
|
||||
|
||||
---
|
||||
|
||||
## 3. Архитектурные изменения
|
||||
|
||||
### 3.1 Слоистая архитектура (Repository Pattern)
|
||||
|
||||
Текущий код содержит 117 прямых SQL-запросов в контроллерах (антипаттерн). При переходе на MySQL/PostgreSQL **крайне рекомендуется** выделить слой репозиториев:
|
||||
|
||||
```
|
||||
src/
|
||||
├── repositories/ # Новый слой
|
||||
│ ├── PropertyRepository.ts
|
||||
│ ├── LeadRepository.ts
|
||||
│ ├── UserRepository.ts
|
||||
│ └── ...
|
||||
├── services/ # Бизнес-логика
|
||||
├── controllers/ # HTTP-handlers
|
||||
└── db/ # Подключение к БД
|
||||
```
|
||||
|
||||
**Без рефакторинга на Repository:** каждый SQL-запрос придётся адаптировать под MySQL вручную (117 мест = высокий риск ошибок).
|
||||
|
||||
**С рефакторингом:** изменения концентрируются в 5-7 файлах репозиториев.
|
||||
|
||||
### 3.2 Библиотека для работы с БД
|
||||
|
||||
| Вариант | MySQL | PostgreSQL | Плюсы | Минусы |
|
||||
|---------|-------|------------|-------|--------|
|
||||
| **mysql2** | ✅ | ❌ | Нативный, быстрый, Promise API | Только MySQL |
|
||||
| **pg** | ❌ | ✅ | Стандарт для PostgreSQL | Только PostgreSQL |
|
||||
| **drizzle-orm** | ✅ | ✅ | TypeScript-first, миграции, zero-config | Новая зависимость |
|
||||
| **prisma** | ✅ | ✅ | ORM, миграции, типизация | Тяжёлый |
|
||||
|
||||
**Рекомендация:** `mysql2` для простоты или `drizzle-orm` для типовой безопасности.
|
||||
|
||||
---
|
||||
|
||||
## 4. Оценка трудоёмкости
|
||||
|
||||
### 4.1 По задачам
|
||||
|
||||
| Задача | Часы | Риск |
|
||||
|--------|------|------|
|
||||
| Замена `bun:sqlite` на `mysql2` + подключение | 2-3 | Низкий |
|
||||
| Рефакторинг SQL-запросов под MySQL синтаксис | 6-8 | Средний (117 мест) |
|
||||
| Создание слоя Repository (рекомендуется) | 8-12 | Низкий (инвестиция) |
|
||||
| Замена `hono/bun` на `hono/node-server` | 1-2 | Низкий |
|
||||
| Замена `Bun.password` на `bcrypt` | 0.5 | Низкий |
|
||||
| Миграция `bun:test` на Node.js tests | 1-2 | Низкий |
|
||||
| Создание SQL-схемы под MySQL | 2-3 | Средний |
|
||||
| Перенос данных (seed / дамп) | 1-2 | Средний |
|
||||
| Тестирование на сервере BrainyCP | 4-6 | Высокий (интеграция) |
|
||||
| **Итого без Repository** | **~15-20** | Высокий |
|
||||
| **Итого с Repository** | **~25-30** | Низкий |
|
||||
|
||||
### 4.2 Альтернатива: Docker на сервере
|
||||
|
||||
Если на сервере можно запустить Docker (не через BrainyCP, а напрямую):
|
||||
- Создать `docker-compose.prod.yml` с Bun-контейнером.
|
||||
- BrainyCP продолжает проксировать Nginx → порт 3003.
|
||||
- Внутри контейнера: Bun + SQLite (как сейчас локально).
|
||||
|
||||
**Время:** 2-4 часа.
|
||||
**Риск:** Низкий (работает точно как локально).
|
||||
**Требования:** Docker на сервере + root-доступ.
|
||||
|
||||
---
|
||||
|
||||
## 5. Сравнение вариантов
|
||||
|
||||
| Вариант | Время | Сложность | Надёжность | Поддержка |
|
||||
|---------|-------|-----------|------------|-----------|
|
||||
| **Оставить Bun на сервере** (V1) | 2-4 часа | Низкая | Высокая | Стандартна |
|
||||
| **Docker-контейнер на сервере** | 2-4 часа | Низкая | Высокая | Идентична локальной |
|
||||
| **Миграция на MySQL + Node.js** | 15-30 часов | Высокая | Средняя | Нужен рефакторинг |
|
||||
| **BrainyCP Next.js** | 15-30 часов | Высокая | Средняя | Полный рерайт |
|
||||
|
||||
---
|
||||
|
||||
## 6. Рекомендация
|
||||
|
||||
**Миграция на MySQL/Node.js — избыточно дорого и рискованно.** Проект маленький (~6K строк), с простой схемой. Переписывание ради развёртывания в BrainyCP не окупается.
|
||||
|
||||
**Оптимальный путь:**
|
||||
1. Установить Bun на сервере (15 минут).
|
||||
2. Загрузить файлы проекта.
|
||||
3. Запустить через PM2.
|
||||
4. Nginx уже настроен BrainyCP.
|
||||
|
||||
Если обязательно нужна MySQL — внедряйте Repository Pattern и ORM (drizzle-orm), но это отдельный проект.
|
||||
|
||||
---
|
||||
*Отчёт подготовлен после анализа кода (32 файла, 6,011 строк) и конфигурации сервера.*
|
||||
57
README.md
57
README.md
@@ -127,6 +127,63 @@ Email: admin@tenerifeprop.com
|
||||
Password: admin123
|
||||
```
|
||||
|
||||
## 🌐 Деплой на BrainyCP (Production)
|
||||
|
||||
### Инфраструктура
|
||||
- **Сервер:** Ubuntu 22.04, BrainyCP (пользователь `nero`)
|
||||
- **Домен:** `https://tenerifeprop.es`
|
||||
- **Runtime:** Bun v1.3.14
|
||||
- **Порт:** 3003 (reverse proxy через Nginx)
|
||||
- **SSL:** Let's Encrypt (управляется BrainyCP)
|
||||
|
||||
### Синхронизация (Git workflow)
|
||||
|
||||
Проект использует три ветки:
|
||||
- `dev` — разработка
|
||||
- `main` — стабильный релиз
|
||||
- `production` — ветка продакшена на BrainyCP
|
||||
|
||||
```bash
|
||||
# 1. Разработка
|
||||
bun run dev # Локально
|
||||
git checkout dev
|
||||
git commit -m "feat: ..."
|
||||
git push origin dev
|
||||
|
||||
# 2. Релиз → main
|
||||
git checkout main
|
||||
git merge dev
|
||||
git push origin main
|
||||
|
||||
# 3. Деплой → production
|
||||
git push origin main:production # Или PR через Gitea
|
||||
|
||||
# 4. Обновление на сервере
|
||||
ssh root@46.175.149.131
|
||||
cd /home/nero/sites/tenerifeprop.es
|
||||
./scripts/sync-production.sh full
|
||||
```
|
||||
|
||||
### Скрипты на сервере
|
||||
- `./scripts/sync-production.sh full` — полный деплой (git pull + install + restart)
|
||||
- `./scripts/sync-production.sh quick` — быстрый рестарт
|
||||
- `./scripts/sync-production.sh status` — статус сервера
|
||||
- `./scripts/sync-production.sh backup` — бэкап БД
|
||||
- `./scripts/sync-production.sh logs` — логи в реальном времени
|
||||
|
||||
### Права доступа (BrainyCP standard)
|
||||
```
|
||||
/home/nero root:root 755
|
||||
/home/nero/sites root:root 755
|
||||
/home/nero/sites/tenerifeprop.es nero:nero 755
|
||||
```
|
||||
|
||||
### Документация для DevOps
|
||||
- `docs/BRAINYCP_DEPLOY_GUIDE.md` — полное руководство по деплою
|
||||
- `docs/AI_DEPLOY_CONTEXT.md` — контекст для ИИ-агентов
|
||||
- `DEPLOY_AUDIT_REPORT.md` — аудит перед деплоем
|
||||
- `MIGRATION_AUDIT_REPORT.md` — анализ миграции на MySQL/Node.js
|
||||
|
||||
## 📄 Лицензия
|
||||
|
||||
MIT License - UniqueSoft
|
||||
90
SERVER_AUDIT_REPORT.md
Normal file
90
SERVER_AUDIT_REPORT.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Аудит сервера и план деплоя TenerifeProp
|
||||
|
||||
## Общие данные
|
||||
- **Сервер**: Ubuntu 22.04 (Jammy), IP `46.175.149.131`
|
||||
- **Панель**: BrainyCP (пользователь `nero`)
|
||||
- **Домен**: `tenerifeprop.es` (SSL Let's Encrypt активен)
|
||||
- **Папка сайта**: `/home/nero/sites/tenerifeprop.es`
|
||||
|
||||
## Архитектура текущего сервера (BrainyCP)
|
||||
|
||||
```
|
||||
Internet → Nginx (BrainyCP) → Proxy_pass → Node.js (stub на порту 3003)
|
||||
↑
|
||||
SSL (Let's Encrypt)
|
||||
```
|
||||
|
||||
BrainyCP создала:
|
||||
1. Vhost Nginx с `proxy_pass` на `127.0.0.1:3003`
|
||||
2. SSL-сертификат Let's Encrypt
|
||||
3. Systemd unit `nodejs@3003.service`, запускающий `index.js`
|
||||
4. Заглушку `index.js` (заглушка BrainyCP)
|
||||
|
||||
## Ключевой конфликт стеков
|
||||
|
||||
| Компонент | Проект TenerifeProp | Что предоставляет BrainyCP |
|
||||
|-----------|---------------------|---------------------------|
|
||||
| **Runtime** | Bun (`bun run src/server/index.ts`) | Node.js v20.10.0 (только) |
|
||||
| **БД** | `bun:sqlite` (SQLite) | Нет специфической поддержки |
|
||||
| **Статика** | `serveStatic` из `hono/bun` | Nginx обрабатывает статику |
|
||||
| **Фреймворк** | Hono | Работает под Node.js без `hono/bun` |
|
||||
|
||||
## Варианты решения
|
||||
|
||||
### Вариант 1: Установить Bun на сервере (РЕКОМЕНДУЕТСЯ)
|
||||
|
||||
BrainyCP устанавливает Node.js через `apt`, но на сервере есть root-доступ. Bun можно установить отдельно — он не конфликтует с системным Node.js.
|
||||
|
||||
**Преимущества:**
|
||||
- Не требуется переписывать код
|
||||
- `bun:sqlite` и `hono/bun` работают из коробки
|
||||
- SQLite-файл просто скопировать
|
||||
|
||||
**Шаги:**
|
||||
1. Установить Bun (в `$HOME/.bun` или глобально).
|
||||
2. Загрузить файлы проекта (`src/`, `public/`, `data/`, `package.json`, `bun.lock`) в `/home/nero/sites/tenerifeprop.es`.
|
||||
3. Создать `.env` с `PORT=3003`, `NODE_ENV=production`.
|
||||
4. Установить зависимости: `bun install --production`.
|
||||
5. Остановить `nodejs@3003.service`.
|
||||
6. Запустить проект через PM2.
|
||||
7. Проверить `curl http://localhost:3003/api/settings`.
|
||||
|
||||
### Вариант 2: Переписать проект под Node.js (НЕ РЕКОМЕНДУЕТСЯ)
|
||||
|
||||
Если категорически не ставить Bun, нужно:
|
||||
- Заменить `import { Database } from 'bun:sqlite'` на `better-sqlite3`.
|
||||
- Заменить `import { serveStatic } from 'hono/bun'` на `import { serveStatic } from 'hono/node-server'`.
|
||||
- Пересоздать `bun.lock` в `package-lock.json`.
|
||||
- Протестировать всё заново.
|
||||
|
||||
**Минусы:** высокий риск багов, новые зависимости, перетестировать всё.
|
||||
|
||||
## Что нужно от тебя для деплоя
|
||||
|
||||
| Данные | Пояснение |
|
||||
|--------|-----------|
|
||||
| **SSH логин/пароль** | Доступ к серверу (root) |
|
||||
| **Домен** | `tenerifeprop.es` |
|
||||
| **Порт** | `3003` (уже выделен BrainyCP) |
|
||||
| **Env vars** | `RESEND_API_KEY`, `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID` |
|
||||
|
||||
### Команды для копирования файлов (без SSH)
|
||||
```bash
|
||||
# С локальной машины
|
||||
scp -r /home/swp/Projects/TenerifeProp/src nero@46.175.149.131:/home/nero/sites/tenerifeprop.es/
|
||||
scp -r /home/swp/Projects/TenerifeProp/public nero@46.175.149.131:/home/nero/sites/tenerifeprop.es/
|
||||
scp /home/swp/Projects/TenerifeProp/package.json nero@46.175.149.131:/home/nero/sites/tenerifeprop.es/
|
||||
scp /home/swp/Projects/TenerifeProp/bun.lock nero@46.175.149.131:/home/nero/sites/tenerifeprop.es/
|
||||
```
|
||||
|
||||
## Риски
|
||||
|
||||
1. **Обновление BrainyCP** может перезаписать Nginx-конфиг — нужно проверять после обновлений.
|
||||
2. **Bun не в репозиториях** — обновляется вручную (`bun upgrade`).
|
||||
3. **Systemd unit** — BrainyCP управляет только `nodejs@3003.service`. Если остановить его и запустить PM2 — всё нормально, но кнопка "Перезапустить хост" в BrainyCP перезапустит заглушку, а не ваш проект.
|
||||
|
||||
## Итог
|
||||
|
||||
**Рекомендация:** Установить Bun и запустить проект на нём. Nginx-прокси уже настроена BrainyCP, SSL работает. Нужно только загрузить файлы проекта, установить зависимости и заменить заглушку на реальный процесс.
|
||||
|
||||
Если подтвердишь — выполню деплой.
|
||||
182
docs/AI_DEPLOY_CONTEXT.md
Normal file
182
docs/AI_DEPLOY_CONTEXT.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# AI Deploy Context — TenerifeProp on BrainyCP
|
||||
|
||||
## Machine-Readable Checklist
|
||||
|
||||
```yaml
|
||||
project: TenerifeProp
|
||||
runtime: Bun v1.3.14
|
||||
framework: Hono v4.12.10
|
||||
database: SQLite (WAL mode)
|
||||
ssl: Let's Encrypt (BrainyCP managed)
|
||||
proxy: Nginx (BrainyCP managed)
|
||||
port: 3003
|
||||
server_ip: 46.175.149.131
|
||||
server_os: Ubuntu 22.04 LTS
|
||||
panel: BrainyCP (user: nero, no SSH)
|
||||
```
|
||||
|
||||
## Critical Rules for AI Agents
|
||||
|
||||
### 1. NEVER modify BrainyCP-managed files directly
|
||||
- ❌ Do NOT edit `/etc/nginx/sites-available/*.conf` directly
|
||||
- ❌ Do NOT edit `/etc/nginx/nginx.conf` directly
|
||||
- ❌ Do NOT modify `/lib/systemd/system/nodejs@*.service`
|
||||
- ✅ Use BrainyCP web interface for Nginx changes
|
||||
- ✅ Use custom systemd unit `tenerifeprop.service` for process management
|
||||
|
||||
### 2. Permissions Hierarchy (BrainyCP standard)
|
||||
```
|
||||
/home/nero/ : root:root, 755 — managed by BrainyCP
|
||||
/home/nero/sites/ : root:root, 755 — managed by BrainyCP
|
||||
/home/nero/sites/tenerifeprop.es/ : nero:nero, 755 — site content
|
||||
All files inside : nero:nero, 644
|
||||
All directories : nero:nero, 755
|
||||
.env : nero:nero, 600 (restricted)
|
||||
data/ : nero:nero, 755
|
||||
tenerifeprop.db : nero:nero, 644
|
||||
```
|
||||
|
||||
NEVER change `/home/nero` or `/home/nero/sites/` ownership from `root:root`.
|
||||
ONLY change contents inside `/home/nero/sites/tenerifeprop.es/` to `nero:nero`.
|
||||
|
||||
### 3. Bun Location (not in PATH)
|
||||
```
|
||||
Binary: /home/nero/.bun/bin/bun
|
||||
Version: 1.3.14
|
||||
Owner: root:root (installation)
|
||||
User execution: via su - nero -s /bin/bash -c '...'
|
||||
```
|
||||
|
||||
Always use full path to bun on server.
|
||||
|
||||
### 4. Deployment Flow (Git-based)
|
||||
```
|
||||
[Local] dev branch → commit → push → PR → main
|
||||
[Server] production branch ← git pull origin production → restart
|
||||
```
|
||||
|
||||
The server tracks `production` branch, not `main` or `dev`.
|
||||
|
||||
### 5. Restart Sequence
|
||||
```bash
|
||||
# Correct way to restart
|
||||
systemctl restart tenerifeprop
|
||||
|
||||
# After updating files
|
||||
systemctl restart tenerifeprop
|
||||
|
||||
# After updating .env
|
||||
systemctl restart tenerifeprop
|
||||
```
|
||||
|
||||
### 6. Healthcheck Endpoint
|
||||
```bash
|
||||
curl -s http://localhost:3003/api/settings
|
||||
# Expected: {"success":true,"data":{...}}
|
||||
```
|
||||
|
||||
### 7. Log Inspection
|
||||
```bash
|
||||
journalctl -u tenerifeprop -f
|
||||
```
|
||||
|
||||
### 8. Backup Before Deploy
|
||||
```bash
|
||||
/home/nero/sites/tenerifeprop.es/scripts/backup.sh
|
||||
# Creates: /backup/db/tenerifeprop-YYYYMMDD-HHMMSS.db
|
||||
# Keeps: 7 days of backups
|
||||
# Cron: Daily at 03:00
|
||||
```
|
||||
|
||||
### 9. Deploy Script
|
||||
```bash
|
||||
/home/nero/sites/tenerifeprop.es/scripts/deploy.sh
|
||||
```
|
||||
What it does:
|
||||
1. Backup database.
|
||||
2. Fetch and reset to origin/production.
|
||||
3. Run `bun install --production`.
|
||||
4. Fix permissions (chown nero:nero, chmod 644/755).
|
||||
5. Restart `tenerifeprop.service`.
|
||||
6. Healthcheck (expect HTTP 200 on /api/settings).
|
||||
|
||||
### 10. Environment Variables (production)
|
||||
```
|
||||
NODE_ENV=production
|
||||
PORT=3003
|
||||
RESEND_API_KEY=
|
||||
TELEGRAM_BOT_TOKEN=
|
||||
TELEGRAM_CHAT_ID=
|
||||
GITEA_API_URL=https://git.softuniq.eu/api/v1
|
||||
GITEA_TOKEN=
|
||||
GITEA_USER=
|
||||
GITEA_PASS=
|
||||
```
|
||||
|
||||
File location: `/home/nero/sites/tenerifeprop.es/.env`
|
||||
Permissions: `600` (read-only owner)
|
||||
|
||||
## Synchronization Workflow
|
||||
|
||||
### From local to production (via Git)
|
||||
|
||||
1. Developer commits to `dev`:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: new feature"
|
||||
git push origin dev
|
||||
```
|
||||
|
||||
2. Merge to `main` (via PR or manually):
|
||||
```bash
|
||||
git checkout main
|
||||
git merge dev
|
||||
git push origin main
|
||||
```
|
||||
|
||||
3. Push `main` to `production` branch:
|
||||
```bash
|
||||
git push origin main:production
|
||||
# or
|
||||
git checkout production
|
||||
git merge main
|
||||
git push origin production
|
||||
```
|
||||
|
||||
4. Deploy on server:
|
||||
```bash
|
||||
ssh root@46.175.149.131
|
||||
cd /home/nero/sites/tenerifeprop.es
|
||||
./scripts/deploy.sh
|
||||
```
|
||||
|
||||
### Auto-deploy (optional)
|
||||
Add webhook in Gitea to call POST endpoint.
|
||||
Server endpoint runs `./scripts/deploy.sh`.
|
||||
|
||||
## File Structure on Server
|
||||
```
|
||||
/home/nero/sites/tenerifeprop.es/
|
||||
├── .env # Env vars (secrets)
|
||||
├── .git/ # Git repository (production branch)
|
||||
├── data/
|
||||
│ └── tenerifeprop.db # SQLite database
|
||||
├── node_modules/ # Dependencies
|
||||
├── public/ # Static files
|
||||
├── scripts/
|
||||
│ ├── deploy.sh # Deployment script
|
||||
│ └── backup.sh # Backup script
|
||||
├── src/ # Source code
|
||||
├── package.json
|
||||
├── bun.lock
|
||||
└── docs/ # Documentation
|
||||
```
|
||||
|
||||
## Forbidden Actions
|
||||
- ❌ Do NOT run `git push --force` on production branch
|
||||
- ❌ Do NOT edit `.env` without backup
|
||||
- ❌ Do NOT delete `data/tenerifeprop.db` without backup
|
||||
- ❌ Do NOT change Bun version without testing locally
|
||||
- ❌ Do NOT modify BrainyCP Nginx configs directly
|
||||
- ❌ Do NOT use port other than 3003 without updating Nginx
|
||||
- ❌ Do NOT change `/home/nero` or `/home/nero/sites/` ownership
|
||||
309
docs/BRAINYCP_DEPLOY_GUIDE.md
Normal file
309
docs/BRAINYCP_DEPLOY_GUIDE.md
Normal file
@@ -0,0 +1,309 @@
|
||||
# Руководство по деплою TenerifeProp на BrainyCP
|
||||
|
||||
## Для кого это руководство
|
||||
Для разработчиков и DevOps-инженеров, которые будут разворачивать или обновлять проект TenerifeProp на хостинге с панелью BrainyCP.
|
||||
|
||||
## 1. Предварительные требования
|
||||
|
||||
### На сервере (что уже должно быть)
|
||||
- **BrainyCP** установлена и работает.
|
||||
- **Домен** добавлен в панель (`tenerifeprop.es`).
|
||||
- **NodeJS** установлен через панель BrainyCP (создаст заглушку на порту, например `3003`).
|
||||
- **SSL** активирован (Let's Encrypt через панель).
|
||||
- **SSH-доступ** к серверу с правами root.
|
||||
- **Git** установлен (`git --version`).
|
||||
|
||||
### На локальной машине
|
||||
- Доступ к репозиторию `git.softuniq.eu/UniqueSoft/TenerifeProp`.
|
||||
- SSH-ключ или логин/пароль для доступа к серверу.
|
||||
|
||||
### Ветки проекта
|
||||
```
|
||||
origin/dev — основная ветка разработки
|
||||
origin/main — ветка релиза
|
||||
origin/production — ветка продакшена на BrainyCP (создаётся при первом деплое)
|
||||
```
|
||||
|
||||
## 2. Структура проекта на сервере
|
||||
|
||||
```
|
||||
/home/nero/sites/tenerifeprop.es/
|
||||
├── .env # Переменные окружения
|
||||
├── src/ # Серверный код
|
||||
├── public/ # Статические файлы
|
||||
├── data/
|
||||
│ └── tenerifeprop.db # SQLite база данных
|
||||
├── node_modules/ # Зависимости
|
||||
├── package.json
|
||||
├── bun.lock
|
||||
└── .git/ # Git репозиторий (если клонирован)
|
||||
```
|
||||
|
||||
## 3. Первый деплой (ручной)
|
||||
|
||||
### Шаг 1: Остановить заглушку BrainyCP
|
||||
```bash
|
||||
ssh root@46.175.149.131
|
||||
systemctl stop nodejs@3003.service
|
||||
systemctl disable nodejs@3003.service
|
||||
```
|
||||
|
||||
### Шаг 2: Установить Bun
|
||||
```bash
|
||||
# Установка Bun в папку пользователя (не трогает системный Node.js)
|
||||
curl -fsSL https://bun.sh/install | BUN_INSTALL=/home/nero/.bun bash
|
||||
chown -R nero:nero /home/nero/.bun
|
||||
```
|
||||
|
||||
Путь к Bun: `/home/nero/.bun/bin/bun`
|
||||
|
||||
### Шаг 3: Клонировать репозиторий
|
||||
```bash
|
||||
cd /home/nero/sites/tenerifeprop.es
|
||||
# Очистить заглушку (сохранить .well-known для SSL)
|
||||
rm -f index.js app.js app.css
|
||||
git clone https://git.softuniq.eu/UniqueSoft/TenerifeProp.git .
|
||||
```
|
||||
|
||||
### Шаг 4: Переключиться на ветку production
|
||||
```bash
|
||||
git checkout -b production origin/production
|
||||
# или если ветки нет:
|
||||
git checkout -b production
|
||||
```
|
||||
|
||||
### Шаг 5: Создать `.env`
|
||||
```bash
|
||||
cat > .env <<'EOF'
|
||||
NODE_ENV=production
|
||||
PORT=3003
|
||||
RESEND_API_KEY=your_key_here
|
||||
TELEGRAM_BOT_TOKEN=your_token_here
|
||||
TELEGRAM_CHAT_ID=your_chat_id_here
|
||||
GITEA_API_URL=https://git.softuniq.eu/api/v1
|
||||
GITEA_TOKEN=your_gitea_token
|
||||
EOF
|
||||
chmod 600 .env
|
||||
chown nero:nero .env
|
||||
```
|
||||
|
||||
### Шаг 6: Установить зависимости
|
||||
```bash
|
||||
/home/nero/.bun/bin/bun install --production
|
||||
```
|
||||
|
||||
### Шаг 7: Настроить systemd
|
||||
Создать файл `/etc/systemd/system/tenerifeprop.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=TenerifeProp Bun Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nero
|
||||
WorkingDirectory=/home/nero/sites/tenerifeprop.es
|
||||
Environment=NODE_ENV=production
|
||||
Environment=PORT=3003
|
||||
EnvironmentFile=/home/nero/sites/tenerifeprop.es/.env
|
||||
ExecStart=/home/nero/.bun/bin/bun run src/server/index.ts
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Активировать:
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable tenerifeprop.service
|
||||
systemctl start tenerifeprop.service
|
||||
```
|
||||
|
||||
### Шаг 8: Проверить работу
|
||||
```bash
|
||||
# Локальный тест
|
||||
curl http://localhost:3003/api/settings
|
||||
# Ожидается: {"success":true,"data":{...}}
|
||||
|
||||
# Публичный тест
|
||||
curl https://tenerifeprop.es/api/settings
|
||||
|
||||
# Логи
|
||||
journalctl -u tenerifeprop -f
|
||||
```
|
||||
|
||||
## 4. Обновление проекта (Git-based deploy)
|
||||
|
||||
### Метод A: Скрипт автообновления (рекомендуется)
|
||||
|
||||
На сервере есть скрипт `/home/nero/sites/tenerifeprop.es/scripts/deploy.sh`.
|
||||
|
||||
```bash
|
||||
# Обновить из ветки production
|
||||
cd /home/nero/sites/tenerifeprop.es
|
||||
./scripts/deploy.sh
|
||||
```
|
||||
|
||||
Что делает скрипт:
|
||||
1. `git fetch origin`
|
||||
2. `git reset --hard origin/production`
|
||||
3. `bun install --production`
|
||||
4. `chown -R nero:nero .`
|
||||
5. `chmod 600 .env`
|
||||
6. `systemctl restart tenerifeprop`
|
||||
7. Проверка healthcheck
|
||||
|
||||
### Метод B: Ручное обновление
|
||||
|
||||
```bash
|
||||
ssh root@46.175.149.131
|
||||
cd /home/nero/sites/tenerifeprop.es
|
||||
|
||||
# Переключиться на production
|
||||
git checkout production
|
||||
git pull origin production
|
||||
|
||||
# Установить зависимости (если изменились)
|
||||
/home/nero/.bun/bin/bun install --production
|
||||
|
||||
# Права
|
||||
chown -R nero:nero .
|
||||
chmod 600 .env
|
||||
|
||||
# Перезапустить
|
||||
systemctl restart tenerifeprop
|
||||
|
||||
# Проверить
|
||||
systemctl status tenerifeprop
|
||||
curl http://localhost:3003/api/settings
|
||||
```
|
||||
|
||||
## 5. Git workflow для синхронизации
|
||||
|
||||
### Схема веток
|
||||
```
|
||||
[dev] → commit, push → PR → [main] → tag → PR → [production] → auto-deploy
|
||||
```
|
||||
|
||||
### Как внести изменения
|
||||
|
||||
1. **Разработка** (на локальной машине или в Docker):
|
||||
```bash
|
||||
git checkout dev
|
||||
# вносишь изменения
|
||||
git add .
|
||||
git commit -m "feat: новая фича"
|
||||
git push origin dev
|
||||
```
|
||||
|
||||
2. **Релиз** (merge в main):
|
||||
```bash
|
||||
git checkout main
|
||||
git merge dev
|
||||
git tag -a v1.1.0 -m "Release v1.1.0"
|
||||
git push origin main --tags
|
||||
```
|
||||
|
||||
3. **Деплой** (merge в production):
|
||||
```bash
|
||||
git checkout production
|
||||
git merge main
|
||||
git push origin production
|
||||
```
|
||||
|
||||
4. **Авто-деплой** (на сервере):
|
||||
- Вебхук Gitea → сервер получает уведомление.
|
||||
- Или `git pull` по cron каждые 5 минут.
|
||||
- Или запускаешь `./scripts/deploy.sh` вручную.
|
||||
|
||||
### Webhook (Gitea → сервер)
|
||||
|
||||
В Gitea (Settings → Webhooks → Add Webhook):
|
||||
- URL: `https://tenerifeprop.es/api/admin/deploy`
|
||||
- Секретный ключ: настрой в `.env` (`DEPLOY_SECRET`)
|
||||
- События: `push`
|
||||
|
||||
На сервере нужен endpoint `/api/admin/deploy`, который:
|
||||
1. Проверяет секретный ключ.
|
||||
2. Запускает `git pull origin production`.
|
||||
3. Перезапускает сервер.
|
||||
|
||||
Это усложнение — рекомендуется начать со скрипта.
|
||||
|
||||
## 6. Резервное копирование базы данных
|
||||
|
||||
### Дамп БД (на сервере)
|
||||
```bash
|
||||
cd /home/nero/sites/tenerifeprop.es
|
||||
# SQLite — просто копируем файл
|
||||
cp data/tenerifeprop.db /backup/tenerifeprop-$(date +%Y%m%d).db
|
||||
```
|
||||
|
||||
### Восстановление
|
||||
```bash
|
||||
systemctl stop tenerifeprop
|
||||
cp /backup/tenerifeprop-20260513.db data/tenerifeprop.db
|
||||
chown nero:nero data/tenerifeprop.db
|
||||
chmod 644 data/tenerifeprop.db
|
||||
systemctl start tenerifeprop
|
||||
```
|
||||
|
||||
## 7. Troubleshooting
|
||||
|
||||
| Проблема | Решение |
|
||||
|----------|---------|
|
||||
| Bun не найден | Проверь `ls /home/nero/.bun/bin/bun`. Если нет — переустановить. |
|
||||
| Порт 3003 занят | `lsof -i :3003` → найти и убить процесс. Или изменить порт в `.env` и Nginx. |
|
||||
| Nginx не проксирует | Проверить конфиг BrainyCP. Сравнить с рабочим сайтом. |
|
||||
| Permission denied | `chown -R nero:nero /home/nero/sites/tenerifeprop.es` |
|
||||
| SQLite database is locked | Остановить сервер, удалить `*.db-shm` и `*.db-wal`, запустить. |
|
||||
| 502 Bad Gateway | Backend не запущен. `systemctl start tenerifeprop`. |
|
||||
| Статика 404 | Проверить пути в `public/`. CSS/JS должны быть доступны через Bun. |
|
||||
|
||||
## 8. Команды для мониторинга
|
||||
|
||||
```bash
|
||||
# Статус сервера
|
||||
systemctl status tenerifeprop
|
||||
|
||||
# Логи реального времени
|
||||
journalctl -u tenerifeprop -f
|
||||
|
||||
# Проверка порта
|
||||
ss -tlnp | grep 3003
|
||||
lsof -i :3003
|
||||
|
||||
# Проверка процесса Bun
|
||||
ps aux | grep bun
|
||||
|
||||
# Проверка API
|
||||
curl -s http://localhost:3003/api/settings | python -m json.tool
|
||||
|
||||
# Проверка SSL
|
||||
openssl s_client -connect tenerifeprop.es:443 -servername tenerifeprop.es
|
||||
|
||||
# Ресурсы сервера
|
||||
htop
|
||||
df -h
|
||||
free -h
|
||||
```
|
||||
|
||||
## 9. Контакты и доступы
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Сервер | `46.175.149.131` |
|
||||
| SSH логин | `root` |
|
||||
| Панель | BrainyCP (пользователь `nero`) |
|
||||
| Домен | `tenerifeprop.es` |
|
||||
| Backend порт | `3003` |
|
||||
| Bun путь | `/home/nero/.bun/bin/bun` |
|
||||
| Папка сайта | `/home/nero/sites/tenerifeprop.es` |
|
||||
| Логи | `journalctl -u tenerifeprop` |
|
||||
| База данных | `data/tenerifeprop.db` (SQLite) |
|
||||
| GitHub/Gitea | `https://git.softuniq.eu/UniqueSoft/TenerifeProp` |
|
||||
123
scripts/sync-production.sh
Normal file
123
scripts/sync-production.sh
Normal file
@@ -0,0 +1,123 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# TenerifeProp Production Sync Script
|
||||
# Usage: ./scripts/sync-production.sh [command]
|
||||
# Commands:
|
||||
# full - Full sync with git, install, restart (default)
|
||||
# quick - Only restart server (if only .env changed)
|
||||
# status - Show server status
|
||||
# logs - Show logs
|
||||
# backup - Backup database only
|
||||
|
||||
PROJECT_DIR="/home/nero/sites/tenerifeprop.es"
|
||||
BUN="/home/nero/.bun/bin/bun"
|
||||
SERVICE="tenerifeprop"
|
||||
GITEA_URL="https://git.softuniq.eu/UniqueSoft/TenerifeProp"
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
show_status() {
|
||||
echo "=== Server Status ==="
|
||||
systemctl status "$SERVICE" --no-pager
|
||||
echo ""
|
||||
echo "=== CPU/Memory ==="
|
||||
ps aux | grep "$SERVICE" | grep -v grep
|
||||
echo ""
|
||||
echo "=== Disk Space ==="
|
||||
df -h "$PROJECT_DIR"
|
||||
echo ""
|
||||
echo "=== Database Size ==="
|
||||
ls -lh "$PROJECT_DIR/data/tenerifeprop.db"
|
||||
echo ""
|
||||
echo "=== Port Check ==="
|
||||
ss -tlnp | grep :3003 || echo "Port 3003 NOT listening"
|
||||
echo ""
|
||||
echo "=== Healthcheck ==="
|
||||
curl -s -o /dev/null -w '%{http_code}' http://localhost:3003/api/settings
|
||||
echo " - /api/settings"
|
||||
}
|
||||
|
||||
show_logs() {
|
||||
journalctl -u "$SERVICE" -f --no-pager
|
||||
}
|
||||
|
||||
backup_db() {
|
||||
mkdir -p /backup/db
|
||||
BACKUP_FILE="/backup/db/tenerifeprop-$(date +%Y%m%d-%H%M%S).db"
|
||||
cp "$PROJECT_DIR/data/tenerifeprop.db" "$BACKUP_FILE"
|
||||
echo "✅ Backup created: $BACKUP_FILE"
|
||||
find /backup/db -name '*.db' -mtime +7 -delete
|
||||
echo "✅ Old backups (7+ days) cleaned"
|
||||
}
|
||||
|
||||
deploy() {
|
||||
echo "=== Deploy started at $(date) ==="
|
||||
|
||||
# Backup database
|
||||
backup_db
|
||||
|
||||
# Git sync
|
||||
echo "=== Syncing with Gitea (production branch)... ==="
|
||||
git fetch origin production
|
||||
git reset --hard origin/production
|
||||
|
||||
# Install dependencies
|
||||
"${BUN}" install --production
|
||||
|
||||
# Fix permissions
|
||||
chown -R nero:nero "$PROJECT_DIR"
|
||||
chmod 600 "$PROJECT_DIR/.env"
|
||||
find "$PROJECT_DIR" -type f -not -path '*/node_modules/*' -exec chmod 644 {} \;
|
||||
find "$PROJECT_DIR" -type d -exec chmod 755 {} \;
|
||||
chmod 644 "$PROJECT_DIR/data/tenerifeprop.db" 2>/dev/null || true
|
||||
|
||||
# Restart
|
||||
echo "=== Restarting $SERVICE ==="
|
||||
systemctl restart "$SERVICE"
|
||||
|
||||
# Healthcheck
|
||||
sleep 2
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:3003/api/settings)
|
||||
if [ "$HTTP_CODE" = "200" ]; then
|
||||
echo "✅ Deploy successful. Healthcheck: HTTP 200"
|
||||
# Tag the deploy
|
||||
git tag "deploy-$(date +%Y%m%d-%H%M%S)" || true
|
||||
else
|
||||
echo "❌ Deploy failed. Healthcheck: HTTP $HTTP_CODE"
|
||||
echo "Check logs: journalctl -u $SERVICE --no-pager -n 50"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Deploy completed at $(date) ==="
|
||||
}
|
||||
|
||||
quick_restart() {
|
||||
echo "=== Quick restart ==="
|
||||
systemctl restart "$SERVICE"
|
||||
sleep 2
|
||||
curl -s -o /dev/null -w '%{http_code}' http://localhost:3003/api/settings
|
||||
echo " - Healthcheck"
|
||||
}
|
||||
|
||||
case "${1:-full}" in
|
||||
full)
|
||||
deploy
|
||||
;;
|
||||
quick)
|
||||
quick_restart
|
||||
;;
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
logs)
|
||||
show_logs
|
||||
;;
|
||||
backup)
|
||||
backup_db
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $(basename "$0") {full|quick|status|logs|backup}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user