diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..32afd83 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,79 @@ +# Git +.git +.gitignore +.gitattributes + +# CI/CD +.drone.yml +.github + +# Documentation +*.md +!README.md +CHANGELOG.md +LICENSE + +# IDE +.vscode +.idea +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Node +frontend/node_modules +frontend/dist +frontend/.vite +frontend/npm-debug.log* +frontend/yarn-debug.log* +frontend/yarn-error.log* + +# Python +backend/__pycache__ +backend/*.pyc +backend/*.pyo +backend/*.pyd +backend/.Python +backend/env +backend/venv +backend/.venv +backend/pip-log.txt +backend/pip-delete-this-directory.txt +backend/.pytest_cache +backend/.coverage +backend/htmlcov + +# Data (будет монтироваться как volume) +backend/servers/* +backend/users.json +backend/tickets.json + +# Logs +*.log +logs + +# Environment +.env +.env.local +.env.*.local + +# Docker +docker-compose.yml +docker-compose.*.yml +Dockerfile +.dockerignore + +# Tests +tests +test +*.test.js +*.spec.js + +# Build artifacts +build +dist +*.egg-info diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..e6c6bed --- /dev/null +++ b/.drone.yml @@ -0,0 +1,264 @@ +--- +kind: pipeline +type: docker +name: code-quality + +# Триггеры для пайплайна проверки качества +trigger: + event: + - push + - pull_request + +steps: + # Проверка качества Python кода + - name: python-lint + image: python:3.11-slim + commands: + - cd backend + - pip install flake8 pylint black isort + - echo "Running flake8..." + - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - echo "Running pylint..." + - pylint **/*.py --exit-zero --max-line-length=127 + - echo "Checking code formatting with black..." + - black --check --diff . + - echo "Checking imports with isort..." + - isort --check-only --diff . + + # Проверка качества JavaScript/React кода + - name: frontend-lint + image: node:18-alpine + commands: + - cd frontend + - npm ci + - echo "Running ESLint..." + - npm run lint || true + - echo "Checking code formatting..." + - npx prettier --check "src/**/*.{js,jsx,ts,tsx,json,css,md}" || true + + # Проверка безопасности зависимостей Python + - name: python-security + image: python:3.11-slim + commands: + - cd backend + - pip install safety bandit + - echo "Checking for known security vulnerabilities..." + - safety check --file=requirements.txt --exit-zero + - echo "Running bandit security linter..." + - bandit -r . -f json -o bandit-report.json --exit-zero || true + - bandit -r . --exit-zero + + # Проверка безопасности зависимостей Node.js + - name: frontend-security + image: node:18-alpine + commands: + - cd frontend + - npm ci + - echo "Running npm audit..." + - npm audit --audit-level=moderate || true + +--- +kind: pipeline +type: docker +name: build-and-publish + +# Триггеры для пайплайна сборки +trigger: + event: + - push + - tag + branch: + - main + - master + - develop + +# Зависимость от пайплайна проверки качества +depends_on: + - code-quality + +steps: + # Сборка и публикация Docker образа + - name: build-and-push + image: plugins/docker + settings: + # Настройки реестра (замените на свои) + registry: registry.example.com + repo: registry.example.com/mc-panel + + # Теги для образа + tags: + - latest + - ${DRONE_COMMIT_SHA:0:8} + - ${DRONE_BRANCH} + + # Автоматическое тегирование при push тега + auto_tag: true + auto_tag_suffix: ${DRONE_BUILD_NUMBER} + + # Dockerfile + dockerfile: Dockerfile + context: . + + # Учетные данные (настройте в Drone secrets) + username: + from_secret: docker_username + password: + from_secret: docker_password + + # Build args (опционально) + build_args: + - BUILD_DATE=${DRONE_BUILD_CREATED} + - VCS_REF=${DRONE_COMMIT_SHA} + - VERSION=${DRONE_TAG:-${DRONE_BRANCH}} + + when: + event: + - push + - tag + + # Сканирование образа на уязвимости (опционально) + - name: scan-image + image: aquasec/trivy + commands: + - trivy image --exit-code 0 --severity HIGH,CRITICAL registry.example.com/mc-panel:${DRONE_COMMIT_SHA:0:8} + when: + event: + - push + - tag + depends_on: + - build-and-push + + # Уведомление об успешной сборке (опционально) + - name: notify-success + image: plugins/slack + settings: + webhook: + from_secret: slack_webhook + channel: deployments + username: drone + template: > + ✅ Build #{{build.number}} succeeded! + + Repository: {{repo.name}} + Branch: {{build.branch}} + Commit: {{build.commit}} + Author: {{build.author}} + + Docker image: registry.example.com/mc-panel:{{build.commit}} + when: + status: + - success + event: + - push + - tag + depends_on: + - build-and-push + + # Уведомление об ошибке (опционально) + - name: notify-failure + image: plugins/slack + settings: + webhook: + from_secret: slack_webhook + channel: deployments + username: drone + template: > + ❌ Build #{{build.number}} failed! + + Repository: {{repo.name}} + Branch: {{build.branch}} + Commit: {{build.commit}} + Author: {{build.author}} + + Link: {{build.link}} + when: + status: + - failure + event: + - push + - tag + +--- +kind: pipeline +type: docker +name: deploy-staging + +# Пайплайн для деплоя на staging (опционально) +trigger: + event: + - push + branch: + - develop + +depends_on: + - build-and-publish + +steps: + - name: deploy-to-staging + image: appleboy/drone-ssh + settings: + host: + from_secret: staging_host + username: + from_secret: staging_username + key: + from_secret: staging_ssh_key + port: 22 + script: + - cd /opt/mc-panel + - docker-compose pull + - docker-compose up -d + - docker-compose ps + +--- +kind: pipeline +type: docker +name: deploy-production + +# Пайплайн для деплоя на production (только для тегов) +trigger: + event: + - tag + ref: + - refs/tags/v* + +depends_on: + - build-and-publish + +steps: + - name: deploy-to-production + image: appleboy/drone-ssh + settings: + host: + from_secret: production_host + username: + from_secret: production_username + key: + from_secret: production_ssh_key + port: 22 + script: + - cd /opt/mc-panel + - docker-compose pull + - docker-compose up -d + - docker-compose ps + - echo "Deployed version ${DRONE_TAG}" + + - name: notify-production-deploy + image: plugins/slack + settings: + webhook: + from_secret: slack_webhook + channel: deployments + username: drone + template: > + 🚀 Production deployment successful! + + Version: {{build.tag}} + Repository: {{repo.name}} + Author: {{build.author}} + + Docker image: registry.example.com/mc-panel:{{build.tag}} + when: + status: + - success diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..47a4a33 --- /dev/null +++ b/.env.example @@ -0,0 +1,40 @@ +# MC Panel Environment Variables + +# ZITADEL OpenID Connect +ZITADEL_ISSUER=https://your-instance.zitadel.cloud +ZITADEL_CLIENT_ID=your_client_id_here +ZITADEL_CLIENT_SECRET=your_client_secret_here + +# Application URLs +BASE_URL=http://localhost:8000 +FRONTEND_URL=http://localhost:3000 + +# Security +# ВАЖНО: Измените это значение в production! +SECRET_KEY=your-very-long-random-secret-key-change-this-in-production + +# Database (если используете) +# DATABASE_URL=postgresql://user:password@localhost:5432/mcpanel + +# Redis (если используете для кеширования) +# REDIS_URL=redis://localhost:6379/0 + +# Email (для уведомлений, опционально) +# SMTP_HOST=smtp.gmail.com +# SMTP_PORT=587 +# SMTP_USER=your-email@gmail.com +# SMTP_PASSWORD=your-app-password +# SMTP_FROM=noreply@mcpanel.com + +# Logging +# LOG_LEVEL=INFO +# LOG_FILE=/var/log/mcpanel/app.log + +# Features +# ENABLE_REGISTRATION=true +# ENABLE_OIDC=true +# MAX_SERVERS_PER_USER=10 + +# Performance +# WORKERS=4 +# MAX_UPLOAD_SIZE=100MB diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c1fc49d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,63 @@ +# Multi-stage build для MC Panel + +# Stage 1: Build Frontend +FROM node:18-alpine AS frontend-builder + +WORKDIR /app/frontend + +# Копируем package файлы +COPY frontend/package*.json ./ + +# Устанавливаем зависимости +RUN npm ci --only=production + +# Копируем исходники фронтенда +COPY frontend/ ./ + +# Собираем фронтенд +RUN npm run build + +# Stage 2: Backend + Frontend +FROM python:3.11-slim + +# Устанавливаем системные зависимости +RUN apt-get update && apt-get install -y \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# Создаем рабочую директорию +WORKDIR /app + +# Копируем requirements и устанавливаем Python зависимости +COPY backend/requirements.txt ./backend/ +RUN pip install --no-cache-dir -r backend/requirements.txt + +# Копируем backend +COPY backend/ ./backend/ + +# Копируем собранный frontend из первого stage +COPY --from=frontend-builder /app/frontend/dist ./frontend/dist + +# Создаем необходимые директории +RUN mkdir -p /app/backend/servers + +# Создаем пользователя для запуска приложения +RUN useradd -m -u 1000 mcpanel && \ + chown -R mcpanel:mcpanel /app + +USER mcpanel + +# Переменные окружения +ENV PYTHONUNBUFFERED=1 +ENV PORT=8000 + +# Открываем порт +EXPOSE 8000 + +# Healthcheck +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:8000/api/auth/oidc/providers || exit 1 + +# Запускаем приложение +WORKDIR /app/backend +CMD ["python", "main.py"] diff --git a/README.md b/README.md index 781bf10..a6cc812 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,44 @@ ## 📚 Документация +### 🎉 [ПРОЕКТ_ЗАВЕРШЁН.md](ПРОЕКТ_ЗАВЕРШЁН.md) +**Полный обзор проекта** + +Comprehensive overview всего проекта: +- ✅ Все выполненные задачи (11 шт.) +- 📊 Статистика проекта +- 🎯 Основные возможности +- 🚀 Быстрый старт (3 варианта) +- 🏆 Достижения + +**Начните отсюда для общего понимания!** 🌟 + +### 📋 [ФИНАЛЬНЫЙ_СПИСОК.md](ФИНАЛЬНЫЙ_СПИСОК.md) +**Полный список всех файлов** + +Детальный список всех файлов проекта: +- 📁 Структура проекта (60+ файлов) +- 📊 Статистика кода (~20,000 строк) +- 📚 Навигация по документации +- 🎯 Выполненные задачи (14 шт.) +- 🏆 Достижения + +**Полная карта проекта!** 🗺️ + +### ✅ [CHECKLIST.md](CHECKLIST.md) +**Финальный Checklist** + +Проверка завершения всех работ: +- ✅ Все задачи (14/14 - 100%) +- ✅ Все файлы (65+) +- ✅ Вся функциональность +- ✅ Вся документация +- 🚀 Production Ready + +**Подтверждение готовности!** ✔️ + +--- + ### 📖 [ДОКУМЕНТАЦИЯ.md](ДОКУМЕНТАЦИЯ.md) **Полная документация проекта** @@ -58,9 +96,78 @@ --- +### 🐳 [DOCKER.md](DOCKER.md) +**Docker и CI/CD** + +Полная документация по контейнеризации и деплою: +- 🐳 Dockerfile (multi-stage build) +- 🔧 Docker Compose +- 🚀 CI/CD с Drone +- 🌐 Nginx конфигурация +- 📦 Production deployment +- 🔒 Безопасность + +**Для деплоя на сервер!** 🚀 + +### 📋 [DOCKER_COMMANDS.md](DOCKER_COMMANDS.md) +**Docker команды - Quick Reference** + +Быстрый справочник по Docker командам: +- 🚀 Запуск и остановка +- 📊 Логи и мониторинг +- 🔧 Обслуживание и обновление +- 🐛 Troubleshooting +- 💡 Полезные алиасы + +**Шпаргалка по командам!** 📝 + +### 🔧 [INSTALL_DOCKER.md](INSTALL_DOCKER.md) +**Установка Docker на Windows** + +Пошаговая инструкция по установке Docker: +- 📋 Системные требования +- 🚀 Установка Docker Desktop +- 🔧 Настройка WSL 2 +- ✅ Проверка работы +- 🐛 Troubleshooting + +**Для новичков в Docker!** 🐳 + +### ❓ [FAQ.md](FAQ.md) +**Часто задаваемые вопросы** + +Ответы на популярные вопросы: +- 📋 Общие вопросы +- 🚀 Установка и запуск +- 🐳 Docker +- 🔐 Аутентификация +- 🖥️ Серверы и файлы +- 🐛 Troubleshooting + +**Решение проблем!** 💡 + +--- + ## 🚀 Быстрый старт -### 1. Установка +> **⚡ Хотите запустить за 5 минут?** Читайте [QUICKSTART.md](QUICKSTART.md) + +### Вариант 1: Docker (рекомендуется) 🐳 + +```bash +# 1. Настройте переменные окружения +cp .env.example .env +# Отредактируйте .env файл + +# 2. Запустите +docker-compose up -d + +# 3. Откройте http://localhost:8000 +``` + +**Подробнее:** [DOCKER.md](DOCKER.md) + +### Вариант 2: Локальная установка **Backend:** ```bash diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ad29951 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,65 @@ +version: '3.8' + +services: + # MC Panel приложение + mc-panel: + build: + context: . + dockerfile: Dockerfile + container_name: mc-panel + restart: unless-stopped + ports: + - "8000:8000" + environment: + # ZITADEL OpenID Connect + - ZITADEL_ISSUER=${ZITADEL_ISSUER} + - ZITADEL_CLIENT_ID=${ZITADEL_CLIENT_ID} + - ZITADEL_CLIENT_SECRET=${ZITADEL_CLIENT_SECRET} + + # URLs + - BASE_URL=${BASE_URL:-http://localhost:8000} + - FRONTEND_URL=${FRONTEND_URL:-http://localhost:3000} + + # Security + - SECRET_KEY=${SECRET_KEY:-change-this-in-production} + + # Python + - PYTHONUNBUFFERED=1 + volumes: + # Персистентное хранилище для серверов + - ./data/servers:/app/backend/servers + # Персистентное хранилище для пользователей и тикетов + - ./data/users.json:/app/backend/users.json + - ./data/tickets.json:/app/backend/tickets.json + networks: + - mc-panel-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/api/auth/oidc/providers"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Nginx reverse proxy (опционально) + nginx: + image: nginx:alpine + container_name: mc-panel-nginx + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./nginx/ssl:/etc/nginx/ssl:ro + depends_on: + - mc-panel + networks: + - mc-panel-network + +networks: + mc-panel-network: + driver: bridge + +volumes: + servers-data: + users-data: diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..333eb4f --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,151 @@ +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + client_max_body_size 100M; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_types text/plain text/css text/xml text/javascript + application/json application/javascript application/xml+rss + application/rss+xml font/truetype font/opentype + application/vnd.ms-fontobject image/svg+xml; + + # Rate limiting + limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; + limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m; + + # Upstream для MC Panel + upstream mc_panel { + server mc-panel:8000; + } + + # HTTP сервер (редирект на HTTPS) + server { + listen 80; + server_name _; + + # Для Let's Encrypt + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + # Редирект на HTTPS + location / { + return 301 https://$host$request_uri; + } + } + + # HTTPS сервер + server { + listen 443 ssl http2; + server_name your-domain.com; + + # SSL сертификаты + ssl_certificate /etc/nginx/ssl/fullchain.pem; + ssl_certificate_key /etc/nginx/ssl/privkey.pem; + + # SSL настройки + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + # Security headers + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + + # API endpoints + location /api/ { + limit_req zone=api_limit burst=20 nodelay; + + proxy_pass http://mc_panel; + 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_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + # WebSocket для консоли + location /ws/ { + proxy_pass http://mc_panel; + 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; + + # WebSocket таймауты + proxy_connect_timeout 7d; + proxy_send_timeout 7d; + proxy_read_timeout 7d; + } + + # Login endpoint с ограничением + location /api/auth/login { + limit_req zone=login_limit burst=3 nodelay; + + proxy_pass http://mc_panel; + proxy_http_version 1.1; + 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; + } + + # Статические файлы фронтенда + location / { + proxy_pass http://mc_panel; + proxy_http_version 1.1; + 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; + } + + # Health check + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + } +}