update README.md

This commit is contained in:
2026-01-05 20:30:26 +03:00
parent 9bbf88a8f7
commit 501e858c06
151 changed files with 1084 additions and 31525 deletions

View File

@@ -1,443 +0,0 @@
# Contributing to Ospabhost 8.1
Thank you for considering contributing to **Ospabhost 8.1**! This document provides guidelines for contributing.
---
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [Development Workflow](#development-workflow)
- [Coding Standards](#coding-standards)
- [Commit Guidelines](#commit-guidelines)
- [Pull Request Process](#pull-request-process)
- [Testing Requirements](#testing-requirements)
---
## Code of Conduct
### Our Pledge
We pledge to make participation in our project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity, level of experience, nationality, personal appearance, race, religion, sexual identity and orientation.
### Our Standards
**Positive behavior includes:**
- Using welcoming and inclusive language
- Being respectful of differing viewpoints
- Gracefully accepting constructive criticism
- Focusing on what is best for the project
- Showing empathy towards other community members
**Unacceptable behavior includes:**
- Trolling, insulting comments, personal attacks
- Public or private harassment
- Publishing others' private information without permission
### Enforcement
Violations can be reported to:
- **Email:** support@ospab.host
- **Telegram:** @ospab_support
---
## Getting Started
### Prerequisites
Before you begin, ensure you have:
\\\ash
# Node.js (v24.x or higher)
node --version
# npm (v10.x or higher)
npm --version
# MySQL (8.0 or higher)
mysql --version
# Git
git --version
\\\
### Fork and Clone
1. **Fork the repository** on GitHub
2. **Clone your fork locally:**
\\\ash
git clone https://github.com/YOUR_USERNAME/ospabhost8.1.git
cd ospabhost8.1/ospabhost
\\\
3. **Add upstream remote:**
\\\ash
git remote add upstream https://github.com/Ospab/ospabhost8.1.git
\\\
### Setup Development Environment
#### Backend Setup
\\\ash
cd backend
# Install dependencies
npm install
# Copy environment file
cp .env.example .env
# Setup database
npx prisma migrate deploy
# Run in development mode
npm run dev
\\\
#### Frontend Setup
\\\ash
cd frontend
# Install dependencies
npm install
# Copy environment file
cp .env.example .env
# Start development server
npm run dev
\\\
---
## Development Workflow
### Create Feature Branch
\\\ash
git checkout -b feature/your-feature-name
# or for bug fixes:
git checkout -b fix/bug-description
\\\
### Make Changes
1. Make your changes following the coding standards below
2. Ensure tests pass: \
pm run test\
3. Build successfully: \
pm run build\
### Commit Changes
\\\ash
# Stage your changes
git add .
# Commit with a descriptive message
git commit -m "feat: Add new storage feature"
# Push to your fork
git push origin feature/your-feature-name
\\\
### Create Pull Request
1. Go to your fork on GitHub
2. Click "Compare & pull request"
3. Write a clear description of your changes
4. Reference any related issues: "Fixes #123"
5. Submit the PR
---
## Coding Standards
### Backend (Express/TypeScript)
- Use **TypeScript** for type safety
- Follow **camelCase** for variables and functions
- Use **PascalCase** for classes and interfaces
- Keep functions small and focused
- Add JSDoc comments for public methods
- Use async/await instead of promises
Example:
\\\ ypescript
/**
* Generates a secure password for storage credentials
* @param length - Password length (default: 16)
* @returns Generated password
*/
async function generateSecurePassword(length: number = 16): Promise<string> {
// Implementation
}
\\\
### Frontend (React/TypeScript)
- Use **functional components** with hooks
- Use **TypeScript** for type safety
- Follow **camelCase** for functions and variables
- Use **PascalCase** for components
- Extract reusable components
- Keep components focused and small
Example:
\\\ ypescript
interface BucketProps {
id: string;
name: string;
onDelete?: () => void;
}
export const BucketCard: React.FC<BucketProps> = ({ id, name, onDelete }) => {
return <div>{name}</div>;
};
\\\
### General Rules
- Use **4 spaces** for indentation
- Add trailing commas in objects/arrays
- Use semicolons
- No console.log in production code
- Use meaningful variable names
---
## Commit Guidelines
We follow [Conventional Commits](https://www.conventionalcommits.org/):
\\\
feat: Add new feature (S3 storage, etc.)
fix: Bug fixes
docs: Documentation changes
style: Code formatting (no logic changes)
refactor: Code restructuring (no feature changes)
test: Add or update tests
chore: Dependency updates, configuration changes
\\\
Examples:
- \ eat: Add presigned URL generation for S3 downloads\
- \ ix: Fix rate limiting for credential generation\
- \docs: Update API documentation\
- \ est: Add tests for storage service\
---
## Pull Request Process
1. **Update your fork:**
\\\ash
git fetch upstream
git rebase upstream/main
\\\
2. **Resolve conflicts** if any
3. **Ensure tests pass:**
\\\ash
npm run test
npm run lint
npm run build
\\\
4. **Push your changes:**
\\\ash
git push origin feature/your-feature-name
\\\
5. **Create Pull Request** with:
- Clear title describing your changes
- Description of what and why you changed
- Reference to any related issues
- Screenshots if UI changes
6. **Address review feedback:**
- Make requested changes
- Push new commits
- Request re-review
---
## Testing Requirements
### Backend Tests
\\\ash
# Run all tests
npm run test
# Run with coverage
npm run test:coverage
# Run specific test file
npm run test -- storage.service.test.ts
\\\
### Frontend Tests
\\\ash
# Run tests
npm run test
# Run with coverage
npm run test -- --coverage
\\\
### Code Quality
\\\ash
# Lint code
npm run lint
# Format code
npm run format
# Type check
npm run type-check
\\\
---
## Project Structure
\\\
backend/src/modules/
storage/ # S3 Object Storage
auth/ # Authentication
ticket/ # Support Tickets
check/ # Payment Checks
tariff/ # Tariff Plans
notification/ # Notifications
frontend/src/
pages/ # Route pages
components/ # Reusable components
context/ # React Context (Auth)
lib/ # Utilities and API client
App.tsx # Main component
\\\
---
## File Upload Feature Development
### Upload Implementation
The frontend supports multiple upload methods in `frontend/src/pages/dashboard/storage-bucket.tsx`:
**1. Drag & Drop Upload**
- Uses React's `DragEvent` handlers
- Files extracted from `event.dataTransfer.files`
- Triggers `performUpload()` callback
**2. File Selection**
- Single input with `multiple` attribute
- Handled via `handleUploadInput()` event
- Converts FileList to File[] array
**3. Directory Upload**
- Uses `webkitdirectory` and `mozdirectory` attributes
- Creates recursive file upload maintaining folder structure
- Path prefix combines with directory structure
**4. URI Upload**
- `handleUriUpload()` fetches from remote URL
- Creates File object from Blob response
- Integrates with standard upload flow
### Progress Tracking
Upload progress is tracked via XMLHttpRequest:
\\\typescript
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const elapsed = (Date.now() - startTime) / 1000;
const speed = elapsed > 0 ? event.loaded / elapsed : 0;
const percentage = Math.round((event.loaded / event.total) * 100);
setUploadProgress({
loaded: event.loaded,
total: event.total,
speed,
percentage
});
}
});
\\\
**Key Types:**
- `UploadProgress`: Tracks individual file upload metrics
- `uploadStats`: Displays current file and progress counter
- `uploadAbortControllerRef`: Ref to AbortController for canceling uploads
---
## Upload Cancellation
Users can cancel ongoing uploads:
\\\typescript
const handleCancelUpload = useCallback(() => {
if (uploadAbortControllerRef.current) {
uploadAbortControllerRef.current.abort();
uploadAbortControllerRef.current = null;
}
setUploading(false);
setUploadProgress({});
setUploadStats({ currentFile: '', completedFiles: 0, totalFiles: 0 });
addToast('Загрузка отменена', 'info');
}, [addToast]);
\\\
---
## URI Download via Proxy
To bypass CORS limitations, URI downloads use backend proxy:
\\\
POST /api/storage/buckets/:id/objects/download-from-uri
{
"url": "https://example.com/file.zip"
}
\\\
Response:
\\\json
{
"blob": "base64_encoded_file_data",
"mimeType": "application/zip"
}
\\\
This avoids CORS errors by handling the request server-side.
---
## Need Help?
- Read [README.md](./README.md)
- Ask in [GitHub Discussions](https://github.com/Ospab/ospabhost8.1/discussions)
- Report bugs in [GitHub Issues](https://github.com/Ospab/ospabhost8.1/issues)
- Email: support@ospab.host
---
## Thank You!
Thank you for contributing to Ospabhost 8.1! Your efforts help make this project better for everyone.
**Happy Coding! **

View File

@@ -1,308 +0,0 @@
# Система статистики и мониторинга серверов
## 📊 Что добавлено
### Backend (API):
1. **Новая модель Prisma**: `ServerMetric`
- Хранит историю метрик каждого сервера
- Поля: CPU, Memory, Disk, Network, Status, Uptime
- Автоматическое удаление при удалении сервера (CASCADE)
2. **3 новых API endpoint'а**:
- `GET /api/server/:id/metrics` - Получить текущие метрики (+ сохранение в БД)
- `GET /api/server/:id/metrics/history?period=24h` - История за период (1h, 6h, 24h, 7d, 30d)
- `GET /api/server/:id/metrics/summary` - Сводка за 24 часа (средние, макс, мин)
3. **Автоматическое сохранение**:
- При каждом запросе текущих метрик данные сохраняются в БД
- Создаётся точка для графиков
### Frontend (React):
1. **Компонент `ServerMetrics.tsx`**:
- 4 карточки с текущими показателями (CPU, RAM, Disk, Network)
- Цветовая индикация нагрузки (зелёный/жёлтый/красный)
- Фильтр периода (1 час, 6 часов, 24 часа, 7 дней, 30 дней)
- 3 интерактивных графика (Recharts):
- CPU Usage (Area Chart)
- Memory + Disk (Line Chart)
- Network Traffic (Area Chart)
- Автообновление каждую минуту
2. **Интеграция**:
- Встроен в панель управления сервером
- Вкладка "Мониторинг" теперь показывает реальные данные
## 🚀 Установка
### 1. SQL миграция:
```bash
cd /var/www/ospab-host/backend
mysql -u root -p ospabhost < prisma/migrations/add_server_metrics.sql
```
### 2. Обновление Prisma:
```bash
cd /var/www/ospab-host/backend
npx prisma generate
```
### 3. Сборка backend:
```bash
npm run build
pm2 restart ospab-backend
```
### 4. Сборка frontend:
```bash
cd /var/www/ospab-host/frontend
npm install recharts
npm run build
# Деплой dist/
```
## 📈 Как работает
### Сбор данных:
1. Frontend запрашивает `/api/server/:id/metrics`
2. Backend получает данные от Proxmox API
3. Данные сохраняются в таблицу `server_metrics`
4. Возвращаются пользователю
### Графики:
1. Frontend запрашивает историю за период
2. Backend агрегирует данные с интервалами:
- 1h → каждую минуту
- 6h → каждые 5 минут
- 24h → каждые 15 минут
- 7d → каждый час
- 30d → каждые 6 часов
3. Recharts строит интерактивные графики
### Автоочистка (рекомендуется):
Добавьте cron-задачу для удаления старых метрик:
```sql
-- Удалять метрики старше 30 дней
DELETE FROM server_metrics WHERE timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY);
```
Или в crontab:
```bash
0 2 * * * mysql -u root -pПАРОЛЬ ospabhost -e "DELETE FROM server_metrics WHERE timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY);"
```
## 🎨 Внешний вид
### Карточки метрик:
- **CPU**: Процент загрузки с цветовой индикацией
- **Память**: Процент + используемый объём / всего
- **Диск**: Процент + используемый объём / всего
- **Сеть**: Входящий/исходящий трафик + Uptime
### Графики:
- **CPU**: Плавная заливка оранжевым
- **Memory/Disk**: Двойной линейный график (синий/зелёный)
- **Network**: Двойная заливка (фиолетовый/розовый)
## 🔧 API примеры
### Получить текущие метрики:
```bash
curl -H "Authorization: Bearer TOKEN" \
http://localhost:5000/api/server/1/metrics
```
Ответ:
```json
{
"status": "success",
"data": {
"vmid": 105,
"status": "running",
"uptime": 3600,
"cpu": 0.15,
"memory": {
"used": 536870912,
"max": 1073741824,
"usage": 50.0
},
"disk": {
"used": 2147483648,
"max": 10737418240,
"usage": 20.0
},
"network": {
"in": 1048576,
"out": 524288
}
}
}
```
### Получить историю:
```bash
curl -H "Authorization: Bearer TOKEN" \
"http://localhost:5000/api/server/1/metrics/history?period=24h"
```
Ответ:
```json
{
"status": "success",
"period": "24h",
"data": [
{
"timestamp": "2025-11-01T10:00:00.000Z",
"cpuUsage": 15.2,
"memoryUsage": 48.5,
"diskUsage": 20.1,
"networkIn": 1048576,
"networkOut": 524288,
"status": "running"
}
],
"total": 96
}
```
### Получить сводку:
```bash
curl -H "Authorization: Bearer TOKEN" \
http://localhost:5000/api/server/1/metrics/summary
```
Ответ:
```json
{
"status": "success",
"data": {
"cpu": { "avg": 12.5, "max": 45.2, "min": 2.1 },
"memory": { "avg": 48.3, "max": 72.1, "min": 35.2 },
"disk": { "avg": 20.0, "max": 21.5, "min": 19.8 },
"network": {
"totalIn": 104857600,
"totalOut": 52428800
},
"uptime": 86400
}
}
```
## 🔒 Безопасность
-Все endpoints требуют авторизации (authMiddleware)
- ✅ Пользователь видит только метрики своих серверов
- ✅ CASCADE DELETE - метрики удаляются вместе с сервером
- ✅ Нет лимитов на количество запросов (можно добавить rate limiting)
## 📊 База данных
Структура таблицы:
```sql
CREATE TABLE `server_metrics` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`serverId` INT NOT NULL,
`cpuUsage` DOUBLE DEFAULT 0,
`memoryUsage` DOUBLE DEFAULT 0,
`memoryUsed` BIGINT DEFAULT 0,
`memoryMax` BIGINT DEFAULT 0,
`diskUsage` DOUBLE DEFAULT 0,
`diskUsed` BIGINT DEFAULT 0,
`diskMax` BIGINT DEFAULT 0,
`networkIn` BIGINT DEFAULT 0,
`networkOut` BIGINT DEFAULT 0,
`status` VARCHAR(191) DEFAULT 'unknown',
`uptime` BIGINT DEFAULT 0,
`timestamp` DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
INDEX `server_metrics_serverId_timestamp_idx` (`serverId`, `timestamp`),
FOREIGN KEY (`serverId`) REFERENCES `server`(`id`) ON DELETE CASCADE
);
```
Размер записи: ~100 байт
При частоте 1 метрика/минуту: ~144 KB/день/сервер
## 🎯 Рекомендации
1. **Cron для сбора метрик**:
Создайте задачу, которая каждые 5 минут запрашивает метрики всех серверов:
```javascript
// backend/src/cron/collectMetrics.ts
import { PrismaClient } from '@prisma/client';
import { getContainerStats } from './modules/server/proxmoxApi';
const prisma = new PrismaClient();
async function collectAllMetrics() {
const servers = await prisma.server.findMany({
where: { status: 'running' }
});
for (const server of servers) {
if (!server.proxmoxId) continue;
try {
const stats = await getContainerStats(server.proxmoxId);
if (stats.status === 'success' && stats.data) {
await prisma.serverMetric.create({ /* ... */ });
}
} catch (err) {
console.error(`Ошибка сбора метрик для сервера ${server.id}:`, err);
}
}
}
// Запускать каждые 5 минут
setInterval(collectAllMetrics, 5 * 60 * 1000);
```
2. **Партиционирование таблицы** (для высоких нагрузок):
```sql
ALTER TABLE server_metrics
PARTITION BY RANGE (YEAR(timestamp) * 100 + MONTH(timestamp)) (
PARTITION p202511 VALUES LESS THAN (202512),
PARTITION p202512 VALUES LESS THAN (202601),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
```
3. **Кэширование**:
Добавьте Redis для кэширования текущих метрик (TTL 30 секунд).
## 📝 Changelog
**1 ноября 2025**:
- ✅ Добавлена модель ServerMetric в Prisma
- ✅ Созданы 3 API endpoint'а для метрик
- ✅ Реализован компонент ServerMetrics с графиками
- ✅ Интегрирован в панель управления сервером
- ✅ Установлена библиотека Recharts для графиков
- ✅ Добавлена SQL миграция
## 🐛 Troubleshooting
**Проблема**: Графики не отображаются
- Проверьте консоль браузера на ошибки API
- Убедитесь, что сервер запущен и метрики собираются
- Проверьте, что таблица `server_metrics` создана
**Проблема**: "Cannot read property 'cpu' of undefined"
- Сервер ещё не имеет метрик в БД
- Подождите 1-2 минуты после создания сервера
- Вручную запросите `/api/server/:id/metrics`
**Проблема**: Слишком большая база данных
- Настройте автоочистку старых метрик (см. выше)
- Уменьшите частоту сбора данных
- Используйте партиционирование
## 🎉 Готово!
Теперь у вас полноценная система мониторинга с:
- ✅ Реал-тайм метриками
- ✅ Интерактивными графиками
- ✅ Историей данных
- ✅ Красивым интерфейсом
- ✅ Автоматическим обновлением
Пользователи могут отслеживать нагрузку на свои серверы в режиме реального времени! 🚀

View File

@@ -1,154 +0,0 @@
# Nginx Deployment Guide for ospab.host
## Prerequisites
- Ubuntu 20.04+ или Debian 11+
- Nginx 1.18+
- Node.js 18+
- PM2 (для управления процессами)
- Certbot (для SSL)
## Installation
### 1. Install Nginx
```bash
sudo apt update
sudo apt install nginx -y
```
### 2. Install Certbot
```bash
sudo apt install certbot python3-certbot-nginx -y
```
### 3. Setup SSL Certificate
```bash
# Stop nginx temporarily
sudo systemctl stop nginx
# Get certificate
sudo certbot certonly --standalone -d ospab.host -d www.ospab.host
# Restart nginx
sudo systemctl start nginx
```
### 4. Deploy Nginx Configuration
```bash
# Copy config
sudo cp nginx.conf /etc/nginx/sites-available/ospab.host
# Create symlink
sudo ln -s /etc/nginx/sites-available/ospab.host /etc/nginx/sites-enabled/
# Remove default config
sudo rm /etc/nginx/sites-enabled/default
# Test configuration
sudo nginx -t
# Reload nginx
sudo systemctl reload nginx
```
### 5. Deploy Application
```bash
# Create deployment directory
sudo mkdir -p /var/www/ospab.host
# Clone repository
cd /var/www/ospab.host
git clone https://github.com/YOUR_REPO/ospabhost8.1.git .
# Build frontend
cd frontend
npm install
npm run build
# Build backend
cd ../backend
npm install
npm run build
# Start backend with PM2
pm2 start dist/index.js --name "ospab-backend"
pm2 save
pm2 startup
```
## Directory Structure
```
/var/www/ospab.host/
├── frontend/
│ └── dist/ # React SPA build output
├── backend/
│ ├── dist/ # Compiled TypeScript
│ └── uploads/ # Uploaded files
└── nginx.conf # Nginx configuration
```
## Useful Commands
```bash
# Check nginx status
sudo systemctl status nginx
# Reload nginx config
sudo nginx -t && sudo systemctl reload nginx
# View logs
sudo tail -f /var/log/nginx/ospab.host.access.log
sudo tail -f /var/log/nginx/ospab.host.error.log
# PM2 commands
pm2 status
pm2 logs ospab-backend
pm2 restart ospab-backend
# Renew SSL certificate
sudo certbot renew --dry-run
```
## Rate Limiting
- API endpoints: 10 requests/second (burst 20)
- Login/Register: 5 requests/minute (burst 5)
## Security Features
- HSTS enabled
- XSS Protection
- Frame Options (SAMEORIGIN)
- Content-Type sniffing prevention
- Blocked access to .git, .env, node_modules
- Blocked sensitive file extensions (.sql, .bak, .log)
## SSL Auto-Renewal
Add to crontab:
```bash
sudo crontab -e
# Add line:
0 12 * * * /usr/bin/certbot renew --quiet
```
## Troubleshooting
### 502 Bad Gateway
- Check if backend is running: `pm2 status`
- Check backend logs: `pm2 logs ospab-backend`
### 504 Gateway Timeout
- Increase `proxy_read_timeout` in nginx config
- Check backend performance
### SSL Issues
- Check certificate: `sudo certbot certificates`
- Renew if needed: `sudo certbot renew`

View File

@@ -1,259 +0,0 @@
# Исправление Push-уведомлений
## Проблема
Push-уведомления не работали по следующим причинам:
### 1. **Кнопка "Включить уведомления" не зависела от состояния разрешения**
#### До:
```tsx
{!pushEnabled && 'Notification' in window && (
<button onClick={handleEnablePush}>Включить уведомления</button>
)}
```
**Проблема:** Кнопка показывалась, даже если пользователь заблокировал уведомления (`Notification.permission === 'denied'`). Клик по ней приводил к ошибке, так как браузер не давал повторно запросить разрешение.
#### После:
```tsx
{!pushEnabled && 'Notification' in window && pushPermission !== 'denied' && (
<button onClick={handleEnablePush}>Включить уведомления</button>
)}
{pushPermission === 'denied' && (
<div className="alert alert-warning">
Push-уведомления заблокированы. Разрешите их в настройках браузера.
</div>
)}
```
**Решение:**
- Кнопка показывается только когда `pushPermission === 'default'` (не запрашивалось)
- Если `pushPermission === 'denied'`, показывается предупреждение с инструкцией
### 2. **Service Worker мог не копироваться в dist при сборке**
#### До:
```typescript
// vite.config.ts
export default defineConfig({
plugins: [react()],
})
```
**Проблема:** Файл `public/service-worker.js` не копировался автоматически в `dist/` при сборке, что приводило к 404 ошибке при регистрации.
#### После:
```typescript
export default defineConfig({
plugins: [
react(),
{
name: 'copy-service-worker',
writeBundle() {
copyFileSync(
resolve(__dirname, 'public/service-worker.js'),
resolve(__dirname, 'dist/service-worker.js')
)
console.log('✅ Service worker скопирован в dist/')
}
}
],
})
```
**Решение:** Добавлен плагин Vite, который автоматически копирует `service-worker.js` в корень `dist/` при каждой сборке.
### 3. **Недостаточная диагностика ошибок**
#### До:
```typescript
console.error('Ошибка подключения Push-уведомлений:', error);
```
#### После:
```typescript
console.log('📝 Регистрируем Service Worker...');
const registration = await navigator.serviceWorker.register('/service-worker.js');
console.log('✅ Service Worker зарегистрирован:', registration);
console.log('📝 Получаем VAPID ключ...');
const vapidPublicKey = await getVapidKey();
console.log('✅ VAPID ключ получен:', vapidPublicKey.substring(0, 20) + '...');
console.log('📝 Создаём Push подписку...');
const subscription = await registration.pushManager.subscribe({...});
console.log('✅ Push подписка создана:', subscription.endpoint);
```
**Решение:** Добавлены подробные логи на каждом этапе подключения Push-уведомлений для быстрой диагностики проблем.
## Архитектура Push-уведомлений
### Frontend (`notificationService.ts`)
```
1. Notification.requestPermission() → Запрос разрешения
2. navigator.serviceWorker.register() → Регистрация SW
3. GET /api/notifications/vapid-key → Получение публичного ключа
4. registration.pushManager.subscribe() → Создание подписки
5. POST /api/notifications/subscribe-push → Отправка подписки на сервер
```
### Backend
```
1. GET /api/notifications/vapid-key → Возвращает VAPID_PUBLIC_KEY из .env
2. POST /api/notifications/subscribe-push → Сохраняет подписку в PushSubscription
3. Отправка уведомлений → webpush.sendNotification() для каждой подписки
```
### Service Worker (`public/service-worker.js`)
```javascript
self.addEventListener('push', (event) => {
const data = event.data.json();
self.registration.showNotification(data.title, {
body: data.body,
icon: data.icon || '/favicon.svg',
...
});
});
```
## Проверка работы
### 1. Проверка VAPID ключей
```bash
curl https://ospab.host:5000/api/notifications/vapid-key \
-H "Authorization: Bearer YOUR_TOKEN"
```
Должен вернуть:
```json
{
"success": true,
"publicKey": "BPtLNi3TY1ifUWTkgZrhxoEH6ihDgknFcgzc3xzFQg07PeuJ1TsJDQZqA32VqlxUo03g_mG0yKCKqADb4r5fnsM"
}
```
### 2. Проверка Service Worker
Откройте `https://ospab.host` → DevTools → Application → Service Workers
Должен быть зарегистрирован: `/service-worker.js` со статусом **Activated**
### 3. Проверка подписки
После нажатия "Включить уведомления" в консоли должны появиться:
```
📝 Запрашиваем разрешение на уведомления...
📝 Результат запроса разрешения: granted
📝 Регистрируем Service Worker...
✅ Service Worker зарегистрирован: ServiceWorkerRegistration {...}
📝 Ожидаем готовности Service Worker...
✅ Service Worker готов
📝 Получаем VAPID ключ...
✅ VAPID ключ получен: BPtLNi3TY1ifUWTk...
📝 Создаём Push подписку...
✅ Push подписка создана: https://fcm.googleapis.com/fcm/send/...
📝 Отправляем подписку на сервер...
✅ Push-уведомления успешно подключены
```
### 4. Проверка в базе данных
```sql
SELECT * FROM PushSubscription WHERE userId = YOUR_USER_ID;
```
Должна быть запись с endpoint, p256dh, auth.
### 5. Тестовая отправка
Можно создать тестовую отправку через backend:
```typescript
import { sendPushNotification } from './modules/notification/push.service';
await sendPushNotification(userId, {
title: 'Тестовое уведомление',
body: 'Push-уведомления работают!',
icon: '/logo192.png'
});
```
## Состояния Notification.permission
| Состояние | Описание | UI |
|-----------|----------|-----|
| `default` | Разрешение не запрашивалось | Показывается синяя кнопка "Включить уведомления" |
| `granted` | Разрешение получено | Кнопка скрыта, уведомления работают |
| `denied` | Пользователь заблокировал | Показывается красное предупреждение с инструкцией |
## Разблокировка в браузерах
### Chrome/Edge
1. Нажмите на иконку 🔒 (замок) слева от адресной строки
2. Найдите "Уведомления"
3. Выберите "Разрешить"
4. Обновите страницу
### Firefox
1. Откройте Настройки → Приватность и защита
2. Прокрутите до раздела "Разрешения"
3. Нажмите "Настройки" рядом с "Уведомления"
4. Найдите `ospab.host` и измените на "Разрешить"
### Safari
1. Safari → Настройки → Веб-сайты
2. Выберите "Уведомления"
3. Найдите `ospab.host` и выберите "Разрешить"
## Файлы изменены
1.`frontend/src/pages/dashboard/notifications.tsx`
- Добавлено состояние `pushPermission`
- Условный рендеринг кнопки/предупреждения
- Обновление состояния после запроса
2.`frontend/src/services/notificationService.ts`
- Добавлены подробные логи в `requestPushPermission()`
- Эмодзи-маркеры для быстрого поиска в консоли
3.`frontend/vite.config.ts`
- Плагин копирования `service-worker.js` в `dist/`
## Деплой
```bash
# Frontend
cd frontend
npm run build
# Скопируйте dist/ на production сервер
# Backend (если были изменения)
cd backend
npm run build
pm2 restart ospab-backend
```
## Возможные проблемы
### Service Worker не регистрируется
- **Проверка:** DevTools → Application → Service Workers
- **Причина:** Файл `service-worker.js` не доступен по адресу `https://ospab.host/service-worker.js`
- **Решение:** Убедитесь, что файл скопирован в корень `dist/` и доступен через nginx
### 403 Forbidden при запросе VAPID ключа
- **Проверка:** Network → `/api/notifications/vapid-key` → Response
- **Причина:** Не передаётся токен авторизации
- **Решение:** Проверьте, что в localStorage есть `access_token`
### Push-уведомления не приходят
- **Проверка:** Console → Ошибки от `webpush.sendNotification()`
- **Причина:** Неправильные VAPID ключи или подписка устарела
- **Решение:** Перегенерируйте VAPID ключи (`npx web-push generate-vapid-keys`) и переподпишитесь
### Подписка создаётся, но не сохраняется в БД
- **Проверка:** Console → Network → `/api/notifications/subscribe-push` → Response
- **Причина:** Ошибка на backend при сохранении в Prisma
- **Решение:** Проверьте логи backend (`pm2 logs ospab-backend`)
---
**Статус:** ✅ Исправлено и готово к тестированию
**Дата:** 2025-01-20

View File

@@ -1,264 +0,0 @@
# Тестовая отправка Push-уведомлений
## Что добавлено
В админ-панели теперь есть кнопка **"🧪 Тест Push-уведомления"** с подробным логированием всего процесса отправки.
### Backend endpoint
**POST** `/api/notifications/test-push`
- ✅ Требует авторизацию (Bearer token)
- ✅ Требует права администратора (`isAdmin: true`)
- ✅ Подробное логирование каждого шага
### Frontend кнопка
Расположена в **Админ-панели** (правый верхний угол).
## Логирование
### Backend логи (консоль сервера)
```
🧪 [TEST PUSH] Запрос от пользователя: { userId: 1, username: 'admin' }
✅ [TEST PUSH] Пользователь является админом, продолжаем...
📊 [TEST PUSH] Найдено подписок для пользователя 1: 2
📱 Подписка 1: { id: 123, endpoint: 'https://fcm.googleapis...', userAgent: 'Mozilla/5.0...', ... }
📱 Подписка 2: { id: 124, endpoint: 'https://fcm.googleapis...', userAgent: 'Chrome...', ... }
📝 [TEST PUSH] Создаём тестовое уведомление в БД...
✅ [TEST PUSH] Уведомление создано в БД: 456
📤 [TEST PUSH] Отправляем Push-уведомление...
✅ [TEST PUSH] Push-уведомление успешно отправлено!
```
### Frontend логи (консоль браузера)
```
🧪 [FRONTEND] Начинаем тестовую отправку Push-уведомления...
📝 [FRONTEND] Токен найден: Да
📤 [FRONTEND] Отправляем запрос на: https://ospab.host:5000/api/notifications/test-push
✅ [FRONTEND] Ответ от сервера: { success: true, message: '...', data: { notificationId: 456, subscriptionsCount: 2 } }
📊 [FRONTEND] Детали: { notificationId: 456, subscriptionsCount: 2 }
```
## Как использовать
### 1. Включите Push-уведомления
1. Перейдите в **Дашборд → Уведомления**
2. Нажмите **"Включить уведомления"** (синяя кнопка)
3. Разрешите уведомления в браузере
4. Дождитесь сообщения **"Push-уведомления успешно подключены!"**
### 2. Откройте админ-панель
1. Перейдите в **Дашборд → Админ-панель** (👑 иконка в сайдбаре)
2. В правом верхнем углу увидите кнопку **"🧪 Тест Push-уведомления"**
### 3. Нажмите кнопку
1. Откройте **DevTools → Console** (F12)
2. Нажмите **"🧪 Тест Push-уведомления"**
3. Следите за логами в консоли браузера
### 4. Проверьте сервер
Откройте консоль сервера (SSH):
```bash
pm2 logs ospab-backend --lines 50
```
Увидите подробные логи с эмодзи-маркерами.
### 5. Проверьте результат
Через несколько секунд должно прийти Push-уведомление:
- **Заголовок:** 🧪 Тестовое уведомление
- **Текст:** Это тестовое Push-уведомление. Если вы его видите — всё работает отлично!
- **Иконка:** /logo192.png
- **Клик:** Перенаправляет на /dashboard/notifications
## Возможные ошибки
### ❌ "У вас нет прав администратора" (403)
**Причина:** Пользователь не является администратором.
**Решение:**
```sql
UPDATE User SET isAdmin = 1 WHERE id = YOUR_USER_ID;
```
### ❌ "У вас нет активных Push-подписок" (400)
**Причина:** Push-уведомления не включены.
**Решение:**
1. Перейдите в **Дашборд → Уведомления**
2. Нажмите **"Включить уведомления"**
3. Разрешите в браузере
4. Попробуйте снова
### ❌ "Уведомление создано в БД, но ошибка при отправке Push" (500)
**Причины:**
1. Неправильные VAPID ключи
2. Подписка устарела
3. Проблема с web-push библиотекой
**Решение:**
**Проверьте VAPID ключи:**
```bash
cd /var/www/ospab-host/backend
cat .env | grep VAPID
```
Должны быть заполнены:
```
VAPID_PUBLIC_KEY=BPtLNi3TY1ifUWTkgZrhxoEH6ihDgknFcgzc3xzFQg07PeuJ1TsJDQZqA32VqlxUo03g_mG0yKCKqADb4r5fnsM
VAPID_PRIVATE_KEY=5uEJBxEzCLhcMBPyGEw_GDx9JDneb6poZiX8f3b0zNE
VAPID_SUBJECT=mailto:support@ospab.host
```
**Пересоздайте подписку:**
1. Удалите старую: `DELETE FROM PushSubscription WHERE userId = YOUR_USER_ID;`
2. Перейдите в **Дашборд → Уведомления**
3. Включите уведомления заново
### ❌ 410 Gone - Подписка устарела
**Причина:** Push подписка больше недействительна (браузер её отозвал).
**Решение:** Сервис автоматически удаляет устаревшие подписки. Пересоздайте подписку (см. выше).
## Диагностика проблем
### Проверка подписок в БД
```sql
SELECT
ps.id,
ps.userId,
ps.endpoint,
ps.userAgent,
ps.createdAt,
ps.lastUsed,
u.username
FROM PushSubscription ps
JOIN User u ON ps.userId = u.id
ORDER BY ps.createdAt DESC;
```
### Проверка уведомлений в БД
```sql
SELECT * FROM Notification
WHERE type = 'test'
ORDER BY createdAt DESC
LIMIT 10;
```
### Проверка Service Worker
1. Откройте сайт в браузере
2. DevTools (F12) → Application → Service Workers
3. Должен быть зарегистрирован `/service-worker.js` со статусом **Activated**
### Проверка VAPID ключа через API
```bash
curl https://ospab.host:5000/api/notifications/vapid-key \
-H "Authorization: Bearer YOUR_TOKEN"
```
Должен вернуть:
```json
{
"success": true,
"publicKey": "BPtLNi3TY1ifUWTkgZrhxoEH6ihDgknFcgzc3xzFQg07PeuJ1TsJDQZqA32VqlxUo03g_mG0yKCKqADb4r5fnsM"
}
```
## Что логируется
### Backend
| Эмодзи | Описание |
|--------|----------|
| 🧪 | Начало тестовой отправки |
| ✅ | Успешный этап |
| ❌ | Ошибка |
| 📊 | Статистика/данные |
| 📱 | Информация о подписке |
| 📝 | Создание записи |
| 📤 | Отправка |
| ⚠️ | Предупреждение |
### Frontend
| Эмодзи | Описание |
|--------|----------|
| 🧪 | Начало процесса |
| 📝 | Проверка данных |
| 📤 | Отправка запроса |
| ✅ | Успешный ответ |
| ❌ | Ошибка |
| 📊 | Детали ответа |
| 📋 | Детали ошибки |
## Ручная отправка через код
Если нужно отправить тестовое уведомление программно:
```typescript
import { sendPushNotification } from './modules/notification/push.service';
// В любом месте backend кода
await sendPushNotification(userId, {
title: 'Заголовок',
body: 'Текст уведомления',
icon: '/logo192.png',
badge: '/favicon.svg',
data: {
notificationId: 123,
actionUrl: '/dashboard'
}
});
```
## Файлы изменены
1.`backend/src/modules/notification/notification.controller.ts`
- Добавлен `testPushNotification()` с подробным логированием
2.`backend/src/modules/notification/notification.routes.ts`
- Добавлен роут `POST /api/notifications/test-push`
3.`frontend/src/pages/dashboard/admin.tsx`
- Добавлена кнопка тестовой отправки
- Добавлен `handleTestPushNotification()` с логированием
- Состояние `testingPush` для индикации загрузки
## Деплой
```bash
# Backend
cd /var/www/ospab-host/backend
npm run build
pm2 restart ospab-backend
# Frontend
cd /var/www/ospab-host/frontend
npm run build
# Скопируйте dist/ в web root
# Проверка логов
pm2 logs ospab-backend --lines 100
```
---
**Статус:** ✅ Готово к тестированию
**Дата:** 2025-11-01

View File

@@ -1,374 +0,0 @@
# Где должно появиться Push-уведомление?
## 🎯 Правильный ответ: В СИСТЕМНЫХ УВЕДОМЛЕНИЯХ
Push-уведомления - это **НЕ уведомления на сайте**, а **системные уведомления браузера/ОС**.
### Windows
- Появляются в **правом нижнем углу экрана** (Action Center)
- Выглядят как обычные Windows уведомления
- Звук уведомления (если включен)
### macOS
- Появляются в **правом верхнем углу** экрана
- Стиль нативных macOS уведомлений
### Linux
- Зависит от DE (GNOME, KDE, etc.)
- Обычно верхний правый или верхний центр
### Android/iOS (мобильные браузеры)
- В панели уведомлений телефона
- Как обычные push-уведомления приложений
---
## ❓ Почему уведомление может не появиться?
### 1. Уведомления заблокированы в браузере
**Проверка:**
1. Откройте сайт
2. Нажмите на **иконку замка** 🔒 слева от адресной строки
3. Найдите "Уведомления"
4. Должно быть **"Разрешить"** (Allow)
**Решение:**
```
Chrome/Edge: 🔒 → Уведомления → Разрешить → Обновить страницу
Firefox: Меню → Настройки → Приватность → Разрешения → Уведомления
```
---
### 2. Уведомления заблокированы в ОС
#### Windows 10/11
1. **Параметры → Система → Уведомления и действия**
2. Убедитесь, что уведомления **включены глобально**
3. Найдите ваш браузер в списке приложений
4. Убедитесь, что для браузера уведомления **разрешены**
#### macOS
1. **System Preferences → Notifications**
2. Найдите ваш браузер (Chrome, Firefox, Safari)
3. Убедитесь, что уведомления **включены**
#### Linux (GNOME)
```bash
gnome-control-center notifications
```
Проверьте, что уведомления включены для браузера.
---
### 3. Режим "Не беспокоить"
#### Windows
- Проверьте **Action Center** (Win + A)
- Отключите "Фокусировка внимания" (Focus Assist)
#### macOS
- Проверьте, что не включен **Do Not Disturb**
- Notification Center → Отключите DND
---
### 4. Service Worker не зарегистрирован
**Проверка:**
1. Откройте **DevTools** (F12)
2. Вкладка **Application**
3. Слева: **Service Workers**
4. Должен быть зарегистрирован `/service-worker.js` со статусом **"activated and is running"**
**Если нет:**
```javascript
// В консоли браузера
navigator.serviceWorker.getRegistrations().then(regs => {
console.log('Registered Service Workers:', regs.length);
regs.forEach(reg => console.log(reg));
});
```
**Решение:**
1. Перейдите в **Дашборд → Уведомления**
2. Нажмите **"Включить уведомления"** снова
3. Проверьте консоль на ошибки регистрации
---
### 5. Push подписка не создана
**Проверка в консоли браузера:**
```javascript
navigator.serviceWorker.ready.then(reg => {
reg.pushManager.getSubscription().then(sub => {
if (sub) {
console.log('✅ Push подписка существует:', sub.endpoint);
} else {
console.log('❌ Push подписка отсутствует');
}
});
});
```
**Решение:**
Включите уведомления заново на странице "Уведомления".
---
### 6. Ошибка на сервере при отправке
**Проверка логов backend:**
```bash
pm2 logs ospab-backend --lines 100 | grep "TEST PUSH"
```
**Должны увидеть:**
```
✅ [TEST PUSH] Push-уведомление успешно отправлено!
```
**Если ошибка:**
```
❌ [TEST PUSH] Ошибка при отправке Push: ...
```
**Возможные причины:**
- Неправильные VAPID ключи
- Устаревшая подписка (410 Gone)
- Проблемы с сетью
---
## 🧪 Пошаговая диагностика
### Шаг 1: Проверьте разрешения браузера
```javascript
// В консоли браузера
console.log('Notification permission:', Notification.permission);
// Должно быть: "granted"
if (Notification.permission !== 'granted') {
console.log('❌ Уведомления не разрешены!');
console.log('Перейдите в Дашборд → Уведомления → Включить уведомления');
}
```
### Шаг 2: Проверьте Service Worker
```javascript
// В консоли браузера
navigator.serviceWorker.getRegistrations().then(regs => {
if (regs.length === 0) {
console.log('❌ Service Worker не зарегистрирован!');
} else {
console.log('✅ Service Workers найдены:', regs.length);
regs.forEach((reg, i) => {
console.log(` SW ${i+1}:`, reg.active ? '✅ Активен' : '❌ Не активен');
});
}
});
```
### Шаг 3: Проверьте Push подписку
```javascript
// В консоли браузера
navigator.serviceWorker.ready.then(reg => {
reg.pushManager.getSubscription().then(sub => {
if (!sub) {
console.log('❌ Push подписка не найдена!');
console.log('Включите уведомления в разделе "Уведомления"');
} else {
console.log('✅ Push подписка активна');
console.log(' Endpoint:', sub.endpoint);
}
});
});
```
### Шаг 4: Тестовое уведомление вручную
```javascript
// В консоли браузера (для быстрой проверки)
new Notification('Тест', {
body: 'Это локальное тестовое уведомление',
icon: '/logo192.png'
});
```
**Если это уведомление появилось:**
- ✅ Браузер и ОС настроены правильно
- ❌ Проблема в Push-подписке или на сервере
**Если не появилось:**
- ❌ Проблема в настройках браузера/ОС
- Проверьте разрешения (см. выше)
### Шаг 5: Проверьте консоль Service Worker
1. **DevTools → Application → Service Workers**
2. Найдите ваш SW
3. Кликните **"inspect"** или кнопку консоли
4. Откроется отдельная консоль Service Worker
5. Нажмите тестовую кнопку в админке
6. Следите за логами:
```
[Service Worker] Push-уведомление получено
[Service Worker] Показываем уведомление: {...}
```
### Шаг 6: Отправьте тестовое уведомление
1. **Админ-панель → 🧪 Тест Push-уведомления**
2. Откройте **консоль браузера (F12)**
3. Откройте **консоль сервера** (pm2 logs)
4. Нажмите кнопку
5. Проверьте логи в обеих консолях
**Браузер должен показать:**
```
🧪 [FRONTEND] Начинаем тестовую отправку...
📝 [FRONTEND] Токен найден: Да
📤 [FRONTEND] Отправляем запрос...
✅ [FRONTEND] Ответ от сервера: {success: true, ...}
```
**Сервер должен показать:**
```
🧪 [TEST PUSH] Запрос от пользователя: {...}
✅ [TEST PUSH] Push-уведомление успешно отправлено!
```
**Через 1-3 секунды** должно появиться системное уведомление.
---
## 🎬 Видео-пример того, где появляется уведомление
### Chrome на Windows
```
┌─────────────────────────────────────┐
│ 🧪 Тестовое уведомление │
│ Это тестовое Push-уведомление. │
│ Если вы его видите — всё работает │
│ │
│ [Закрыть] [Открыть сайт] │
└─────────────────────────────────────┘
Появляется в правом нижнем углу
```
### Firefox на Windows
```
┌──────────────────────────────┐
│ 🧪 Тестовое уведомление │
│ Это тестовое Push-уведомле │
│ ние. Если вы его видите... │
│ │
│ [×] │
└──────────────────────────────┘
Правый нижний угол
```
### Chrome на macOS
```
┌─────────────────────────────────┐
│ ospab.host │
│ 🧪 Тестовое уведомление │
│ Это тестовое Push-уведомление │
└─────────────────────────────────┘
Правый верхний угол
```
---
## 🔧 Быстрое решение проблем
### "Уведомление не появляется вообще"
1. **Проверьте консоль браузера** на ошибки
2. **Проверьте pm2 logs** на ошибки сервера
3. **Попробуйте локальное уведомление:**
```javascript
new Notification('Тест', {body: 'Тест'});
```
4. Если локальное появилось → проблема в Push-подписке
5. Если локальное не появилось → проблема в разрешениях
### "Ошибка 400 - нет активных подписок"
1. **Дашборд → Уведомления**
2. **"Включить уведомления"**
3. **Разрешить** в браузере
4. Попробуйте снова
### "Ошибка 403 - нет прав администратора"
```sql
UPDATE User SET isAdmin = 1 WHERE id = YOUR_USER_ID;
```
### "Ошибка 500 при отправке Push"
```bash
# Проверьте VAPID ключи
cd /var/www/ospab-host/backend
cat .env | grep VAPID
# Должны быть заполнены
VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:support@ospab.host
```
---
## ✅ Чеклист перед тестированием
- [ ] Уведомления разрешены в браузере (🔒 → Уведомления → Разрешить)
- [ ] Уведомления разрешены в ОС (Windows: Параметры → Уведомления)
- [ ] Режим "Не беспокоить" отключен
- [ ] Service Worker зарегистрирован (DevTools → Application → Service Workers)
- [ ] Push подписка создана (консоль: `navigator.serviceWorker.ready.then(...)`)
- [ ] Вы являетесь администратором (isAdmin: true в БД)
- [ ] Backend запущен (pm2 list → ospab-backend → online)
- [ ] VAPID ключи настроены в .env
---
## 📞 Если ничего не помогает
1. **Очистите всё и начните заново:**
```javascript
// В консоли браузера
navigator.serviceWorker.getRegistrations().then(regs => {
regs.forEach(reg => reg.unregister());
console.log('Service Workers удалены');
});
// Удалите из БД
// DELETE FROM PushSubscription WHERE userId = YOUR_ID;
// Обновите страницу (Ctrl+Shift+R)
// Включите уведомления заново
```
2. **Попробуйте другой браузер** (Chrome vs Firefox)
3. **Попробуйте режим инкогнито** (чтобы исключить расширения)
4. **Проверьте файрвол** - может блокировать FCM (Firebase Cloud Messaging)
5. **Проверьте антивирус** - может блокировать уведомления
---
**Итог:** Push-уведомление должно появиться как **системное уведомление** в углу экрана, а **НЕ** на сайте как элемент интерфейса!

View File

@@ -1,139 +0,0 @@
# Конфигурация сети и хранилища для Proxmox
## Обзор
Теперь вы можете настроить сетевой интерфейс и диск для контейнеров/VM через переменные окружения в `.env` файле.
## Переменные окружения
### 1. Сетевой мост (Network Bridge)
```env
PROXMOX_NETWORK_BRIDGE=vmbr0
```
**Как узнать доступные мосты:**
1. Войдите в Proxmox веб-интерфейс
2. Перейдите: `Datacenter → Node (sv1) → Network`
3. Посмотрите список доступных мостов (обычно `vmbr0`, `vmbr1`, `vmbr2`)
**Изменение:**
- Просто измените значение в `.env` на нужный мост
- Например: `PROXMOX_NETWORK_BRIDGE=vmbr1`
### 2. Хранилище для дисков (Storage)
```env
PROXMOX_VM_STORAGE=local
PROXMOX_BACKUP_STORAGE=local
PROXMOX_ISO_STORAGE=local
```
**Как узнать доступные хранилища:**
1. Войдите в Proxmox веб-интерфейс
2. Перейдите: `Datacenter → Storage`
3. Посмотрите список доступных хранилищ (обычно `local`, `local-lvm`, `nfs-storage`)
**Изменение:**
- Измените значения в `.env` на нужные хранилища
- Например: `PROXMOX_VM_STORAGE=local-lvm`
## Применение изменений
После изменения `.env` файла:
### На локальной машине (разработка):
```bash
cd backend
npm run build
npm run dev
```
### На production сервере:
```bash
cd /var/www/ospab-host/ospabhost/backend
# 1. Редактируем .env файл
vim .env
# 2. Изменяем нужные переменные
# PROXMOX_NETWORK_BRIDGE=vmbr1 # например, на другой мост
# PROXMOX_VM_STORAGE=local-lvm # например, на другое хранилище
# 3. Пересобираем и перезапускаем
npm run build
pm2 restart ospab-backend
# 4. Проверяем логи
pm2 logs ospab-backend --lines 30
```
## Проверка настроек
После создания нового контейнера проверьте его конфигурацию:
```bash
# SSH на Proxmox сервер
ssh root@sv1.ospab.host
# Посмотреть конфигурацию контейнера (замените 100 на VMID)
pct config 100
# Проверить сетевой интерфейс (должен показать ваш мост)
# net0: name=eth0,bridge=vmbr0,ip=dhcp
# Проверить хранилище (должен показать ваше хранилище)
# rootfs: local:100/vm-100-disk-0.raw,size=20G
```
## Примеры конфигураций
### Конфигурация 1: Стандартная (по умолчанию)
```env
PROXMOX_NETWORK_BRIDGE=vmbr0
PROXMOX_VM_STORAGE=local
```
### Конфигурация 2: Отдельная сеть + LVM хранилище
```env
PROXMOX_NETWORK_BRIDGE=vmbr1
PROXMOX_VM_STORAGE=local-lvm
```
### Конфигурация 3: NFS хранилище
```env
PROXMOX_NETWORK_BRIDGE=vmbr0
PROXMOX_VM_STORAGE=nfs-storage
PROXMOX_BACKUP_STORAGE=nfs-storage
```
## Решение проблем
### Ошибка: "storage 'xxx' does not exist"
- Проверьте, что хранилище существует в Proxmox (Datacenter → Storage)
- Убедитесь, что имя написано правильно (чувствительно к регистру)
### Ошибка: "bridge 'xxx' does not exist"
- Проверьте, что мост существует в Proxmox (Node → Network)
- Убедитесь, что имя написано правильно (обычно `vmbr0`, `vmbr1`)
### Контейнер создаётся, но не имеет сети
- Проверьте, что мост активен и настроен правильно
- Убедитесь, что DHCP работает в вашей сети (или используйте статический IP)
## Логирование
При создании контейнера в логах backend вы увидите:
```
Создание LXC контейнера с параметрами: {
...
net0: 'name=eth0,bridge=vmbr0,ip=dhcp',
rootfs: 'local:20',
...
}
```
Проверьте эти значения, чтобы убедиться, что используются правильные настройки.

View File

@@ -1,132 +0,0 @@
# PM2 Шпаргалка
## 🚀 Основные команды
```bash
# Запуск
pm2 start ecosystem.config.js --env production
# Остановка
pm2 stop ospab-backend
# Перезапуск (без даунтайма)
pm2 reload ospab-backend
# Полный перезапуск
pm2 restart ospab-backend
# Удаление из PM2
pm2 delete ospab-backend
# Список процессов
pm2 list
# Детальная информация
pm2 show ospab-backend
```
## 📊 Мониторинг
```bash
# Логи в реальном времени
pm2 logs ospab-backend
# Последние 100 строк
pm2 logs ospab-backend --lines 100
# Только ошибки
pm2 logs ospab-backend --err
# Очистка логов
pm2 flush
# Интерактивный мониторинг
pm2 monit
```
## 💾 Сохранение и автозапуск
```bash
# Сохранить текущую конфигурацию
pm2 save
# Настроить автозапуск при перезагрузке
pm2 startup
# Отменить автозапуск
pm2 unstartup
# Удалить сохранённую конфигурацию
pm2 kill
```
## 🔧 Управление через npm
```bash
npm run pm2:start # Запуск
npm run pm2:stop # Остановка
npm run pm2:restart # Перезапуск
npm run pm2:logs # Логи
npm run pm2:monit # Мониторинг
npm run pm2:status # Статус
```
## 📦 Обновление PM2
```bash
# Обновить PM2
npm install -g pm2@latest
# Обновить процессы PM2
pm2 update
```
## 🐛 Отладка
```bash
# Показать переменные окружения
pm2 env 0
# Информация о системе
pm2 info ospab-backend
# Метрики
pm2 describe ospab-backend
```
## ⚡ Быстрые сценарии
### Деплой нового кода
```bash
git pull origin main
cd backend
npm install
npm run build
pm2 reload ospab-backend
pm2 save
```
### Полный перезапуск системы
```bash
pm2 kill
pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup # Выполнить команду, которую выведет
```
### Проверка статуса
```bash
pm2 list
pm2 logs ospab-backend --lines 50
curl http://localhost:5000
```
## 🎯 Текущая конфигурация
- **Название**: ospab-backend
- **Экземпляры**: 4
- **Режим**: cluster
- **Порт**: 5000
- **Логи**: ./logs/pm2-error.log, ./logs/pm2-out.log
- **Автоперезапуск**: Да
- **Лимит памяти**: 500 MB/процесс

View File

@@ -1,186 +0,0 @@
# 🚀 Быстрый старт PM2
## Запуск Backend в 4 экземплярах
### Через npm scripts (рекомендуется):
```bash
# 1. Сборка проекта
npm run build
# 2. Запуск PM2
npm run pm2:start
# 3. Проверка статуса
npm run pm2:status
```
### Через скрипты:
```bash
# Дать права на выполнение (только один раз)
chmod +x start-pm2.sh restart-pm2.sh stop-pm2.sh
# Запуск
./start-pm2.sh
# Перезапуск
./restart-pm2.sh
# Перезапуск с пересборкой
./restart-pm2.sh --build
# Перезапуск с обновлением из Git
./restart-pm2.sh --update
# Остановка
./stop-pm2.sh
```
### Через PM2 напрямую:
```bash
# Запуск
pm2 start ecosystem.config.js --env production
# Сохранение конфигурации
pm2 save
# Настройка автозапуска
pm2 startup
# Выполните команду, которую выведет pm2 startup
```
## ⚙️ Настройка автозапуска
Чтобы backend автоматически запускался при перезагрузке сервера:
```bash
# 1. Запустить процесс
npm run pm2:start
# 2. Настроить автозапуск
pm2 startup
# 3. Выполнить команду, которую выведет pm2 startup
# Например:
# sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u root --hp /root
# 4. Сохранить текущую конфигурацию
pm2 save
```
## 📊 Мониторинг
```bash
# Просмотр логов
npm run pm2:logs
# Интерактивный мониторинг
npm run pm2:monit
# Статус всех процессов
npm run pm2:status
# Детальная информация
pm2 show ospab-backend
```
## 🔄 Обновление кода
```bash
# Вариант 1: Вручную
git pull origin main
npm install
npm run build
npm run pm2:restart
# Вариант 2: Через скрипт
./restart-pm2.sh --update
```
## 🛑 Остановка
```bash
# Через npm
npm run pm2:stop
# Через скрипт
./stop-pm2.sh
# Напрямую
pm2 stop ospab-backend
pm2 delete ospab-backend
pm2 save
```
## 📝 Полезные команды
```bash
# Логи в реальном времени
pm2 logs ospab-backend --lines 100
# Очистка логов
pm2 flush
# Перезапуск без даунтайма
pm2 reload ospab-backend
# Обновление PM2
npm install -g pm2@latest
pm2 update
# Резервная копия конфигурации
pm2 save --force
```
## 🔍 Проверка работы
После запуска проверьте:
```bash
# 1. Статус процессов (должно быть 4 инстанса "online")
pm2 list
# 2. Backend доступен
curl http://localhost:5000
# 3. Логи без ошибок
pm2 logs ospab-backend --lines 50
```
## ⚠️ Устранение проблем
### PM2 не запускается
```bash
# Проверить версию Node.js
node -v
# Переустановить PM2
npm install -g pm2@latest
# Удалить старую конфигурацию
pm2 kill
rm -rf ~/.pm2
# Запустить заново
npm run pm2:start
```
### Процессы крашатся
```bash
# Посмотреть ошибки
pm2 logs ospab-backend --err
# Увеличить лимит памяти в ecosystem.config.js
# max_memory_restart: '1G'
# Уменьшить количество инстансов
# instances: 2
```
## 📚 Подробная документация
См. [PM2_SETUP.md](./PM2_SETUP.md) для детальной информации.

View File

@@ -1,257 +0,0 @@
# Настройка PM2 для Backend
## 📦 Установка PM2 (если ещё не установлен)
```bash
# Глобальная установка PM2
npm install -g pm2
# Проверка версии
pm2 -v
```
## 🚀 Запуск Backend в 4 экземплярах
### Шаг 1: Сборка проекта
```bash
cd /var/www/ospab-host/backend
# или локально:
cd backend
# Установка зависимостей (если нужно)
npm install
# Компиляция TypeScript
npm run build
```
### Шаг 2: Создание папки для логов
```bash
mkdir -p logs
```
### Шаг 3: Запуск с помощью PM2
```bash
# Запуск 4 экземпляров согласно ecosystem.config.js
pm2 start ecosystem.config.js --env production
# Или напрямую (без конфига):
pm2 start dist/src/index.js -i 4 --name ospab-backend
```
### Шаг 4: Сохранение конфигурации для автозапуска
```bash
# Сохранить текущий список процессов
pm2 save
# Настроить автозапуск при перезагрузке сервера
pm2 startup
# Выполните команду, которую выведет pm2 startup
# Обычно это что-то вроде:
# sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u root --hp /root
```
## 📊 Управление процессами
### Просмотр статуса
```bash
# Список всех процессов
pm2 list
# Детальная информация о процессе
pm2 show ospab-backend
# Мониторинг в реальном времени
pm2 monit
```
### Логи
```bash
# Все логи
pm2 logs
# Логи конкретного процесса
pm2 logs ospab-backend
# Последние 100 строк
pm2 logs ospab-backend --lines 100
# Очистка логов
pm2 flush
```
### Перезапуск
```bash
# Перезапуск без даунтайма (рекомендуется)
pm2 reload ospab-backend
# Полный перезапуск (с кратковременным даунтаймом)
pm2 restart ospab-backend
# Остановка
pm2 stop ospab-backend
# Удаление из PM2
pm2 delete ospab-backend
```
## 🔧 Обновление кода (деплой)
### Вариант 1: Автоматический деплой через PM2
```bash
# Из корня проекта
pm2 deploy ecosystem.config.js production
```
### Вариант 2: Ручной деплой
```bash
cd /var/www/ospab-host
# Обновление кода
git pull origin main
# Переход в backend
cd backend
# Установка зависимостей
npm install
# Сборка
npm run build
# Перезапуск без даунтайма
pm2 reload ospab-backend
# Сохранение конфигурации
pm2 save
```
## 📈 Мониторинг и отладка
### Проверка памяти и CPU
```bash
pm2 monit
```
### Веб-интерфейс (опционально)
```bash
# Установка PM2 Plus (бесплатно для мониторинга)
pm2 link <secret_key> <public_key>
# Или просто веб-дашборд
pm2 web
# Откройте http://localhost:9615
```
## ⚙️ Текущая конфигурация
- **Экземпляры**: 4 процесса в кластерном режиме
- **Порт**: 5000 (балансировка внутри PM2)
- **Автоперезапуск**: Да
- **Лимит памяти**: 500 MB на процесс
- **Логи**: `./logs/pm2-error.log` и `./logs/pm2-out.log`
## 🔍 Проверка автозапуска
После перезагрузки сервера:
```bash
# Проверить, что PM2 запустился
pm2 list
# Должен показать 4 экземпляра ospab-backend в статусе "online"
```
## 🛠️ Устранение проблем
### PM2 не запускается при загрузке
```bash
# Удалить старую конфигурацию
pm2 unstartup
# Создать новую
pm2 startup
# Выполните команду, которую выведет
# Сохранить
pm2 save
```
### Процессы крашатся
```bash
# Проверить логи ошибок
pm2 logs ospab-backend --err
# Увеличить лимит памяти в ecosystem.config.js
# max_memory_restart: '1G'
# Перезапустить
pm2 reload ecosystem.config.js
```
### Высокая нагрузка на CPU
```bash
# Уменьшить количество экземпляров
# В ecosystem.config.js:
instances: 2
# Перезапустить
pm2 reload ecosystem.config.js
```
## 📝 Полезные команды
```bash
# Обновить PM2 до последней версии
npm install -g pm2@latest
pm2 update
# Резервная копия конфигурации PM2
pm2 save --force
# Информация о системе
pm2 info ospab-backend
# Метрики производительности
pm2 describe ospab-backend
```
## 🎯 Быстрый старт (TL;DR)
```bash
# 1. Перейти в папку backend
cd backend
# 2. Собрать проект
npm run build
# 3. Создать папку логов
mkdir -p logs
# 4. Запустить PM2
pm2 start ecosystem.config.js --env production
# 5. Сохранить и настроить автозапуск
pm2 save
pm2 startup
# 6. Проверить статус
pm2 list
```
Готово! Backend запущен в 4 экземплярах и будет автоматически запускаться при перезагрузке сервера. 🚀

View File

@@ -1,65 +0,0 @@
# Решение проблемы Foreign Key при удалении тарифов
## Проблема
При попытке удалить тариф через Prisma Studio появляется ошибка:
```
Foreign key constraint violated on the fields: (`tariffId`)
```
## Причина
Тариф используется серверами. MySQL не позволяет удалить тариф, если на него ссылаются записи в таблице `server`.
## Решение
### Способ 1: Безопасный (рекомендуется)
Удаляет только неиспользуемые тарифы, сохраняет серверы.
```bash
mysql -u root -p ospabhost < backend/prisma/safe_tariff_migration.sql
```
### Способ 2: Полная очистка (только для dev!)
Удаляет ВСЕ серверы и тарифы.
```bash
# Сначала бэкап!
mysqldump -u root -p ospabhost > backup.sql
# Потом очистка
mysql -u root -p ospabhost < backend/prisma/clean_slate_migration.sql
```
### Способ 3: Ручное удаление через SQL
```sql
-- 1. Найти тарифы без серверов
SELECT t.id, t.name, COUNT(s.id) as servers
FROM tariff t
LEFT JOIN server s ON s.tariffId = t.id
GROUP BY t.id
HAVING servers = 0;
-- 2. Удалить только неиспользуемые
DELETE FROM tariff WHERE id IN (
SELECT id FROM (
SELECT t.id FROM tariff t
LEFT JOIN server s ON s.tariffId = t.id
GROUP BY t.id
HAVING COUNT(s.id) = 0
) as unused
);
-- 3. Добавить категорию
ALTER TABLE tariff ADD COLUMN category VARCHAR(50) NOT NULL DEFAULT 'vps';
-- 4. Добавить новые тарифы (см. safe_tariff_migration.sql)
```
## Перезапуск backend
```bash
cd backend
npm start
```
Готово! 🎉

View File

@@ -1,149 +0,0 @@
# Решение проблемы 501 "Method not implemented"
## Проблема
При смене root-пароля через Proxmox API получали ошибку:
```
AxiosError: Request failed with status code 501
statusMessage: "Method 'POST /nodes/sv1/lxc/105/config' not implemented"
```
## Причина
Proxmox API **не поддерживает POST** для изменения конфигурации контейнера.
Правильный метод - **PUT**.
## Решение
### Было (неправильно):
```typescript
const response = await axios.post(
`${PROXMOX_API_URL}/nodes/${PROXMOX_NODE}/lxc/${vmid}/config`,
`password=${encodeURIComponent(newPassword)}`,
...
);
```
### Стало (правильно):
```typescript
const response = await axios.put(
`${PROXMOX_API_URL}/nodes/${PROXMOX_NODE}/lxc/${vmid}/config`,
`password=${encodeURIComponent(newPassword)}`,
...
);
```
## Правильные HTTP методы для Proxmox API
### LXC Container Config (`/nodes/{node}/lxc/{vmid}/config`)
- `GET` - получить конфигурацию
- `PUT` - **изменить конфигурацию** (в т.ч. пароль)
-`POST` - не поддерживается
### LXC Container Status (`/nodes/{node}/lxc/{vmid}/status/{action}`)
- `POST` - start/stop/restart/shutdown
### LXC Container Create (`/nodes/{node}/lxc`)
- `POST` - создать новый контейнер
## Документация Proxmox VE API
Официальная документация: https://pve.proxmox.com/pve-docs/api-viewer/
Основные правила:
1. **GET** - чтение данных
2. **POST** - создание ресурсов, выполнение действий (start/stop)
3. **PUT** - изменение существующих ресурсов
4. **DELETE** - удаление ресурсов
## Тестирование
### Через curl:
```bash
# Получить конфигурацию (GET)
curl -k -X GET \
-H "Authorization: PVEAPIToken=user@pam!token=secret" \
https://proxmox:8006/api2/json/nodes/nodename/lxc/100/config
# Изменить пароль (PUT)
curl -k -X PUT \
-H "Authorization: PVEAPIToken=user@pam!token=secret" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "password=NewPassword123" \
https://proxmox:8006/api2/json/nodes/nodename/lxc/100/config
```
### Через веб-интерфейс:
1. Откройте панель управления сервером
2. Вкладка "Настройки"
3. Нажмите "Сменить root-пароль"
4. Проверьте логи: `pm2 logs ospab-backend`
## Проверка прав API токена
Убедитесь, что API токен имеет права:
```bash
# В Proxmox WebUI
# Datacenter → Permissions → API Tokens
# Проверьте права токена:
# - VM.Config.* (для изменения конфигурации)
# - VM.PowerMgmt (для start/stop)
```
Или через командную строку:
```bash
pveum user token permissions api-user@pve sv1-api-user
```
## Fallback через SSH
Если API не работает, система автоматически использует SSH:
```bash
ssh root@proxmox "pct set {vmid} --password 'новый_пароль'"
```
Для этого нужно:
1. Настроить SSH ключи:
```bash
ssh-keygen -t rsa -b 4096
ssh-copy-id root@proxmox_ip
```
2. Проверить доступ:
```bash
ssh root@proxmox_ip "pct list"
```
## Деплой исправления
```bash
# На сервере
cd /var/www/ospab-host/backend
git pull
npm run build
pm2 restart ospab-backend
# Проверка логов
pm2 logs ospab-backend --lines 50
```
## Ожидаемые логи при успехе
```
✅ Пароль успешно изменён для контейнера 105
✅ Пароль успешно обновлён для сервера #17 (VMID: 105)
```
## Ожидаемые логи при ошибке
```
❌ Ошибка смены пароля через API: ...
⚠️ Пробуем через SSH...
✅ Пароль изменён через SSH для контейнера 105
```
## Дополнительные ресурсы
- [Proxmox VE API Documentation](https://pve.proxmox.com/pve-docs/api-viewer/)
- [Proxmox VE Administration Guide](https://pve.proxmox.com/pve-docs/pve-admin-guide.html)
- [pct command reference](https://pve.proxmox.com/pve-docs/pct.1.html)

View File

@@ -1,144 +0,0 @@
# Простые команды для создания нагрузки на сервер
# Выполняйте их в консоли вашего LXC контейнера через noVNC или SSH
## 1. БЫСТРЫЙ ТЕСТ (без установки дополнительных пакетов)
### CPU нагрузка (запустить в фоне)
# Создаёт 100% нагрузку на все ядра на 2 минуты
yes > /dev/null &
yes > /dev/null &
yes > /dev/null &
yes > /dev/null &
# Остановить через 2 минуты:
# killall yes
### Memory нагрузка
# Заполнить 500MB оперативки
cat <( </dev/zero head -c 500m) <(sleep 120) | tail &
# Для 1GB используйте:
# cat <( </dev/zero head -c 1000m) <(sleep 120) | tail &
### Disk I/O нагрузка
# Создать файл 1GB и записать его несколько раз
dd if=/dev/zero of=/tmp/testfile bs=1M count=1000 oflag=direct &
# Удалить после теста:
# rm /tmp/testfile
### Network нагрузка
# Скачать большой файл
wget -O /dev/null http://speedtest.tele2.net/100MB.zip &
# Или создать сетевой трафик:
# ping -f 8.8.8.8 -c 10000 &
## 2. С УСТАНОВКОЙ STRESS-NG (рекомендуется)
# Установить stress-ng (один раз)
apt-get update && apt-get install -y stress-ng
### Комплексный тест (5 минут)
# CPU 50%, Memory 50%, Disk I/O
stress-ng --cpu 2 --cpu-load 50 --vm 1 --vm-bytes 512M --hdd 1 --timeout 300s
### Только CPU (80% нагрузка, 3 минуты)
stress-ng --cpu 4 --cpu-load 80 --timeout 180s
### Только Memory (заполнить 70%, 3 минуты)
stress-ng --vm 2 --vm-bytes 70% --timeout 180s
### Только Disk I/O (3 минуты)
stress-ng --hdd 4 --timeout 180s
## 3. PYTHON СКРИПТ (если Python установлен)
# Создать файл test_load.py:
cat > /tmp/test_load.py << 'EOF'
import time
import threading
def cpu_load():
"""CPU нагрузка"""
end_time = time.time() + 180 # 3 минуты
while time.time() < end_time:
[x**2 for x in range(10000)]
def memory_load():
"""Memory нагрузка"""
data = []
for i in range(100):
data.append(' ' * 10000000) # ~10MB каждый
time.sleep(1)
# Запустить в потоках
threads = []
for i in range(4): # 4 потока для CPU
t = threading.Thread(target=cpu_load)
t.start()
threads.append(t)
# Memory нагрузка
m = threading.Thread(target=memory_load)
m.start()
threads.append(m)
# Ждать завершения
for t in threads:
t.join()
print("Test completed!")
EOF
# Запустить:
python3 /tmp/test_load.py &
## 4. МОНИТОРИНГ НАГРУЗКИ
# Установить htop для визуального мониторинга
apt-get install -y htop
# Запустить htop
htop
# Или использовать стандартные команды:
top # CPU и Memory
iostat -x 1 # Disk I/O (нужно установить: apt install sysstat)
free -h # Memory
uptime # Load average
## 5. ОСТАНОВИТЬ ВСЕ ТЕСТЫ
# Остановить все процессы нагрузки
killall stress-ng yes dd wget python3
# Очистить временные файлы
rm -f /tmp/testfile /tmp/test_load.py
## КАК ПРОВЕРИТЬ РЕЗУЛЬТАТЫ
1. Откройте панель управления сервером в браузере
2. Перейдите на вкладку "Мониторинг"
3. Выберите период "1h" или "6h"
4. Вы увидите графики:
- CPU usage (оранжевый график)
- Memory usage (синий график)
- Disk usage (зеленый график)
- Network In/Out (фиолетовый график)
5. Обновите страницу через 1-2 минуты после запуска теста
6. Используйте кнопки периодов (1h, 6h, 24h) для изменения масштаба

View File

@@ -1,168 +0,0 @@
# Тестирование смены root-пароля
## Как это работает
Система использует **3 метода** смены пароля с автоматическим fallback:
### Метод 1: Proxmox API (основной)
```
POST /api/nodes/{node}/lxc/{vmid}/config
Body: password=новый_пароль
```
- Самый быстрый и надёжный
- Работает через API токен
- Не требует SSH доступа
### Метод 2: SSH + pct set (fallback)
```bash
ssh root@proxmox "pct set {vmid} --password 'новый_пароль'"
```
- Запасной вариант если API не работает
- Требует SSH доступа от backend к Proxmox
- Настраивается через `.env`
### Метод 3: Exec внутри контейнера (последний fallback)
```
POST /api/nodes/{node}/lxc/{vmid}/exec
Body: { command: ["bash", "-c", "echo 'root:пароль' | chpasswd"] }
```
- Выполняет команду внутри контейнера
- Работает если контейнер запущен
- Не требует SSH
## Как протестировать
### 1. Через веб-интерфейс
1. Откройте панель управления сервером
2. Перейдите на вкладку "Настройки"
3. Нажмите кнопку "Сменить root-пароль"
4. Подтвердите действие
5. Новый пароль появится на вкладке "Обзор"
### 2. Через API (curl)
```bash
# Получить токен (замените email и password)
TOKEN=$(curl -X POST https://ospab.host:5000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"yourpassword"}' \
| jq -r '.token')
# Сменить пароль (замените {id} на ID сервера)
curl -X POST https://ospab.host:5000/api/server/{id}/password \
-H "Authorization: Bearer $TOKEN" \
| jq
```
### 3. Проверка нового пароля
#### Через noVNC консоль:
1. Откройте консоль сервера
2. Войдите как `root`
3. Введите новый пароль из панели
#### Через SSH:
```bash
ssh root@IP_СЕРВЕРА
# Введите новый пароль
```
## Логи и отладка
### Backend логи
```bash
# Просмотр логов в реальном времени
pm2 logs ospab-backend
# Или если запущен напрямую
tail -f /var/www/ospab-host/backend/logs/pm2-out.log
```
### Что искать в логах:
**Успешная смена:**
```
✅ Пароль успешно изменён для контейнера 123
✅ Пароль успешно обновлён для сервера #5 (VMID: 123)
```
**Ошибки:**
```
❌ Ошибка смены пароля через API: ...
⚠️ Основной метод не сработал, пробуем через exec...
❌ Ошибка смены пароля через SSH: ...
```
## Возможные проблемы
### Проблема 1: "Не удалось изменить пароль"
**Причина:** Нет доступа к Proxmox API или SSH
**Решение:**
```bash
# Проверьте переменные окружения
cat /var/www/ospab-host/backend/.env | grep PROXMOX
# Должны быть установлены:
PROXMOX_API_URL=https://IP:8006/api2/json
PROXMOX_TOKEN_ID=root@pam!your-token-name
PROXMOX_TOKEN_SECRET=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
PROXMOX_NODE=proxmox
```
### Проблема 2: SSH метод не работает
**Причина:** Нет SSH ключей или доступа
**Решение:**
```bash
# Настройте SSH ключи (на сервере с backend)
ssh-keygen -t rsa -b 4096
ssh-copy-id root@PROXMOX_IP
# Проверьте доступ
ssh root@PROXMOX_IP "pct list"
```
### Проблема 3: Контейнер не запущен
**Причина:** Exec метод работает только для запущенных контейнеров
**Решение:**
1. Запустите контейнер
2. Подождите 30 секунд
3. Попробуйте снова сменить пароль
## Автоматическое скрытие пароля
Пароль автоматически скрывается через **30 минут** после:
- Создания сервера
- Смены пароля
### Как проверить:
1. Создайте сервер или смените пароль
2. Пароль виден на вкладке "Обзор"
3. Через 30 минут пароль будет заменён на "••••••••"
4. Кнопка "Показать пароль" перестанет работать
### Как показать снова:
Нажмите "Сменить root-пароль" - будет сгенерирован новый пароль и снова виден 30 минут.
## Частые вопросы
**Q: Как часто можно менять пароль?**
A: Без ограничений. Каждая смена генерирует новый случайный пароль.
**Q: Можно ли задать свой пароль?**
A: Нет, система генерирует случайный пароль 16 символов для безопасности.
**Q: Пароль сохраняется в базе?**
A: Да, в зашифрованном виде в таблице `server.rootPassword`.
**Q: Что если я потерял пароль?**
A: Просто нажмите "Сменить root-пароль" - будет сгенерирован новый.
**Q: Работает ли для KVM виртуалок?**
A: Эта реализация для LXC контейнеров. Для KVM нужна доработка.