Files
octopus/myproject/docker/DEPLOY_NAS.md
Andrey Smakotin 0bddbc08c4 feat: Добавлен флаг is_superuser для platform_support и сохранение credentials в файл
- Platform support пользователь теперь создается с is_superuser=True для полного доступа
- Добавлено сохранение credentials (домен:логин:пароль) в support_credentials.txt
- Добавлен support_credentials.txt в .gitignore для безопасности
- Обновлена документация развертывания на NAS

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 00:02:10 +03:00

491 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Развёртывание на TerraMaster F2-424 (TOS 6)
## Требования
- TerraMaster NAS с TOS 6
- Docker и Docker Compose установлены
- SSH доступ к NAS
- 32 GB RAM (более чем достаточно)
## Структура на NAS
```
/Volume1/DockerYAML/mix/ # Только docker-compose.yml
└── docker-compose.yml
/Volume1/DockerAppsData/mixapp/ # Всё остальное
├── app/ # Код приложения (весь проект)
│ ├── myproject/
│ ├── requirements.txt
│ └── docker/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── .env.docker
├── postgres/ # База данных PostgreSQL
├── redis/ # Данные Redis
├── media/ # Загруженные файлы (фото товаров)
└── static/ # Статические файлы Django
```
## Шаг 1: Подготовка директорий на NAS
```bash
# Подключаемся к NAS по SSH
ssh admin@<NAS_IP>
# Создаём директории
mkdir -p /Volume1/DockerAppsData/mixapp/{app,postgres,redis,media,static}
mkdir -p /Volume1/DockerYAML/mix
# Устанавливаем права (uid 1000 для контейнера appuser)
chown -R 1000:1000 /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 /Volume1/DockerAppsData/mixapp/media
chown -R 1000:1000 /Volume1/DockerAppsData/mixapp/static
chmod -R u+rwX /Volume1/DockerAppsData/mixapp
chown -R 1000:1000 /Volume1/DockerYAML/mix
```
## Шаг 2: Копирование файлов проекта на NAS
### Вариант A: Через SCP (с Windows)
```powershell
# Из папки проекта на Windows
cd C:\Users\team_\Desktop\test_qwen
# Копируем код приложения в папку данных
scp -r myproject requirements.txt docker .dockerignore admin@<NAS_IP>:/Volume1/DockerAppsData/mixapp/app/
# Копируем docker-compose.yml в папку YAML
scp docker/docker-compose.yml admin@<NAS_IP>:/Volume1/DockerYAML/mix/
```
### Вариант B: Через общую папку SMB
1. Подключите сетевую папку NAS
2. Скопируйте содержимое папки проекта (`myproject/`, `requirements.txt`, `docker/` и т.д.) в `/Volume1/DockerAppsData/mixapp/app/`
3. Скопируйте `docker/docker-compose.yml` в `/Volume1/DockerYAML/mix/`
## Шаг 3: Настройка переменных окружения
```bash
# На NAS
cd /Volume1/DockerAppsData/mixapp/app/docker
# Редактируем .env.docker
nano .env.docker
```
**ВАЖНО! Измените следующие значения:**
```env
# Django settings
SECRET_KEY=ваш-очень-длинный-секретный-ключ-минимум-50-символов
DEBUG=False
ALLOWED_HOSTS=*
CSRF_TRUSTED_ORIGINS=https://mix.smaa.by,https://*.mix.smaa.by
DOMAIN_NAME=mix.smaa.by
# Database (PostgreSQL)
DB_NAME=inventory_db
DB_USER=postgres
DB_PASSWORD=ваш-надежный-пароль-postgres
DB_HOST=db
DB_PORT=5432
# Значения для официального образа Postgres (ДОЛЖНЫ СОВПАДАТЬ с DB_*)
POSTGRES_DB=inventory_db
POSTGRES_USER=postgres
POSTGRES_PASSWORD=ваш-надежный-пароль-postgres
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_DB=0
# Celery
CELERY_BROKER_URL=redis://redis:6379/0
# Platform Admin (администратор платформы - создаётся автоматически)
PLATFORM_ADMIN_EMAIL=admin@mix.smaa.by
PLATFORM_ADMIN_PASSWORD=ваш-надёжный-пароль-минимум-16-символов
PLATFORM_ADMIN_NAME=Platform Admin
# Django-tenants
PUBLIC_SCHEMA_DOMAIN=mix.smaa.by
TENANT_DOMAIN_BASE=mix.smaa.by
USE_HTTPS=True
```
### ⚠️ КРИТИЧЕСКИ ВАЖНО:
1. **`DB_PASSWORD` и `POSTGRES_PASSWORD` ДОЛЖНЫ БЫТЬ ОДИНАКОВЫМИ!**
Иначе Django не сможет подключиться к PostgreSQL.
2. **В `docker-compose.yml` у сервиса `db` НЕ должно быть блока `environment:`**
Все переменные читаются напрямую из `.env.docker` через `env_file`.
3. **При смене пароля БД после первого запуска:**
Простое изменение `POSTGRES_PASSWORD` в `.env.docker` НЕ изменит пароль существующей базы.
Нужно пересоздать данные PostgreSQL:
```bash
cd /Volume1/DockerYAML/mix
docker-compose down
rm -rf /Volume1/DockerAppsData/mixapp/postgres
docker-compose up -d --build
```
⚠️ **Это удалит все данные в БД!**
### Генерация SECRET_KEY:
```bash
python3 -c "import secrets; print(secrets.token_urlsafe(64))"
```
## Шаг 4: Исправление прав entrypoint.sh и файлов проекта
```bash
# Конвертируем из Windows формата (CRLF -> LF)
cd /Volume1/DockerAppsData/mixapp/app/myproject/docker
sed -i 's/\r$//' entrypoint.sh
chmod +x entrypoint.sh
# Убедитесь, что весь проект принадлежит UID 1000 (appuser внутри контейнера)
cd /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 myproject
chmod -R u+rwX myproject
```
## Шаг 5: Сборка и запуск
```bash
cd /Volume1/DockerYAML/mix
# Запускаем в фоновом режиме (автоматически соберет образы, используя пути из yml)
docker-compose up -d --build
# Проверяем статус
docker-compose ps
# Смотрим логи
docker-compose logs -f
```
## Шаг 6: Первичная настройка
При первом запуске автоматически:
1. Создаётся база данных PostgreSQL
2. Применяются миграции Django
3. Собираются статические файлы
4. Создаётся public tenant
5. **Создаётся PlatformAdmin** из переменных `PLATFORM_ADMIN_*` в `.env.docker`
### Проверка работоспособности:
```bash
# Проверяем что все контейнеры работают
docker-compose ps
# Должны быть в статусе "Up":
# - mix_postgres
# - mix_redis
# - mix_web
# - mix_celery_worker
# - mix_celery_beat
```
## Шаг 7: Настройка Nginx (на NAS или внешний)
### Пример конфигурации nginx:
```nginx
# Upstream для Django
upstream mix_django {
server 127.0.0.1:8000;
}
# HTTP -> HTTPS редирект
server {
listen 80;
server_name mix.smaa.by *.mix.smaa.by;
return 301 https://$host$request_uri;
}
# HTTPS сервер
server {
listen 443 ssl http2;
server_name mix.smaa.by *.mix.smaa.by;
# SSL сертификаты (Let's Encrypt или свои)
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# Безопасность
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# Лимиты
client_max_body_size 50M;
# Статические файлы
location /static/ {
alias /Volume1/DockerAppsData/mixapp/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Медиа файлы
location /media/ {
alias /Volume1/DockerAppsData/mixapp/media/;
expires 7d;
add_header Cache-Control "public";
}
# Django приложение
location / {
proxy_pass http://mix_django;
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 support (если понадобится)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Таймауты
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
```
## Создание тенантов (магазинов)
**Рекомендуемый способ:** Через форму регистрации и активацию в админке.
1. Пользователь заполняет форму на `https://mix.smaa.by/register/`
2. PlatformAdmin входит в `https://mix.smaa.by/admin/`
3. В разделе "Заявки на регистрацию" нажимает "Активировать"
При активации автоматически:
- Создаётся тенант и домен
- Применяются миграции
- Создаётся владелец (CustomUser)
- Инициализируются данные (склад, статусы и т.д.)
- Отправляется email с ссылкой для установки пароля
### Архитектура пользователей
| Модель | Schema | Доступ |
|--------|--------|--------|
| `PlatformAdmin` | public | Django Admin везде |
| `CustomUser` | tenant | Только фронтенд |
PlatformAdmin может войти в Django Admin любого тенанта для техподдержки.
## Полезные команды
```bash
# Переходим в папку с docker-compose.yml
cd /Volume1/DockerYAML/mix
# Перезапуск всех контейнеров
docker-compose restart
# Перезапуск только web
docker-compose restart web
# Просмотр логов конкретного сервиса
docker-compose logs -f web
docker-compose logs -f celery-worker
# Выполнение команд Django
docker-compose exec web python manage.py shell
docker-compose exec web python manage.py createsuperuser
docker-compose exec web python manage.py migrate_schemas --shared
# Остановка
docker-compose down
# Остановка с удалением volumes (ОСТОРОЖНО - удалит данные!)
docker-compose down -v
```
## Резервное копирование
### База данных:
```bash
# Создание бэкапа
docker-compose exec db pg_dump -U postgres inventory_db > backup_$(date +%Y%m%d).sql
# Восстановление
cat backup.sql | docker-compose exec -T db psql -U postgres inventory_db
```
### Медиа файлы:
```bash
# Бэкап медиа
tar -czvf media_backup_$(date +%Y%m%d).tar.gz /Volume1/DockerAppsData/mixapp/media/
```
## Обновление приложения
```bash
cd /Volume1/DockerYAML/mix
# Остановить контейнеры
docker-compose down
# Обновить код в /Volume1/DockerAppsData/mixapp/app/
# (скопировать новые файлы myproject/, requirements.txt, docker/)
# ⚠️ КРИТИЧЕСКИ ВАЖНО: После КАЖДОГО обновления кода настроить права доступа!
cd /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 myproject
chmod -R u+rwX myproject
# Вернуться в папку с docker-compose.yml
cd /Volume1/DockerYAML/mix
# Пересобрать образы
docker-compose build --no-cache
# Запустить
docker-compose up -d
```
**⚠️ ВАЖНО:** Если после обновления кода контейнеры не запускаются или тенанты недоступны (404),
первым делом проверьте права доступа командами выше!
## Мониторинг
```bash
# Статус контейнеров
docker-compose ps
# Использование ресурсов
docker stats
# Логи в реальном времени
docker-compose logs -f --tail=100
```
## Возможные проблемы
### 1. Ошибка "permission denied" для entrypoint.sh
```bash
sed -i 's/\r$//' entrypoint.sh
chmod +x entrypoint.sh
```
### 2. PostgreSQL не запускается
```bash
# Проверьте логи
docker-compose logs db
# Возможно нужны права на директорию
sudo chown -R 999:999 /Volume1/DockerAppsData/mixapp/postgres
```
### 3. Celery не подключается к Redis
```bash
# Проверьте что Redis запущен
docker-compose logs redis
# Проверьте сеть
docker-compose exec web ping redis
```
### 4. Статические файлы не отображаются
```bash
# Пересоберите статику
docker-compose exec web python manage.py collectstatic --noinput
# Проверьте права
sudo chown -R 1000:1000 /Volume1/DockerAppsData/mixapp/static
```
### 5. Ошибка "password authentication failed for user postgres"
**Причина:** `DB_PASSWORD` и `POSTGRES_PASSWORD` в `.env.docker` не совпадают, или в `docker-compose.yml` у сервиса `db` есть блок `environment` с дефолтными значениями `${DB_PASSWORD:-postgres}`.
**Решение:**
1. Откройте `/Volume1/DockerAppsData/mixapp/app/myproject/docker/.env.docker`
2. Убедитесь, что `DB_PASSWORD` и `POSTGRES_PASSWORD` **ОДИНАКОВЫЕ**
3. Проверьте `docker-compose.yml` — у сервиса `db` должно быть только `env_file`, **БЕЗ блока `environment`**:
```yaml
db:
image: postgres:15-alpine
env_file:
- /Volume1/DockerAppsData/mixapp/app/myproject/docker/.env.docker
# НЕ ДОЛЖНО БЫТЬ:
# environment:
# - POSTGRES_PASSWORD=${DB_PASSWORD:-postgres}
```
4. Пересоздайте базу данных:
```bash
cd /Volume1/DockerYAML/mix
docker-compose down
rm -rf /Volume1/DockerAppsData/mixapp/postgres
docker-compose up -d --build
```
5. Проверьте, что пароли совпадают внутри контейнера:
```bash
docker exec -it mix_postgres env | grep -E 'POSTGRES_PASSWORD|DB_PASSWORD'
```
Оба должны показывать одинаковое значение.
### 6. Ошибка "Permission denied" для /app/manage.py
**Причина:** Файлы проекта на хосте принадлежат не тому пользователю (не UID 1000).
**Решение:**
```bash
cd /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 myproject
chmod -R u+rwX myproject
cd /Volume1/DockerYAML/mix
docker-compose restart web celery-worker celery-beat
```
### 7. Новый тенант создан, но его поддомен возвращает HTTP 404
**Причина:** Чаще всего — контейнер `web` постоянно перезапускается из-за `Permission denied` на `/app/manage.py`, и Django не успевает запуститься.
**Диагностика:**
1. Проверьте, что домен создан в базе:
```bash
docker exec -it mix_web python manage.py shell
```
```python
from tenants.models import Client, Domain
for domain in Domain.objects.all():
print(f"Domain: {domain.domain}, Tenant: {domain.tenant.schema_name}")
```
Если домен есть — проблема не в базе.
2. Посмотрите логи контейнера:
```bash
docker logs -f mix_web
```
Если видите множество повторяющихся сообщений:
```
python: can't open file '/app/manage.py': [Errno 13] Permission denied
Waiting for PostgreSQL...
```
Это значит, что контейнер падает и перезапускается.
**Решение:**
```bash
cd /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 myproject
chmod -R u+rwX myproject
cd /Volume1/DockerYAML/mix
docker-compose restart web celery-worker celery-beat
```
После этого контейнер перестанет падать, Django запустится, и поддомен тенанта станет доступен.