360 lines
10 KiB
Markdown
360 lines
10 KiB
Markdown
# Развёртывание Social Graph на [social.deepfishing.ru](https://social.deepfishing.ru)
|
||
|
||
Инструкция для production-сервера **social.deepfishing.ru**. Приложение публикуется через Docker; снаружи доступен только веб-прокси (80/443).
|
||
|
||
**Адрес приложения:** https://social.deepfishing.ru
|
||
|
||
---
|
||
|
||
## Схема
|
||
|
||
```text
|
||
https://social.deepfishing.ru (: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 на сервере | обязателен |
|
||
|
||
Для **social.deepfishing.ru** рекомендуется **remote** + `USE_JWT_AUTH=true` (регистрация, вход, общая база).
|
||
|
||
---
|
||
|
||
## 1. Требования
|
||
|
||
- Linux (Ubuntu 22.04+ / Debian 12+)
|
||
- Docker Engine + Docker Compose
|
||
- Git
|
||
- DNS: запись **A** (или **AAAA**) `social.deepfishing.ru` → IP сервера
|
||
- Apache2 **или** nginx на хосте
|
||
|
||
Установка Docker:
|
||
|
||
```bash
|
||
curl -fsSL https://get.docker.com | sh
|
||
sudo usermod -aG docker "$USER"
|
||
# перелогиньтесь
|
||
docker compose version
|
||
```
|
||
|
||
---
|
||
|
||
## 2. Клонирование
|
||
|
||
```bash
|
||
sudo mkdir -p /opt/social-graph
|
||
sudo chown "$USER:$USER" /opt/social-graph
|
||
git clone <URL-репозитория> /opt/social-graph
|
||
cd /opt/social-graph
|
||
git checkout main
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Конфигурация `deploy/.env.prod`
|
||
|
||
```bash
|
||
cd /opt/social-graph
|
||
cp deploy/.env.prod.example deploy/.env.prod
|
||
nano deploy/.env.prod
|
||
```
|
||
|
||
### Рекомендуемый конфиг для social.deepfishing.ru (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=social.deepfishing.ru
|
||
USE_JWT_AUTH=true
|
||
```
|
||
|
||
Сгенерировать `DJANGO_SECRET_KEY`:
|
||
|
||
```bash
|
||
python3 -c "import secrets; print(secrets.token_urlsafe(50))"
|
||
```
|
||
|
||
### Альтернатива — только UI (local)
|
||
|
||
Если backend не нужен, данные останутся в браузере каждого пользователя:
|
||
|
||
```env
|
||
VITE_DATA_MODE=local
|
||
FRONTEND_BIND=127.0.0.1
|
||
FRONTEND_PORT=8080
|
||
```
|
||
|
||
Файл `deploy/.env.prod` **не коммитить**.
|
||
|
||
---
|
||
|
||
## 4. Запуск контейнеров
|
||
|
||
```bash
|
||
cd /opt/social-graph
|
||
```
|
||
|
||
### Remote (frontend + backend)
|
||
|
||
```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
|
||
```
|
||
|
||
### Только frontend (local)
|
||
|
||
```bash
|
||
docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend
|
||
```
|
||
|
||
### Проверка на сервере
|
||
|
||
```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/
|
||
curl -s -o /dev/null -w "public: %{http_code}\n" https://social.deepfishing.ru/
|
||
```
|
||
|
||
Логи:
|
||
|
||
```bash
|
||
docker logs sg_frontend --tail 50
|
||
docker logs sg_backend --tail 50
|
||
```
|
||
|
||
> Перед prod-запуском остановите dev-контейнеры: `docker compose down`
|
||
|
||
---
|
||
|
||
## 5. Прокси на хосте
|
||
|
||
Контейнеры слушают **только** `127.0.0.1`. Снаружи — прокси на 80/443.
|
||
|
||
### Apache2
|
||
|
||
```bash
|
||
sudo apt install apache2
|
||
sudo a2enmod proxy proxy_http headers rewrite ssl
|
||
sudo cp deploy/apache/social-graph.conf /etc/apache2/sites-available/social-graph.conf
|
||
sudo nano /etc/apache2/sites-available/social-graph.conf
|
||
```
|
||
|
||
Пример VirtualHost:
|
||
|
||
```apache
|
||
<VirtualHost *:80>
|
||
ServerName social.deepfishing.ru
|
||
|
||
ProxyPreserveHost On
|
||
RequestHeader set X-Forwarded-Proto "https"
|
||
RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
|
||
|
||
# API (режим remote)
|
||
ProxyPass /api http://127.0.0.1:8000/api
|
||
ProxyPassReverse /api http://127.0.0.1:8000/api
|
||
|
||
# Frontend SPA
|
||
ProxyPass / http://127.0.0.1:8080/
|
||
ProxyPassReverse / http://127.0.0.1:8080/
|
||
|
||
ErrorLog ${APACHE_LOG_DIR}/social-graph-error.log
|
||
CustomLog ${APACHE_LOG_DIR}/social-graph-access.log combined
|
||
</VirtualHost>
|
||
```
|
||
|
||
```bash
|
||
sudo a2ensite social-graph.conf
|
||
sudo a2dissite 000-default.conf
|
||
sudo apache2ctl configtest
|
||
sudo systemctl reload apache2
|
||
```
|
||
|
||
HTTPS (Let's Encrypt):
|
||
|
||
```bash
|
||
sudo apt install certbot python3-certbot-apache
|
||
sudo certbot --apache -d social.deepfishing.ru
|
||
```
|
||
|
||
После certbot сайт будет доступен по https://social.deepfishing.ru .
|
||
|
||
### nginx на хосте
|
||
|
||
```bash
|
||
sudo apt install nginx
|
||
sudo nano /etc/nginx/sites-available/social-graph
|
||
```
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name social.deepfishing.ru;
|
||
|
||
location /api/ {
|
||
proxy_pass http://127.0.0.1:8000/api/;
|
||
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://127.0.0.1:8080;
|
||
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;
|
||
}
|
||
}
|
||
```
|
||
|
||
```bash
|
||
sudo ln -s /etc/nginx/sites-available/social-graph /etc/nginx/sites-enabled/
|
||
sudo nginx -t
|
||
sudo systemctl reload nginx
|
||
sudo certbot --nginx -d social.deepfishing.ru
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Первый вход
|
||
|
||
1. Откройте https://social.deepfishing.ru
|
||
2. **Регистрация:** https://social.deepfishing.ru/register
|
||
3. Или **вход:** https://social.deepfishing.ru/login
|
||
|
||
Если на сервере есть пользователь `legacy` (данные после миграции), задайте пароль:
|
||
|
||
```bash
|
||
cd /opt/social-graph
|
||
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()
|
||
```
|
||
|
||
Вход: https://social.deepfishing.ru/login → логин `legacy`.
|
||
|
||
---
|
||
|
||
## 7. Обновление
|
||
|
||
```bash
|
||
cd /opt/social-graph
|
||
git pull
|
||
|
||
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
|
||
|
||
sudo systemctl reload apache2 # или: sudo nginx -s reload
|
||
```
|
||
|
||
Проверка: https://social.deepfishing.ru
|
||
|
||
---
|
||
|
||
## 8. Резервное копирование
|
||
|
||
```bash
|
||
cd /opt/social-graph
|
||
docker compose -f docker-compose.prod.yml --profile with-backend exec backend \
|
||
python manage.py dumpdata contacts --indent 2 \
|
||
> backup-social-deepfishing-$(date +%F).json
|
||
```
|
||
|
||
Копия SQLite (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-social-deepfishing-$(date +%F).sqlite3
|
||
docker compose -f docker-compose.prod.yml --profile with-backend start backend
|
||
```
|
||
|
||
---
|
||
|
||
## 9. Безопасность
|
||
|
||
```bash
|
||
sudo ufw allow OpenSSH
|
||
sudo ufw allow 'Apache Full' # или 'Nginx Full'
|
||
sudo ufw enable
|
||
```
|
||
|
||
| Порт | Доступ |
|
||
|------|--------|
|
||
| 443, 80 | открыт (прокси) |
|
||
| 8080, 8000 | только 127.0.0.1 |
|
||
|
||
---
|
||
|
||
## 10. Устранение неполадок
|
||
|
||
| Симптом | Решение |
|
||
|---------|---------|
|
||
| 502 на https://social.deepfishing.ru | `docker ps`, логи `sg_frontend` / `sg_backend` |
|
||
| Страница открывается, API 404 | В прокси включён `ProxyPass /api` → `:8000` |
|
||
| 401 / не пускает | `USE_JWT_AUTH=true` в `.env.prod`, пересобрать backend |
|
||
| Данные не сохраняются между устройствами | `VITE_DATA_MODE=remote`, пересобрать frontend |
|
||
| Белый экран | `docker logs sg_frontend`, пересборка с `--build` |
|
||
|
||
```bash
|
||
cd /opt/social-graph
|
||
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. Шпаргалка (social.deepfishing.ru, remote)
|
||
|
||
```bash
|
||
cd /opt/social-graph
|
||
cp deploy/.env.prod.example deploy/.env.prod
|
||
# ALLOWED_HOSTS=social.deepfishing.ru
|
||
# VITE_DATA_MODE=remote
|
||
# USE_JWT_AUTH=true
|
||
# DJANGO_SECRET_KEY=...
|
||
|
||
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
|
||
|
||
# Apache: ServerName social.deepfishing.ru
|
||
# ProxyPass /api → 127.0.0.1:8000
|
||
# ProxyPass / → 127.0.0.1:8080
|
||
# certbot --apache -d social.deepfishing.ru
|
||
```
|
||
|
||
**Проверка:** https://social.deepfishing.ru
|