chore: reorganize project structure and prepare for deployment

- Organize files into logical directories (docs/, scripts/, tests/)
- Add comprehensive documentation (README, CONTRIBUTING, CHANGELOG)
- Create deployment automation scripts
- Add Docker production configuration
- Update .gitignore and add .dockerignore
- Remove temporary and test files from root
- Improve settings.py with DEBUG from env variable

Added:
- README.md with project overview
- CONTRIBUTING.md for contributors
- CHANGELOG.md for version tracking
- PROJECT_STATUS.md with current state
- docker-compose.prod.yml for production
- nginx.conf for production web server
- scripts/deploy.sh for automated deployment
- scripts/check-config.sh for configuration validation
- scripts/setup-ssl.sh for SSL certificate setup
- docs/DEPLOYMENT.md with detailed deployment guide
- docs/ENV_VARIABLES.md with all environment variables

Moved:
- Documentation to docs/
- Scripts to scripts/
- Test files to tests/

Removed:
- .history/ directory
- Test response JSON files from root
- settings_production.py (merged into settings.py)

This commit prepares the project for:
- Production deployment
- Team collaboration
- Docker containerization
- Proper documentation
This commit is contained in:
2025-11-24 07:12:04 +09:00
parent 7bf003e70d
commit d9adac609b
26 changed files with 1869 additions and 11 deletions

154
scripts/README.md Normal file
View File

@@ -0,0 +1,154 @@
# Scripts
Скрипты для управления и деплоя SmartSolTech.
## Доступные скрипты
### 🚀 deploy.sh
Автоматический деплой приложения в Docker.
**Использование:**
```bash
chmod +x deploy.sh
./deploy.sh
```
**Что делает:**
- Проверяет наличие .env файла
- Останавливает существующие контейнеры
- Собирает Docker образы
- Запускает PostgreSQL
- Применяет миграции БД
- Собирает статику
- Запускает все сервисы
---
### 🔍 check-config.sh
Проверка конфигурации проекта перед деплоем.
**Использование:**
```bash
chmod +x check-config.sh
./check-config.sh
```
**Проверяет:**
- Наличие .env файла и обязательных переменных
- Установку Docker и Docker Compose
- Наличие необходимых файлов
- Права доступа к скриптам
---
### 🔒 setup-ssl.sh
Настройка SSL сертификатов Let's Encrypt для production.
**Использование:**
```bash
chmod +x setup-ssl.sh
./setup-ssl.sh your-domain.com admin@your-domain.com
```
**Параметры:**
- `domain` - Ваш домен (например, smartsoltech.kr)
- `email` - Email для уведомлений Let's Encrypt
**Что делает:**
- Создает директории для сертификатов
- Запрашивает SSL сертификат через Certbot
- Генерирует конфигурацию Nginx с HTTPS
- Настраивает автоматическое обновление сертификатов
---
### 📱 update_telegram_token.py
Обновление токена Telegram бота в базе данных.
**Использование:**
```bash
# Внутри Docker контейнера
docker-compose exec web python scripts/update_telegram_token.py
# Или напрямую с Python
python scripts/update_telegram_token.py
```
**Что делает:**
- Проверяет валидность нового токена
- Обновляет токен в базе данных
- Сохраняет информацию о боте
**Получение токена:**
1. Откройте [@BotFather](https://t.me/BotFather) в Telegram
2. Отправьте `/mybots`
3. Выберите своего бота
4. Нажмите "API Token"
---
### 🔄 update_bot_token.sh
Shell скрипт для обновления токена бота (обертка для Python скрипта).
**Использование:**
```bash
chmod +x update_bot_token.sh
./update_bot_token.sh "YOUR_BOT_TOKEN"
```
---
## Общие рекомендации
### Права доступа
Все скрипты должны быть исполняемыми:
```bash
chmod +x scripts/*.sh
```
### Production деплой
Для production используйте:
```bash
# 1. Проверьте конфигурацию
./scripts/check-config.sh
# 2. Настройте SSL (опционально)
./scripts/setup-ssl.sh your-domain.com your-email@example.com
# 3. Запустите деплой с production конфигурацией
docker-compose -f docker-compose.prod.yml up -d
```
### Development
Для разработки:
```bash
# Используйте обычный docker-compose.yml
./scripts/deploy.sh
```
## Troubleshooting
### Скрипт не запускается
```bash
# Проверьте права доступа
ls -la scripts/
# Добавьте права на выполнение
chmod +x scripts/*.sh
```
### Ошибка "command not found"
```bash
# Запускайте скрипты с ./
./scripts/deploy.sh
# Или из корня проекта
bash scripts/deploy.sh
```
### Docker команды не работают
Убедитесь, что Docker и Docker Compose установлены:
```bash
docker --version
docker-compose --version
```

102
scripts/check-config.sh Executable file
View File

@@ -0,0 +1,102 @@
#!/bin/bash
# Configuration check script for SmartSolTech
echo "🔍 Checking SmartSolTech configuration..."
echo ""
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Check if .env file exists
if [ -f .env ]; then
echo -e "${GREEN}${NC} .env file found"
# Check required variables
required_vars=("SECRET_KEY" "POSTGRES_DB" "POSTGRES_USER" "POSTGRES_PASSWORD" "POSTGRES_HOST" "PGADMIN_DEFAULT_EMAIL" "PGADMIN_DEFAULT_PASSWORD")
for var in "${required_vars[@]}"; do
if grep -q "^${var}=" .env; then
value=$(grep "^${var}=" .env | cut -d '=' -f2)
if [ -n "$value" ] && [ "$value" != "your-" ] && [[ ! "$value" =~ ^your- ]]; then
echo -e "${GREEN}${NC} $var is set"
else
echo -e "${YELLOW}${NC} $var needs to be configured"
fi
else
echo -e "${RED}${NC} $var is missing"
fi
done
else
echo -e "${RED}${NC} .env file not found"
echo -e "${YELLOW}${NC} Copy .env.example to .env and configure it"
fi
echo ""
# Check Docker
if command -v docker &> /dev/null; then
echo -e "${GREEN}${NC} Docker is installed"
docker --version
else
echo -e "${RED}${NC} Docker is not installed"
fi
echo ""
# Check Docker Compose
if command -v docker-compose &> /dev/null; then
echo -e "${GREEN}${NC} Docker Compose is installed"
docker-compose --version
else
echo -e "${RED}${NC} Docker Compose is not installed"
fi
echo ""
# Check required files
required_files=("Dockerfile" "docker-compose.yml" "requirements.txt" "wait-for-it.sh")
for file in "${required_files[@]}"; do
if [ -f "$file" ]; then
echo -e "${GREEN}${NC} $file exists"
else
echo -e "${RED}${NC} $file is missing"
fi
done
echo ""
# Check wait-for-it.sh is executable
if [ -f "wait-for-it.sh" ] && [ -x "wait-for-it.sh" ]; then
echo -e "${GREEN}${NC} wait-for-it.sh is executable"
else
echo -e "${YELLOW}${NC} wait-for-it.sh is not executable (will be set in Docker)"
fi
echo ""
# Check Python version in requirements
if [ -f "requirements.txt" ]; then
echo -e "${GREEN}${NC} Python dependencies:"
grep -E "^Django==|^psycopg2|^python-telegram-bot==" requirements.txt
fi
echo ""
# Summary
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📋 Next steps:"
echo ""
if [ ! -f .env ]; then
echo "1. Create .env file: cp .env.example .env"
echo "2. Edit .env with your configuration: nano .env"
fi
echo "3. Generate SECRET_KEY:"
echo ' python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"'
echo "4. Update ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS in .env"
echo "5. Run deployment: ./deploy.sh"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

60
scripts/deploy.sh Executable file
View File

@@ -0,0 +1,60 @@
#!/bin/bash
# Production deployment script for SmartSolTech
set -e
echo "🚀 Starting SmartSolTech deployment..."
# Check if .env file exists
if [ ! -f .env ]; then
echo "⚠️ .env file not found!"
echo "Creating .env from .env.example..."
cp .env.example .env
echo "📝 Please edit .env file with your production values before continuing."
exit 1
fi
# Stop existing containers
echo "🛑 Stopping existing containers..."
docker-compose down
# Build images
echo "🏗️ Building Docker images..."
docker-compose build --no-cache
# Start services
echo "▶️ Starting services..."
docker-compose up -d postgres_db
# Wait for database to be ready
echo "⏳ Waiting for database to be ready..."
sleep 10
# Run migrations
echo "🔄 Running database migrations..."
docker-compose run --rm web python smartsoltech/manage.py migrate
# Collect static files
echo "📦 Collecting static files..."
docker-compose run --rm web python smartsoltech/manage.py collectstatic --noinput
# Create superuser (optional, commented out for security)
# echo "👤 Creating superuser..."
# docker-compose run --rm web python smartsoltech/manage.py createsuperuser
# Start all services
echo "🎬 Starting all services..."
docker-compose up -d
# Show running containers
echo "✅ Deployment complete! Running containers:"
docker-compose ps
echo ""
echo "📋 Service URLs:"
echo " Django App: http://localhost:8000"
echo " PgAdmin: http://localhost:8080"
echo ""
echo "📝 To view logs: docker-compose logs -f"
echo "🛑 To stop: docker-compose down"

131
scripts/setup-ssl.sh Executable file
View File

@@ -0,0 +1,131 @@
#!/bin/bash
# SSL Setup script using Let's Encrypt for SmartSolTech
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: ./setup-ssl.sh <domain> <email>"
echo "Example: ./setup-ssl.sh smartsoltech.kr admin@smartsoltech.kr"
exit 1
fi
DOMAIN=$1
EMAIL=$2
echo "🔒 Setting up SSL for $DOMAIN..."
# Create directories
mkdir -p certbot/conf
mkdir -p certbot/www
# Stop nginx if running
docker-compose -f docker-compose.prod.yml stop nginx 2>/dev/null || true
# Get certificate
echo "📝 Requesting SSL certificate..."
docker-compose -f docker-compose.prod.yml run --rm certbot certonly \
--webroot \
--webroot-path=/var/www/certbot \
--email $EMAIL \
--agree-tos \
--no-eff-email \
--force-renewal \
-d $DOMAIN \
-d www.$DOMAIN
if [ $? -eq 0 ]; then
echo "✅ SSL certificate obtained successfully!"
# Update nginx configuration for HTTPS
cat > nginx-ssl.conf << 'EOF'
upstream django_app {
server web:8000;
}
# HTTP redirect to HTTPS
server {
listen 80;
server_name DOMAIN_PLACEHOLDER www.DOMAIN_PLACEHOLDER;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$server_name$request_uri;
}
}
# HTTPS server
server {
listen 443 ssl http2;
server_name DOMAIN_PLACEHOLDER www.DOMAIN_PLACEHOLDER;
ssl_certificate /etc/letsencrypt/live/DOMAIN_PLACEHOLDER/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/DOMAIN_PLACEHOLDER/privkey.pem;
# SSL settings
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;
client_max_body_size 20M;
# 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;
location / {
proxy_pass http://django_app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_redirect off;
proxy_buffering off;
}
location /static/ {
alias /app/smartsoltech/staticfiles/;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /media/ {
alias /app/smartsoltech/media/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Deny access to sensitive files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
EOF
# Replace domain placeholder
sed -i "s/DOMAIN_PLACEHOLDER/$DOMAIN/g" nginx-ssl.conf
echo ""
echo "📋 SSL certificate installed!"
echo ""
echo "Next steps:"
echo "1. Replace nginx.conf with nginx-ssl.conf:"
echo " mv nginx-ssl.conf nginx.conf"
echo ""
echo "2. Update .env file with your domain:"
echo " ALLOWED_HOSTS=localhost,127.0.0.1,$DOMAIN,www.$DOMAIN"
echo " CSRF_TRUSTED_ORIGINS=https://$DOMAIN,https://www.$DOMAIN"
echo ""
echo "3. Restart services:"
echo " docker-compose -f docker-compose.prod.yml restart"
else
echo "❌ Failed to obtain SSL certificate"
exit 1
fi

50
scripts/update_bot_token.sh Executable file
View File

@@ -0,0 +1,50 @@
#!/bin/bash
# Скрипт для обновления токена Telegram бота
# Использование: ./update_bot_token.sh "НОВЫЙ_ТОКЕН"
if [ $# -eq 0 ]; then
echo "❌ Ошибка: Необходимо указать токен"
echo "Использование: $0 \"НОВЫЙ_ТОКЕН\""
echo ""
echo "Пример: $0 \"1234567890:ABCDEFghijklmnopqrstuvwxyz\""
echo ""
echo "Получите токен от @BotFather в Telegram:"
echo "1. Отправьте /mybots"
echo "2. Выберите своего бота"
echo "3. Нажмите 'API Token'"
exit 1
fi
NEW_TOKEN="$1"
echo "🔄 Обновление токена Telegram бота..."
# Проверяем валидность токена
echo "🔍 Проверка валидности токена..."
RESPONSE=$(curl -s "https://api.telegram.org/bot${NEW_TOKEN}/getMe")
if echo "$RESPONSE" | grep -q '"ok":true'; then
BOT_USERNAME=$(echo "$RESPONSE" | grep -o '"username":"[^"]*"' | cut -d'"' -f4)
echo "✅ Токен валиден! Бот: @${BOT_USERNAME}"
else
echo "❌ Ошибка: Токен невалиден!"
echo "Ответ API: $RESPONSE"
exit 1
fi
# Обновляем токен в базе данных
echo "💾 Обновление токена в базе данных..."
docker exec postgres_db psql -U trevor -d 2st_db -c "
UPDATE comunication_telegramsettings
SET bot_token = '$NEW_TOKEN', bot_name = '@${BOT_USERNAME}'
WHERE id = 1;
"
if [ $? -eq 0 ]; then
echo "✅ Токен успешно обновлен в базе данных!"
echo "🔄 Перезапуск контейнера telegram_bot..."
docker restart telegram_bot
echo "🎉 Готово! Проверьте логи: docker logs telegram_bot"
else
echo "❌ Ошибка при обновлении базы данных"
exit 1
fi

View File

@@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""
Скрипт для обновления токена Telegram бота в базе данных
"""
import os
import sys
import django
import requests
# Настройка Django
sys.path.append('/app/smartsoltech')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'smartsoltech.settings')
django.setup()
from comunication.models import TelegramSettings
def validate_token(token):
"""Проверяет валидность токена через Telegram API"""
url = f"https://api.telegram.org/bot{token}/getMe"
try:
response = requests.get(url, timeout=10)
return response.json().get('ok', False)
except requests.RequestException:
return False
def update_telegram_token(new_token, bot_name=None):
"""Обновляет токен Telegram бота в базе данных"""
# Проверяем валидность токена
if not validate_token(new_token):
print(f"❌ Ошибка: Токен {new_token} невалиден!")
return False
# Получаем информацию о боте
url = f"https://api.telegram.org/bot{new_token}/getMe"
response = requests.get(url)
bot_info = response.json()
if bot_info.get('ok'):
bot_username = bot_info['result']['username']
print(f"✅ Токен валиден. Бот: @{bot_username}")
# Обновляем настройки в базе данных
telegram_settings, created = TelegramSettings.objects.get_or_create(
id=1,
defaults={
'bot_name': f"@{bot_username}",
'bot_token': new_token,
'use_polling': True
}
)
if not created:
telegram_settings.bot_token = new_token
telegram_settings.bot_name = bot_name or f"@{bot_username}"
telegram_settings.save()
print(f"✅ Токен обновлен в базе данных для бота {telegram_settings.bot_name}")
else:
print(f"✅ Создана новая запись для бота @{bot_username}")
return True
else:
print(f"❌ Ошибка при получении информации о боте")
return False
if __name__ == "__main__":
print("🤖 Скрипт обновления токена Telegram бота")
print("=" * 50)
# Проверяем текущий токен
try:
current_settings = TelegramSettings.objects.first()
if current_settings:
print(f"Текущий бот: {current_settings.bot_name}")
print(f"Текущий токен: {current_settings.bot_token[:10]}...")
if not validate_token(current_settings.bot_token):
print("❌ Текущий токен невалиден")
else:
print("✅ Текущий токен валиден")
else:
print("⚠️ Настройки Telegram бота не найдены")
except Exception as e:
print(f"❌ Ошибка при проверке текущих настроек: {e}")
print("\n" + "=" * 50)
print("Для обновления токена:")
print("1. Идите к @BotFather в Telegram")
print("2. Создайте нового бота или используйте /token для существующего")
print("3. Скопируйте токен и введите его ниже")
print("=" * 50)
new_token = input("\nВведите новый токен бота (или 'exit' для выхода): ").strip()
if new_token.lower() == 'exit':
print("Выход...")
sys.exit(0)
if update_telegram_token(new_token):
print("\n🎉 Токен успешно обновлен!")
print("Теперь перезапустите контейнер telegram_bot:")
print("docker restart telegram_bot")
else:
print("\nНе удалось обновить токен")