56
This commit is contained in:
@@ -15,11 +15,12 @@ FRONTEND_PORT=80
|
||||
# ============================
|
||||
# DATABASE (PostgreSQL)
|
||||
# ============================
|
||||
# На VPS используй: openssl rand -base64 32
|
||||
DB_HOST=postgres
|
||||
DB_PORT=5432
|
||||
DB_NAME=pg_admin
|
||||
DB_USER=postgres
|
||||
DB_PASSWORD=CHANGE_ME_SECURE_PASSWORD
|
||||
DB_PASSWORD=CHANGE_ME_TO_STRONG_PASSWORD_GENERATED_WITH_OPENSSL
|
||||
DB_HOST_DEV=localhost
|
||||
|
||||
# Connection pool
|
||||
|
||||
269
VPS-DEPLOYMENT.md
Normal file
269
VPS-DEPLOYMENT.md
Normal file
@@ -0,0 +1,269 @@
|
||||
# 🚀 Развертывание на VPS
|
||||
|
||||
Инструкция по запуску pg-admin на VPS (Ubuntu 24.04, другие версии похожи).
|
||||
|
||||
## Быстрый старт (3 шага)
|
||||
|
||||
### 1️⃣ Подключись к VPS и клонируй репозиторий
|
||||
|
||||
```bash
|
||||
ssh root@YOUR_VPS_IP
|
||||
cd ~
|
||||
git clone git@your-repo-url:your-org/pg-admin.git
|
||||
cd pg-admin
|
||||
```
|
||||
|
||||
### 2️⃣ Генерируй безопасные пароли
|
||||
|
||||
```bash
|
||||
bash scripts/generate-secrets.sh
|
||||
```
|
||||
|
||||
Скопируй выходные значения.
|
||||
|
||||
### 3️⃣ Создай и настрой .env
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
**Замени в .env:**
|
||||
- `CHANGE_ME_TO_STRONG_PASSWORD` → Пароль из `generate-secrets.sh`
|
||||
- `CHANGE_ME_TO_STRONG_RANDOM_SECRET` → JWT_SECRET из `generate-secrets.sh`
|
||||
- `your-domain.com` → Твой реальный доменName (или IP на тест)
|
||||
- `FRONTEND_API_URL` → `http://ТВЙ_ДОМЕН/api`
|
||||
- `CORS_ORIGIN` → `http://ТВЙ_ДОМЕН` (пока HTTP)
|
||||
|
||||
Сохрани (Ctrl+X, Y, Enter в nano).
|
||||
|
||||
### 4️⃣ Запусти инициализацию
|
||||
|
||||
```bash
|
||||
bash scripts/setup-vps.sh
|
||||
```
|
||||
|
||||
Скрипт установит Docker, настроит контейнеры и запустит приложение.
|
||||
|
||||
### 5️⃣ Проверь статус
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
Приложение готово на `http://YOUR_VPS_IP:80` 🎉
|
||||
|
||||
---
|
||||
|
||||
## 📋 Требования
|
||||
|
||||
- **OS:** Ubuntu 20.04+ (или другой Linux с Docker)
|
||||
- **RAM:** Минимум 2GB (рекомендуется 4GB)
|
||||
- **CPU:** 2 ядра (рекомендуется 4+)
|
||||
- **Диск:** 20GB свободного места (SSD лучше)
|
||||
- **Порты:** 80/TCP открыты в файрволе
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Безопасность на VPS
|
||||
|
||||
### ✅ Сделано в docker-compose.yml:
|
||||
- ❌ БД не открыта наружу (только для контейнеров)
|
||||
- ❌ Redis не открыт наружу (только для контейнеров)
|
||||
- ❌ API не открыт напрямую (только через Nginx)
|
||||
- ✅ Nginx проксирует запросы безопасно
|
||||
- ✅ Ограничение ресурсов на контейнеры
|
||||
- ✅ Health checks для отказоустойчивости
|
||||
|
||||
### ⚠️ Нужно сделать вручную:
|
||||
|
||||
#### 1. Настрой файрвол (UFW)
|
||||
```bash
|
||||
# Разреши только необходимые порты
|
||||
sudo ufw enable
|
||||
sudo ufw allow 22/tcp # SSH (для удаленного доступа)
|
||||
sudo ufw allow 80/tcp # HTTP
|
||||
sudo ufw allow 443/tcp # HTTPS (когда добавишь SSL)
|
||||
sudo ufw status
|
||||
```
|
||||
|
||||
#### 2. Добавь SSH ключи (вместо пароля)
|
||||
```bash
|
||||
# На локальной машине генерируй ключ если нет
|
||||
ssh-keygen -t ed25519 -C "your-email@example.com"
|
||||
|
||||
# Скопируй публичный ключ на VPS
|
||||
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@YOUR_VPS_IP
|
||||
|
||||
# Отключи вход по пароеи в sshd_config
|
||||
sudo nano /etc/ssh/sshd_config
|
||||
# Найди и измени на:
|
||||
# PasswordAuthentication no
|
||||
# PubkeyAuthentication yes
|
||||
|
||||
sudo systemctl reload ssh
|
||||
```
|
||||
|
||||
#### 3. Установи Let's Encrypt SSL/HTTPS
|
||||
Позже, когда будешь готов:
|
||||
```bash
|
||||
sudo apt-get install certbot python3-certbot-nginx
|
||||
sudo certbot certonly --standalone -d your-domain.com -d www.your-domain.com
|
||||
```
|
||||
|
||||
Затем обнови nginx.conf и docker-compose.yml для HTTPS.
|
||||
|
||||
#### 4. Настрой резервное копирование БД
|
||||
```bash
|
||||
# Создай backup скрипт
|
||||
mkdir -p backups
|
||||
cat > backups/backup-db.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
BACKUP_DIR="./backups"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
docker exec pg-admin-db pg_dump -U postgres pg_admin | gzip > $BACKUP_DIR/backup_$TIMESTAMP.sql.gz
|
||||
echo "✅ Backup завершен: backup_$TIMESTAMP.sql.gz"
|
||||
EOF
|
||||
|
||||
chmod +x backups/backup-db.sh
|
||||
|
||||
# Настрой cron для ежедневного backup (21:00 UTC)
|
||||
crontab -e
|
||||
# Добавь строку:
|
||||
# 0 21 * * * cd /root/pg-admin && bash backups/backup-db.sh
|
||||
```
|
||||
|
||||
#### 5. Мониторинг логов
|
||||
```bash
|
||||
# Просмотри логи всех контейнеров
|
||||
docker compose logs -f
|
||||
|
||||
# Или конкретного контейнера
|
||||
docker compose logs -f pg-admin-api
|
||||
|
||||
# Проверь дисковое пространство
|
||||
df -h
|
||||
|
||||
# Проверь использование памяти
|
||||
docker stats
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Частые команды
|
||||
|
||||
```bash
|
||||
# Посмотри статус контейнеров
|
||||
docker compose ps
|
||||
|
||||
# Перезагрузи приложение
|
||||
docker compose restart
|
||||
|
||||
# Обнови код и перестрой
|
||||
git pull origin main
|
||||
docker compose up -d --build
|
||||
|
||||
# Посмотри логи
|
||||
docker compose logs -f
|
||||
|
||||
# Останови все
|
||||
docker compose down
|
||||
|
||||
# Полная переустановка (опасно - удалит данные!)
|
||||
docker compose down -v
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Pipeline для development → production
|
||||
|
||||
1. ✅ Делай коммиты в git
|
||||
2. ✅ Пуш на main/master
|
||||
3. ✅ На VPS: `git pull origin main`
|
||||
4. ✅ На VPS: `docker compose up -d --build`
|
||||
5. ✅ Проверь: `docker compose logs -f`
|
||||
|
||||
---
|
||||
|
||||
## 📊 Проверка здоровья приложения
|
||||
|
||||
```bash
|
||||
# Проверь доступность
|
||||
curl -I http://YOUR_VPS_IP:80/
|
||||
|
||||
# Посмотри статус контейнеров
|
||||
docker compose ps
|
||||
|
||||
# Проверь память и CPU
|
||||
docker stats
|
||||
|
||||
# Посмотри логи ошибок
|
||||
docker compose logs | grep -i error
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### Контейнер крашится при старте
|
||||
```bash
|
||||
# Посмотри логи
|
||||
docker compose logs pg-admin-api
|
||||
|
||||
# Перестрой с чистого листа
|
||||
docker compose down -v
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### БД не подключается
|
||||
```bash
|
||||
# Проверь что БД запущена
|
||||
docker compose ps
|
||||
|
||||
# Проверь логи БД
|
||||
docker compose logs pg-admin-db
|
||||
|
||||
# Проверь переменные окружения
|
||||
docker compose exec pg-admin-api env | grep DB
|
||||
```
|
||||
|
||||
### Порт уже занят
|
||||
```bash
|
||||
# Найди процесс на порту 80
|
||||
sudo lsof -i :80
|
||||
|
||||
# Убей процесс (замени PID)
|
||||
sudo kill -9 PID
|
||||
|
||||
# Или смени порт в .env:
|
||||
NGINX_PORT=8080
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### No space left on device
|
||||
```bash
|
||||
# Очисти Docker образы
|
||||
docker image prune -a
|
||||
|
||||
# Очисти volumes (ОСТОРОЖНО!)
|
||||
docker volume prune
|
||||
|
||||
# Посмотри место на диске
|
||||
df -h
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 Поддержка
|
||||
|
||||
Если что-то не работает:
|
||||
1. Проверь логи: `docker compose logs -f`
|
||||
2. Проверь конфигурацию .env
|
||||
3. Посмотри порты: `sudo netstat -tlnp | grep LISTEN`
|
||||
4. Перезагрузи: `docker compose restart`
|
||||
|
||||
---
|
||||
|
||||
**Создано для pg-admin | VPS Deployment Guide v1.0**
|
||||
@@ -6,9 +6,8 @@ services:
|
||||
POSTGRES_USER: ${DB_USER:-postgres}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
|
||||
POSTGRES_DB: ${DB_NAME:-pg_admin}
|
||||
POSTGRES_INITDB_ARGS: "--encoding=UTF8"
|
||||
ports:
|
||||
- "${DB_PORT:-5432}:5432"
|
||||
POSTGRES_INITDB_ARGS: "--encoding=UTF8 -c shared_buffers=256MB -c max_connections=100"
|
||||
# БД НЕ открыта наружу - только для контейнеров
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./docker/init-db.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
@@ -19,6 +18,15 @@ services:
|
||||
retries: 5
|
||||
networks:
|
||||
- pg-admin-network
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 512M
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
memory: 256M
|
||||
|
||||
backend:
|
||||
build:
|
||||
@@ -37,8 +45,7 @@ services:
|
||||
JWT_EXPIRE: ${JWT_EXPIRE:-7d}
|
||||
MAX_CONNECTIONS: ${MAX_CONNECTIONS:-20}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
ports:
|
||||
- "${API_PORT:-3000}:${API_PORT:-3000}"
|
||||
# API НЕ открыт наружу - только для nginx
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
@@ -48,6 +55,14 @@ services:
|
||||
networks:
|
||||
- pg-admin-network
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 512M
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
memory: 256M
|
||||
|
||||
frontend:
|
||||
build:
|
||||
@@ -57,8 +72,7 @@ services:
|
||||
environment:
|
||||
REACT_APP_API_URL: ${FRONTEND_API_URL:-http://localhost:3000/api}
|
||||
REACT_APP_ENV: ${NODE_ENV:-production}
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-80}:3000"
|
||||
# Frontend НЕ открыт наружу - только для nginx
|
||||
depends_on:
|
||||
- backend
|
||||
volumes:
|
||||
@@ -66,14 +80,20 @@ services:
|
||||
networks:
|
||||
- pg-admin-network
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 512M
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
memory: 256M
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: pg-admin-cache
|
||||
ports:
|
||||
- "${REDIS_PORT:-6379}:6379"
|
||||
environment:
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-change_me}
|
||||
# Redis НЕ открыт наружу - только для контейнеров
|
||||
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
healthcheck:
|
||||
@@ -84,12 +104,20 @@ services:
|
||||
networks:
|
||||
- pg-admin-network
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 256M
|
||||
reservations:
|
||||
cpus: '0.25'
|
||||
memory: 128M
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: pg-admin-proxy
|
||||
ports:
|
||||
- "${NGINX_PORT:-8080}:80"
|
||||
- "${NGINX_PORT:-80}:80"
|
||||
volumes:
|
||||
- ./docker/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
depends_on:
|
||||
@@ -98,6 +126,14 @@ services:
|
||||
networks:
|
||||
- pg-admin-network
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 256M
|
||||
reservations:
|
||||
cpus: '0.25'
|
||||
memory: 128M
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
||||
@@ -6,22 +6,22 @@ WORKDIR /app
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies with production flag
|
||||
RUN npm ci --only=production && npm ci
|
||||
# Install dependencies
|
||||
RUN npm install
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build production bundle with optimizations
|
||||
RUN NODE_ENV=production npm run build 2>/dev/null || true
|
||||
RUN NODE_ENV=production npm run build
|
||||
|
||||
# Production stage - optimize serving
|
||||
# Production stage - minimal footprint
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install serve with gzip compression support
|
||||
RUN npm install -g serve
|
||||
# Install serve for static file serving
|
||||
RUN npm install -g serve@14
|
||||
|
||||
# Copy built app from builder
|
||||
COPY --from=builder /app/build ./build
|
||||
@@ -32,5 +32,5 @@ EXPOSE 3000
|
||||
HEALTHCHECK --interval=10s --timeout=5s --retries=5 \
|
||||
CMD wget --quiet --tries=1 --spider http://localhost:3000/ || exit 1
|
||||
|
||||
# Start server with compression and caching headers
|
||||
# Start server with gzip compression
|
||||
CMD ["serve", "-s", "build", "-l", "3000", "--gzip"]
|
||||
|
||||
31
scripts/generate-secrets.sh
Normal file
31
scripts/generate-secrets.sh
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
# Генерирование безопасных паролей и секретов для production VPS
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔐 Генерирование захищенных паролей для production..."
|
||||
echo ""
|
||||
|
||||
# Генерируем паароль для БД
|
||||
DB_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
|
||||
echo "📊 DB_PASSWORD: $DB_PASSWORD"
|
||||
|
||||
# Генерируем JWT секрет
|
||||
JWT_SECRET=$(openssl rand -base64 64 | tr -d "\n")
|
||||
echo "🔑 JWT_SECRET: $JWT_SECRET"
|
||||
|
||||
# Генерируем Redis пароль
|
||||
REDIS_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
|
||||
echo "💾 REDIS_PASSWORD: $REDIS_PASSWORD"
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo "📝 Скопируй эти значения в .env на VPS:"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "DB_PASSWORD=$DB_PASSWORD"
|
||||
echo "JWT_SECRET=$JWT_SECRET"
|
||||
echo "REDIS_PASSWORD=$REDIS_PASSWORD"
|
||||
echo ""
|
||||
echo "⚠️ НЕ коммитьи эти значения в git!"
|
||||
echo "⚠️ Храни .env в безопасном месте, не в репозитории!"
|
||||
79
scripts/setup-vps.sh
Normal file
79
scripts/setup-vps.sh
Normal file
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
# Инициализация Django приложения на VPS (Ubuntu 24.04)
|
||||
# Запуск: bash scripts/setup-vps.sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Инициализация pg-admin на VPS..."
|
||||
echo ""
|
||||
|
||||
# Проверяем что мы на VPS (Ubuntu)
|
||||
if ! grep -qi ubuntu /etc/os-release; then
|
||||
echo "⚠️ Это скрипт для Ubuntu. Попробуй вручную для другой OS."
|
||||
fi
|
||||
|
||||
# 1. Обновляем систему
|
||||
echo "📦 Обновление системы..."
|
||||
sudo apt-get update
|
||||
sudo apt-get upgrade -y
|
||||
|
||||
# 2. Устанавливаем Docker если его нет
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "🐳 Установка Docker..."
|
||||
sudo apt-get install -y docker.io docker-compose-plugin
|
||||
sudo usermod -aG docker $USER
|
||||
echo "⚠️ Нужен перелогин для работы docker без sudo. Выполни: newgrp docker"
|
||||
else
|
||||
echo "✅ Docker уже установлен"
|
||||
fi
|
||||
|
||||
# 3. Создаем .env если его нет
|
||||
if [ ! -f .env ]; then
|
||||
echo "📝 Создание .env из .env.example..."
|
||||
cp .env.example .env
|
||||
echo ""
|
||||
echo "⚠️ ВАЖНО! Отредактируй .env:"
|
||||
echo " - Замени CHANGE_ME_TO_STRONG_PASSWORD на реальный пароль"
|
||||
echo " - Замени CHANGE_ME_TO_STRONG_RANDOM_SECRET на реальный секрет"
|
||||
echo " - Замени your-domain.com на твой домен"
|
||||
echo " - Используй скрипт: bash scripts/generate-secrets.sh"
|
||||
echo ""
|
||||
echo "📝 Открой .env в редакторе и отредактируй значения:"
|
||||
echo " nano .env"
|
||||
exit 1
|
||||
else
|
||||
echo "✅ .env файл уже существует"
|
||||
fi
|
||||
|
||||
# 4. Останавливаем старые контейнеры
|
||||
echo "🛑 Остановка старых контейнеров..."
|
||||
docker compose down -v --remove-orphans || true
|
||||
|
||||
# 5. Создаем необходимые папки
|
||||
echo "📁 Создание папок..."
|
||||
mkdir -p backend/logs
|
||||
mkdir -p logs
|
||||
|
||||
# 6. Собираем и запускаем контейнеры
|
||||
echo "🔨 Сборка и запуск контейнеров..."
|
||||
docker compose up -d --build
|
||||
|
||||
# 7. Проверяем статус
|
||||
echo ""
|
||||
echo "✅ Инициализация завершена!"
|
||||
echo ""
|
||||
echo "📊 Статус контейнеров:"
|
||||
docker compose ps
|
||||
|
||||
echo ""
|
||||
echo "🌐 Приложение доступно по адресу:"
|
||||
echo " http://YOUR_VPS_IP:80"
|
||||
echo ""
|
||||
echo "📝 Логи:"
|
||||
echo " docker compose logs -f"
|
||||
echo ""
|
||||
echo "💡 Рекомендации:"
|
||||
echo " 1. Настрой файрвол (UFW): sudo ufw allow 80,443/tcp"
|
||||
echo " 2. Добавь SSL (Let's Encrypt) когда будешь готов"
|
||||
echo " 3. Настрой резервное копирование БД"
|
||||
echo " 4. Настрой мониторинг"
|
||||
Reference in New Issue
Block a user