API аккаунтов на чистой стандартной библиотеке Python (server/splitapi): - регистрация по почте: пароль задаётся по ссылке из письма, аккаунт создаётся только после подтверждения - вход, выход, сброс пароля по почте (токены одноразовые, в базе только SHA-256), удаление аккаунта - пароли scrypt, лимиты попыток по паре «адрес + IP», IP и аккаунту, защита от CSRF - хранение прогресса пользователя с оптимистичной блокировкой версии - SMTP через переменные окружения; без SMTP на публичном адресе API не стартует Клиент: public/auth.js (вход, регистрация, сброс, синхронизация), public/sync.js (чистое слияние прогресса). Без API сайт работает как раньше. Развёртывание: Dockerfile.api, сервис splitapi в docker-compose, проксирование /api/ в nginx с ограничением частоты, deploy/install-api-debian.sh (systemd), .env.example. Тесты: 216 для бэкенда (unittest, покрытие около 97%), 16 для клиентского слияния. Документация: раздел «Аккаунты и почта» в docs/DEPLOY.md, раздел 9 в docs/ИНСТРУКЦИЯ.md.
69 lines
2.6 KiB
YAML
69 lines
2.6 KiB
YAML
# Запуск: docker compose up -d --build
|
|
# Сайт по умолчанию открыт только на localhost: он предназначен для работы за обратным прокси.
|
|
# BIND=0.0.0.0 откроет его наружу, PORT=9000 сменит порт. Все переменные можно положить в файл .env рядом (образец: .env.example).
|
|
services:
|
|
split-trainer:
|
|
build: .
|
|
image: split-trainer:latest
|
|
container_name: split-trainer
|
|
restart: unless-stopped
|
|
ports:
|
|
- "${BIND:-127.0.0.1}:${PORT:-8080}:8080"
|
|
read_only: true
|
|
tmpfs:
|
|
- /tmp
|
|
cap_drop:
|
|
- ALL
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
mem_limit: 64m
|
|
pids_limit: 64
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "5m"
|
|
max-file: "3"
|
|
|
|
# API аккаунтов. Порт наружу не публикуется: к нему ходит только nginx из контейнера выше по имени splitapi.
|
|
# Если API не нужен, сайт работает и без него (просто без входа): уберите этот сервис.
|
|
splitapi:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile.api
|
|
image: split-trainer-api:latest
|
|
container_name: splitapi
|
|
restart: unless-stopped
|
|
environment:
|
|
# Должен совпадать с адресом, по которому открывают сайт (схема, домен, порт): из него строятся ссылки в письмах и проверяется Origin
|
|
PUBLIC_URL: ${PUBLIC_URL:-http://127.0.0.1:${PORT:-8080}}
|
|
# Верим X-Real-IP, потому что порт API не публикуется и до него доходит только nginx. Не публикуйте порт 8000.
|
|
TRUST_PROXY: "1"
|
|
MAIL_BACKEND: ${MAIL_BACKEND:-}
|
|
MAIL_FROM: ${MAIL_FROM:-}
|
|
SMTP_HOST: ${SMTP_HOST:-}
|
|
SMTP_PORT: ${SMTP_PORT:-}
|
|
SMTP_SECURITY: ${SMTP_SECURITY:-}
|
|
SMTP_USER: ${SMTP_USER:-}
|
|
SMTP_PASSWORD: ${SMTP_PASSWORD:-}
|
|
ALLOW_REGISTRATION: ${ALLOW_REGISTRATION:-true}
|
|
SESSION_DAYS: ${SESSION_DAYS:-}
|
|
volumes:
|
|
- splitapi-data:/data
|
|
read_only: true
|
|
tmpfs:
|
|
- /tmp
|
|
cap_drop:
|
|
- ALL
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
mem_limit: 384m # scrypt занимает десятки МБ на каждый одновременный вход
|
|
pids_limit: 64
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "5m"
|
|
max-file: "3"
|
|
|
|
volumes:
|
|
splitapi-data:
|