# Развёртывание Social Graph на сервере Инструкция для Linux-сервера (Ubuntu/Debian). Приложение публикуется через Docker; снаружи доступен только веб-прокси (80/443). > **Production:** [deploy/social.deepfishing.ru.md](./social.deepfishing.ru.md) — инструкция для https://social.deepfishing.ru ## Схема ```text Интернет :80 / :443 ↓ Прокси на хосте (Apache или nginx) ↓ ┌───────────────────────────────────────┐ │ frontend-контейнер (nginx) │ │ 127.0.0.1:8080 → SPA + статика │ └───────────────────────────────────────┘ ↓ (только в режиме remote) ┌───────────────────────────────────────┐ │ backend-контейнер (gunicorn) │ │ 127.0.0.1:8000 → Django API │ │ SQLite в Docker volume │ └───────────────────────────────────────┘ ``` | Режим | Где данные | Backend на сервере | |-------|------------|--------------------| | **local** (по умолчанию) | IndexedDB в браузере каждого пользователя | не нужен | | **remote** | SQLite на сервере, общая БД | обязателен | Режим задаётся при **сборке** фронтенда (`VITE_DATA_MODE`). --- ## 1. Требования к серверу - Linux (Ubuntu 22.04+ / Debian 12+) - Docker Engine + Docker Compose plugin - Git - Домен, указывающий на IP сервера (для HTTPS) - Apache2 **или** nginx на хосте (reverse proxy) Установка Docker (если ещё нет): ```bash curl -fsSL https://get.docker.com | sh sudo usermod -aG docker "$USER" # перелогиньтесь, чтобы группа docker применилась docker compose version ``` --- ## 2. Клонирование проекта ```bash sudo mkdir -p /opt/social-graph sudo chown "$USER:$USER" /opt/social-graph git clone /opt/social-graph cd /opt/social-graph git checkout main # или нужная ветка ``` --- ## 3. Конфигурация окружения ```bash cp deploy/.env.prod.example deploy/.env.prod nano deploy/.env.prod ``` ### Вариант A — local-first (данные только в браузере) Подходит, если сервер — просто «хостинг интерфейса», без общей базы. ```env VITE_DATA_MODE=local FRONTEND_BIND=127.0.0.1 FRONTEND_PORT=8080 ``` Backend **не поднимается**. Каждый пользователь хранит данные локально; при смене браузера или устройства данные не переносятся автоматически (экспорт/импорт — через UI → Импорт). ### Вариант B — remote (данные на сервере, вход по логину) Подходит для команды или одного аккаунта с доступом с разных устройств. ```env VITE_DATA_MODE=remote FRONTEND_BIND=127.0.0.1 FRONTEND_PORT=8080 BACKEND_BIND=127.0.0.1 BACKEND_PORT=8000 DJANGO_SECRET_KEY=сгенерируйте-длинную-случайную-строку ALLOWED_HOSTS=your-domain.com,www.your-domain.com USE_JWT_AUTH=true ``` Сгенерировать секретный ключ: ```bash python3 -c "import secrets; print(secrets.token_urlsafe(50))" ``` Файл `deploy/.env.prod` **не коммитить** — в нём секреты. --- ## 4. Сборка и запуск контейнеров Перейдите в каталог проекта: ```bash cd /opt/social-graph ``` ### Только frontend (режим local) ```bash docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend ``` ### Frontend + backend (режим remote) ```bash docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod build docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod --profile with-backend up -d --build backend ``` Проверка: ```bash docker compose -f docker-compose.prod.yml ps curl -s -o /dev/null -w "frontend: %{http_code}\n" http://127.0.0.1:8080/ curl -s -o /dev/null -w "backend: %{http_code}\n" http://127.0.0.1:8000/api/v1/meta/choices/ ``` Ожидается `200` (backend в режиме remote с JWT может вернуть `401` без токена — это нормально, главное не `502`). Логи: ```bash docker logs sg_frontend --tail 50 docker logs sg_backend --tail 50 ``` > **Конфликт с dev:** если в том же каталоге запускали `docker compose up`, сначала выполните `docker compose down`. --- ## 5. Прокси на хосте Контейнеры слушают только `127.0.0.1`. Наружу открывается прокси. ### Apache2 ```bash sudo apt install apache2 sudo a2enmod proxy proxy_http headers rewrite sudo cp deploy/apache/social-graph.conf /etc/apache2/sites-available/social-graph.conf sudo nano /etc/apache2/sites-available/social-graph.conf ``` Измените `ServerName` / `ServerAlias` на ваш домен. **При `VITE_DATA_MODE=remote`** раскомментируйте блок API **выше** блока frontend: ```apache ProxyPass /api http://127.0.0.1:8000/api ProxyPassReverse /api http://127.0.0.1:8000/api ``` Включите сайт: ```bash sudo a2ensite social-graph.conf sudo a2dissite 000-default.conf # опционально sudo apache2ctl configtest sudo systemctl reload apache2 ``` HTTPS: ```bash sudo apt install certbot python3-certbot-apache sudo certbot --apache -d your-domain.com -d www.your-domain.com ``` ### nginx на хосте ```bash sudo apt install nginx sudo cp deploy/proxy/nginx-host.conf.example /etc/nginx/sites-available/social-graph sudo nano /etc/nginx/sites-available/social-graph ``` Укажите `server_name` и при remote-режиме раскомментируйте `location /api/`. ```bash sudo ln -s /etc/nginx/sites-available/social-graph /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx ``` HTTPS: ```bash sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d your-domain.com -d www.your-domain.com ``` --- ## 6. Первый вход (режим remote) 1. Откройте `https://your-domain.com` 2. Перейдите на **Регистрация** (`/register`) и создайте аккаунт 3. Либо войдите под существующим пользователем Если на сервере уже есть данные от пользователя `legacy` (миграция), задайте ему пароль: ```bash docker compose -f docker-compose.prod.yml --profile with-backend exec backend python manage.py shell ``` ```python from django.contrib.auth import get_user_model User = get_user_model() u = User.objects.get(username='legacy') u.set_password('ваш-пароль') u.save() exit() ``` --- ## 7. Обновление версии ```bash cd /opt/social-graph git pull docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend # при remote: docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod --profile with-backend up -d --build backend sudo systemctl reload apache2 # или: sudo nginx -s reload ``` При изменении `VITE_DATA_MODE` нужна **пересборка** frontend (`--build`). --- ## 8. Резервное копирование (remote) База — SQLite в Docker volume `sqlite_data`. ```bash docker compose -f docker-compose.prod.yml --profile with-backend exec backend \ python manage.py dumpdata contacts --indent 2 > backup-contacts-$(date +%F).json ``` Полный дамп через UI: **Импорт** → экспорт бэкапа (если включён в интерфейсе). Копия файла БД (осторожно — только при остановленном backend): ```bash docker compose -f docker-compose.prod.yml --profile with-backend stop backend docker run --rm -v social-graph_sqlite_data:/data -v "$PWD":/backup alpine \ cp /data/db.sqlite3 /backup/db.sqlite3-$(date +%F) docker compose -f docker-compose.prod.yml --profile with-backend start backend ``` --- ## 9. Порты и безопасность | Переменная | По умолчанию | Назначение | |------------|--------------|------------| | `FRONTEND_PORT` | 8080 | nginx в контейнере | | `BACKEND_PORT` | 8000 | gunicorn | | `FRONTEND_BIND` | 127.0.0.1 | только localhost | Рекомендуется: ```bash sudo ufw allow OpenSSH sudo ufw allow 'Apache Full' # или 'Nginx Full' sudo ufw enable ``` Порты 8080 и 8000 **не** открывать наружу — только через прокси. --- ## 10. Устранение неполадок | Симптом | Что проверить | |---------|----------------| | 502 Bad Gateway | Контейнеры запущены? `docker ps`, логи `sg_frontend` / `sg_backend` | | Белая страница после деплоя | Пересобран frontend? `VITE_DATA_MODE` совпадает с ожиданиями | | API не отвечает в remote | Раскомментирован `ProxyPass /api` в Apache/nginx; backend в profile `with-backend` | | «Сессия истекла» / 401 | `USE_JWT_AUTH=true` на backend; перелогин | | Данные не общие между ПК | Нужен `VITE_DATA_MODE=remote`, не `local` | Полезные команды: ```bash docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod ps docker logs sg_frontend --tail 100 docker logs sg_backend --tail 100 docker compose -f docker-compose.prod.yml --profile with-backend exec backend python manage.py migrate ``` --- ## 11. Краткая шпаргалка **Local (только UI):** ```bash cd /opt/social-graph cp deploy/.env.prod.example deploy/.env.prod # VITE_DATA_MODE=local docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend # настроить Apache/nginx → 127.0.0.1:8080 ``` **Remote (серверная БД + авторизация):** ```bash cd /opt/social-graph cp deploy/.env.prod.example deploy/.env.prod # VITE_DATA_MODE=remote, DJANGO_SECRET_KEY, ALLOWED_HOSTS, USE_JWT_AUTH=true docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod build docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod --profile with-backend up -d --build backend # прокси: / → :8080, /api → :8000 ``` Дополнительно: [README.md](../README.md), разработка — `docker compose up --build` (порты 5173 и 8000).