diff --git a/backend/app.js b/backend/app.js index 32c1230..ddb256d 100644 --- a/backend/app.js +++ b/backend/app.js @@ -30,6 +30,8 @@ const monitoringRoutes = require('./routes/monitoring'); const pagesRoutes = require('./routes/pages'); // Добавляем импорт роутера страниц const uploadsRoutes = require('./routes/uploads'); const ensRoutes = require('./routes/ens'); +const sshRoutes = require('./routes/ssh'); // SSH роуты +const encryptionRoutes = require('./routes/encryption'); // Encryption роуты // Factory routes removed - no longer needed // Проверка и создание директорий для хранения данных контрактов @@ -211,6 +213,8 @@ app.use('/api/pages', pagesRoutes); // Подключаем роутер стр app.use('/api/system', systemRoutes); // Добавляем маршрут системного мониторинга app.use('/api/uploads', uploadsRoutes); // Загрузка файлов (логотипы) app.use('/api/ens', ensRoutes); // ENS utilities +app.use('/api', sshRoutes); // SSH роуты +app.use('/api', encryptionRoutes); // Encryption роуты // app.use('/api/factory', factoryRoutes); // Factory routes removed - no longer needed app.use('/api/compile-contracts', compileRoutes); // Компиляция контрактов diff --git a/backend/routes/encryption.js b/backend/routes/encryption.js new file mode 100644 index 0000000..424073d --- /dev/null +++ b/backend/routes/encryption.js @@ -0,0 +1,67 @@ +const express = require('express'); +const router = express.Router(); +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +// Путь к папке с ключами шифрования +const KEYS_DIR = path.join(__dirname, '../../ssl/keys'); +const ENCRYPTION_KEY_PATH = path.join(KEYS_DIR, 'full_db_encryption.key'); + +// Создаем папку keys если её нет +if (!fs.existsSync(KEYS_DIR)) { + fs.mkdirSync(KEYS_DIR, { recursive: true }); +} + +// Helper to read encryption key +const readEncryptionKey = (keyPath) => { + try { + return fs.readFileSync(keyPath, 'utf8'); + } catch (error) { + return null; + } +}; + +// Helper to write encryption key +const writeEncryptionKey = (keyPath, key) => { + try { + fs.writeFileSync(keyPath, key, { mode: 0o600 }); + return true; + } catch (error) { + return false; + } +}; + +// GET /api/encryption-key - Get existing encryption key +router.get('/encryption-key', (req, res) => { + const encryptionKey = readEncryptionKey(ENCRYPTION_KEY_PATH); + + if (encryptionKey) { + res.json({ success: true, encryptionKey: encryptionKey }); + } else { + res.status(404).json({ success: false, message: 'Encryption key not found' }); + } +}); + +// POST /api/encryption-key/generate - Generate a new encryption key +router.post('/encryption-key/generate', (req, res) => { + try { + // Генерируем новый ключ шифрования (256 бит) + const encryptionKey = crypto.randomBytes(32).toString('hex'); + + // Сохраняем ключ в файл + if (writeEncryptionKey(ENCRYPTION_KEY_PATH, encryptionKey)) { + res.json({ + success: true, + message: 'Encryption key generated successfully', + encryptionKey: encryptionKey + }); + } else { + res.status(500).json({ success: false, message: 'Failed to save encryption key' }); + } + } catch (error) { + res.status(500).json({ success: false, message: `Failed to generate encryption key: ${error.message}` }); + } +}); + +module.exports = router; diff --git a/backend/routes/ssh.js b/backend/routes/ssh.js new file mode 100644 index 0000000..0dffefa --- /dev/null +++ b/backend/routes/ssh.js @@ -0,0 +1,42 @@ +const express = require('express'); +const router = express.Router(); +const fs = require('fs'); +const path = require('path'); + +const SSH_DIR = path.join(process.env.HOME || process.env.USERPROFILE, '.ssh'); +const DEFAULT_KEY_PATH = path.join(SSH_DIR, 'id_rsa'); +const DEFAULT_PUB_KEY_PATH = path.join(SSH_DIR, 'id_rsa.pub'); + +// Helper to read SSH key +const readSshKey = (keyPath) => { + try { + return fs.readFileSync(keyPath, 'utf8'); + } catch (error) { + return null; + } +}; + +// GET /api/ssh-key - Get existing SSH private key +router.get('/ssh-key', (req, res) => { + const privateKey = readSshKey(DEFAULT_KEY_PATH); + const publicKey = readSshKey(DEFAULT_PUB_KEY_PATH); + + if (privateKey) { + res.json({ success: true, sshKey: privateKey, publicKey: publicKey, keyType: 'rsa' }); + } else { + res.status(404).json({ success: false, message: 'SSH private key not found' }); + } +}); + +// GET /api/ssh-key/public - Get existing SSH public key +router.get('/ssh-key/public', (req, res) => { + const publicKey = readSshKey(DEFAULT_PUB_KEY_PATH); + + if (publicKey) { + res.json({ success: true, publicKey: publicKey, keyType: 'rsa' }); + } else { + res.status(404).json({ success: false, message: 'SSH public key not found' }); + } +}); + +module.exports = router; diff --git a/docker-compose.yml b/docker-compose.yml index 021c22e..9970bfb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -201,6 +201,24 @@ services: + # SSH Key Server для безопасной передачи ключей + ssh-key-server: + image: node:20-alpine + container_name: dapp-ssh-key-server + restart: unless-stopped + volumes: + - ./scripts/ssh-key-server.js:/app/ssh-key-server.js:ro + - ./ssl:/app/ssl:ro + - ~/.ssh:/root/.ssh:ro + ports: + - '3001:3001' + command: node /app/ssh-key-server.js + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3001/ssh-key"] + interval: 30s + timeout: 10s + retries: 3 + # Автоматический бэкап базы данных backup-service: image: postgres:16-alpine diff --git a/docs/dns-setup.md b/docs/dns-setup.md new file mode 100644 index 0000000..635997a --- /dev/null +++ b/docs/dns-setup.md @@ -0,0 +1,98 @@ +# Настройка DNS записей для VDS + +## 🎯 **Цель:** +Настроить DNS записи так, чтобы домен указывал на IP адрес VDS сервера. + +## 📋 **Требуемые DNS записи:** + +### **1. A запись (обязательная):** +``` +Тип: A +Имя: @ (или пустое) +Значение: IP_VDS_СЕРВЕРА +TTL: 3600 (или по умолчанию) +``` + +### **2. CNAME запись (опциональная):** +``` +Тип: CNAME +Имя: www +Значение: example.com +TTL: 3600 (или по умолчанию) +``` + +## 🔧 **Настройка у разных провайдеров:** + +### **Cloudflare:** +1. Заходим в панель Cloudflare +2. Выбираем домен +3. Переходим в "DNS" → "Records" +4. Добавляем A запись: + - **Type:** A + - **Name:** @ + - **IPv4 address:** IP_VDS_СЕРВЕРА + - **Proxy status:** DNS only (серый облачок) + +### **Reg.ru:** +1. Заходим в панель управления +2. Выбираем домен +3. Переходим в "DNS-записи" +4. Добавляем A запись: + - **Тип:** A + - **Поддомен:** @ + - **IP-адрес:** IP_VDS_СЕРВЕРА + +### **Namecheap:** +1. Заходим в панель управления +2. Выбираем домен +3. Переходим в "Advanced DNS" +4. Добавляем A запись: + - **Type:** A Record + - **Host:** @ + - **Value:** IP_VDS_СЕРВЕРА + +## ⏱️ **Время распространения DNS:** + +- **Обычно:** 15-60 минут +- **Максимум:** 24-48 часов +- **Проверка:** `nslookup example.com` или `dig example.com` + +## 🔍 **Проверка DNS записей:** + +### **Через браузер:** +- Откройте `https://dns.google/resolve?name=example.com&type=A` +- Проверьте, что в ответе указан IP VDS сервера + +### **Через командную строку:** +```bash +# Linux/Mac +nslookup example.com +dig example.com + +# Windows +nslookup example.com +``` + +## ⚠️ **Важные моменты:** + +1. **Убедитесь, что домен активен** и не заблокирован +2. **Проверьте, что IP VDS сервера правильный** +3. **Дождитесь распространения DNS** перед настройкой VDS +4. **Используйте только IP адрес** (не домен) для VDS + +## 🚨 **Частые проблемы:** + +### **DNS не обновляется:** +- Проверьте TTL записи (должен быть 300-3600) +- Очистите DNS кэш: `ipconfig /flushdns` (Windows) +- Подождите до 48 часов + +### **Домен не указывает на VDS:** +- Проверьте правильность IP адреса +- Убедитесь, что A запись создана для корневого домена (@) +- Проверьте, что нет других A записей + +### **Сайт не открывается:** +- Убедитесь, что VDS сервер запущен +- Проверьте, что порт 80/443 открыт +- Проверьте firewall на VDS сервере diff --git a/docs/vds.md b/docs/vds.md new file mode 100644 index 0000000..a039283 --- /dev/null +++ b/docs/vds.md @@ -0,0 +1,153 @@ +# Задача: Простая настройка VDS с автоматической установкой Ubuntu + +## 🎯 **Описание задачи:** + +### **Цель:** +Создать простую форму для автоматической настройки VDS сервера с установкой Ubuntu и деплоем DLE приложения. + +### **Проблема:** +Нужно вручную настраивать VDS сервер, устанавливать Ubuntu и необходимые компоненты для работы DLE приложения. + +### **Решение:** +Автоматическая очистка VDS, установка Ubuntu, создание пользователя и деплой DLE приложения через локальную форму. + +## 📋 **Требования:** + +### **1. Входные данные (9 полей):** +- **VDS IP** - IP адрес сервера +- **Домен** - например `example.com` (должен указывать на IP VDS) +- **Email** - для SSL сертификата +- **Логин Ubuntu** - пользователь для VDS (по умолчанию `ubuntu`) +- **Пароль Ubuntu** - пароль для пользователя VDS +- **Логин Docker** - пользователь для Docker (по умолчанию `docker`) +- **Пароль Docker** - пароль для пользователя Docker +- **SSH пользователь** - обычно `root` +- **SSH ключ** - приватный ключ для подключения +- **Ключ шифрования** - автоматически загружается с локальной машины + +### **1.1. Требования к домену:** +- **A запись** `example.com` → IP VDS сервера +- **CNAME запись** `www.example.com` → `example.com` (опционально) +- **Домен должен быть активен** и доступен +- **DNS записи должны распространиться** (проверка перед настройкой) + +### **2. Что должно происходить:** +1. **Проверка DNS** - валидация A записи домена +2. **Подключение** к VDS по SSH +3. **Очистка** всего содержимого на VDS +4. **Установка** Ubuntu +5. **Создание пользователя Ubuntu** с паролем +6. **Создание пользователя Docker** с паролем +7. **Установка** Docker, Docker Compose, nginx +8. **Настройка** nginx для продакшн приложения +9. **Получение** SSL сертификата +10. **Миграция** Docker образов с локальной машины +11. **Передача ключей** (шифрования и RSA) на VDS +12. **Обновление переменных** в БД VDS +13. **Запуск** DLE приложения в Docker + +### **3. Результат:** +- **VDS полностью очищена** и переустановлена +- **Ubuntu установлена** с пользователями Ubuntu и Docker +- **Docker образы** мигрированы с локальной машины +- **Ключи переданы** с локальной машины на VDS +- **Переменные обновлены** в БД VDS +- **DLE приложение** работает в Docker на VDS +- **Домен работает** с SSL +- **Приложение работает** автономно на VDS + +## 🏗️ **Архитектура:** + +``` +Продакшн режим: +Интернет → VDS nginx (домен) → VDS Docker приложение (автономно) + +Настройка: +Локальная машина → SSH → VDS сервер → Очистка + Ubuntu + Docker миграция +``` + +### **Компоненты:** +1. **Веб-форма** - настройка VDS (7 полей) +2. **WebSSH сервис** - SSH команды к VDS +3. **SSH агент** - подключение к VDS +4. **VDS сервер** - Ubuntu + Docker + nginx + SSL +5. **Docker образы** - мигрированы с локальной машины +6. **Переменные окружения** - настроены для продакшн + +## 🚀 **Процесс работы:** + +### **1. Первоначальная настройка:** +- Заходит на `http://localhost:5173/settings/interface/webssh` +- Заполняет форму с данными VDS (9 полей) +- Нажимает "Настроить VDS" + +### **2. Система настраивает VDS:** +- **Проверяет DNS** записи домена +- **Предупреждает** если домен не готов +- Подключается к VDS по SSH +- **Очищает** все содержимое на VDS +- **Устанавливает** Ubuntu +- **Создает пользователя Ubuntu** с паролем +- **Создает пользователя Docker** с паролем +- Устанавливает Docker, Docker Compose, nginx +- Настраивает nginx для продакшн +- Получает SSL сертификат +- **Мигрирует** Docker образы с локальной машины +- **Передает ключи** (шифрования и RSA) на VDS +- **Обновляет переменные** в БД VDS +- **Запускает** DLE приложение в Docker + +### **3. Результат:** +- **VDS полностью готова** для работы +- **Пользователи Ubuntu и Docker** созданы +- **Docker образы** мигрированы и запущены +- **Ключи переданы** с локальной машины на VDS +- **Переменные обновлены** в БД VDS +- **DLE приложение** работает автономно в Docker +- **Домен доступен** с SSL + +## 📁 **Файлы проекта:** + +### **Frontend:** +- `frontend/src/components/WebSshForm.vue` - форма управления +- `frontend/src/services/webSshService.js` - SSH команды к VDS + +### **Backend:** +- `backend/routes/vds-management.js` - API для управления VDS +- `backend/services/sshManager.js` - SSH команды +- `backend/services/encryptionManager.js` - управление шифрованием + +### **Scripts:** +- `scripts/setup-vds.sh` - очистка VDS и установка Ubuntu +- `scripts/migrate-docker.sh` - миграция Docker образов на VDS +- `scripts/configure-vds.sh` - настройка переменных окружения +- `scripts/transfer-keys.sh` - передача ключей на VDS +- `scripts/update-variables.sh` - обновление переменных в БД +- `scripts/install-ubuntu.sh` - автоматическая установка Ubuntu + +## ✅ **Статус:** + +### **Готово:** +- ✅ Форма WebSSH упрощена +- ✅ WebSSH сервис обновлен +- ✅ DNS проверка добавлена +- ✅ Инструкции по настройке DNS созданы +- ✅ Поле VDS IP добавлено в форму + +### **Нужно доработать:** +- 🔄 SSH агент для очистки и установки Ubuntu +- 🔄 API для управления VDS +- 🔄 Миграция Docker образов на VDS +- 🔄 Передача ключей (шифрования и RSA) на VDS +- 🔄 Обновление переменных в БД VDS +- 🔄 Автоматическая загрузка ключа шифрования в форму + +## 🎯 **Следующие шаги:** + +1. **Создать SSH агент** для очистки и установки Ubuntu +2. **Добавить API** для управления VDS +3. **Реализовать миграцию** Docker образов на VDS +4. **Создать скрипты** для передачи ключей на VDS +5. **Реализовать обновление** переменных в БД VDS +6. **Добавить автоматическую загрузку** ключа шифрования в форму +7. **Протестировать** на реальной VDS \ No newline at end of file diff --git a/frontend/src/components/WebSshForm.vue b/frontend/src/components/WebSshForm.vue index c6b9d9f..80d0aac 100644 --- a/frontend/src/components/WebSshForm.vue +++ b/frontend/src/components/WebSshForm.vue @@ -21,29 +21,60 @@
-

Настройки домена

+

Настройки VDS

+
+ + +
+ Домен должен указывать на IP VDS сервера (A запись)
+
+ + +
+
+ + +
+
+ + +
+
+ + +

Настройки SSH сервера

-
- - -
- +
+ + +
+
+
+ +
+ + +
@@ -84,23 +115,70 @@ \ No newline at end of file diff --git a/frontend/src/views/VdsMockView.vue b/frontend/src/views/VdsMockView.vue new file mode 100644 index 0000000..0e001b2 --- /dev/null +++ b/frontend/src/views/VdsMockView.vue @@ -0,0 +1,393 @@ + + + + + + + diff --git a/frontend/src/views/settings/Interface/InterfaceWebSshView.vue b/frontend/src/views/settings/Interface/InterfaceWebSshView.vue index cc848f7..71541a5 100644 --- a/frontend/src/views/settings/Interface/InterfaceWebSshView.vue +++ b/frontend/src/views/settings/Interface/InterfaceWebSshView.vue @@ -18,8 +18,6 @@ :identities="identities" :token-balances="tokenBalances" :is-loading-tokens="isLoadingTokens" - :telegram-auth="telegramAuth" - :email-auth="emailAuth" />
@@ -37,6 +35,18 @@ import Header from '@/components/Header.vue'; import Sidebar from '@/components/Sidebar.vue'; import { useAuthContext } from '@/composables/useAuth'; +// Определяем пропсы, которые мы принимаем +defineProps({ + isAuthenticated: Boolean, + identities: Array, + tokenBalances: Array, + isLoadingTokens: Boolean, + formattedLastUpdate: String +}); + +// Определяем события, которые мы эмитим +defineEmits(['authActionCompleted']); + const router = useRouter(); const goBack = () => router.push('/settings/interface'); const showSidebar = ref(false); @@ -49,18 +59,6 @@ const isAuthenticated = auth.isAuthenticated.value; const identities = auth.identities?.value || []; const tokenBalances = auth.tokenBalances?.value || []; const isLoadingTokens = false; - -// Дефолтные объекты для Sidebar -const telegramAuth = { - showVerification: false, - botLink: '', - verificationCode: '', - error: '' -}; -const emailAuth = { - showForm: false, - showVerification: false -};