Files
WhatIDo/.env.example
T
dev 104bdc4f49 feat(uploads): лимиты загрузки в env, 50 МБ на файл и 200 МБ на запись
Лимиты были захардкожены в четырёх местах фронтенда и в константах multer,
из-за чего расходились с текстами ошибок на сервере.

- UPLOAD_FILE_LIMIT_MB (50) и UPLOAD_TOTAL_LIMIT_MB (200) читаются из env;
  оба multer-конфига (upload, adminUpload) берут fileSize из них, тексты
  ошибок собираются из тех же констант вместо литералов
- UPLOAD_REQUEST_TIMEOUT_MS снимает дефолт Node в 5 минут: считается как
  UPLOAD_TOTAL_LIMIT_MB * 7500, иначе 200 МБ по мобильной сети не успевают
- GET /api/public-settings отдаёт upload_file_limit_mb / upload_total_limit_mb,
  фронтенд читает их вместо собственных констант

Проверено на живом стеке: 20 МБ и 180 МБ суммарно принимаются, 55 МБ и
225 МБ отклоняются с верными сообщениями, скачивание 45 МБ из S3 совпадает
по sha256 с оригиналом, api.smoketest.js — 57 PASS / 0 FAIL.
2026-10-03 10:38:36 +03:00

110 lines
8.4 KiB
Bash
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.
ADMIN_USERNAME=admin
ADMIN_PASSWORD=сложный-пароль-админки
DB_PASSWORD=случайная-длинная-строка
# Лимит размера загружаемого на восстановление бэкапа, МБ (по умолчанию 500)
BACKUP_UPLOAD_LIMIT_MB=500
# === Лимиты загрузки файлов ===
# Максимальный размер одного файла, МБ (по умолчанию 50). Применяется ко всем
# загрузкам: файлы проекта и фото учеников, фото групп и учеников, логотип,
# фото модулей. Нельзя делать меньше UPLOAD_TOTAL_LIMIT_MB.
UPLOAD_FILE_LIMIT_MB=50
# Максимальный суммарный размер вложений одной записи, МБ (по умолчанию 200).
UPLOAD_TOTAL_LIMIT_MB=200
# Таймаут приёма запроса, мс. Пусто — считается автоматически
# (UPLOAD_TOTAL_LIMIT_MB * 7500, минимум 5 минут). Увеличьте, если ученики
# жалуются на обрыв загрузки на медленной мобильной связи.
UPLOAD_REQUEST_TIMEOUT_MS=
# === Redis (кэш, rate limit, баны IP, pub/sub) ===
# Пароль Redis. Обязателен, если Redis включён в docker-compose.
REDIS_PASSWORD=замените-на-длинный-секрет
# Префикс ключей — позволяет держать несколько инстансов в одном Redis.
REDIS_PREFIX=whatido
# Лимит памяти Redis. При превышении вытесняются ключи с наименьшим TTL (allkeys-lru).
REDIS_MAXMEMORY=256mb
# Hugging Face token (нужен для закрытых/приватных репозиториев моделей)
HUGGINGFACE_TOKEN=
# Имя GGUF-файла модели для text-corrector (скачивается с Hugging Face, если отсутствует)
AI_MODEL=qwen2.5-1.5b-instruct-q4_k_m.gguf
# Репозиторий Hugging Face, откуда скачивается модель
AI_MODEL_REPO=Qwen/Qwen2.5-1.5B-Instruct-GGUF
# Промпт по умолчанию для автоисправления текстов (переопределяет встроенный, если в настройках не сохранён свой)
AI_PROMPT=Ты — редактор текстов. Исправь ТОЛЬКО грамматические, орфографические и пунктуационные ошибки в тексте. Приведи к правильному регистру буквы. НЕ меняй слова, структуру предложений, стиль или смысл текста. Верни ТОЛЬКО исправленный текст без пояснений.
# Таймаут запроса к AI (мс), по умолчанию 120000 (2 минуты)
AI_REQUEST_TIMEOUT_MS=120000
# === Cloudflare Tunnel (контейнер cloudflared) ===
# По умолчанию — Quick Tunnel на trycloudflare.com: случайный публичный URL,
# адрес печатается в логах: docker compose logs -f cloudflared.
# Чтобы привязать свой домен, замените command сервиса cloudflared
# в docker-compose.yml на: command: ["tunnel", "run", "--token", "${CLOUDFLARE_TUNNEL_TOKEN}"]
# (токен вида "eyJ..." создаётся в Cloudflare Zero Trust -> Networks -> Tunnels).
CLOUDFLARE_TUNNEL_TOKEN=
# Внутренний адрес приложения, на который указывает Quick Tunnel.
CLOUDFLARE_TUNNEL_URL=http://app:3003
# Максимальное ожидание WireGuard handshake перед fallback на прямой запуск
# туннеля без VPN (сек). Если VPN-провайдер не отвечает — сайт всё равно поднимется.
WG_HANDSHAKE_TIMEOUT=60
# === ИИ-улучшение фото (контейнер photo-ai, Real-ESRGAN + GFPGAN) ===
# По умолчанию фото-ИИ включено: сервис photo-ai поднимается вместе со стеком
# и работает на CPU. Оставьте значение пустым, чтобы выключить сервис —
# тогда кнопка «🤖 ИИ» скрыта, а /api/entries/:id/photo/enhance-ai отвечает 503.
# Ручные проверки сервиса идут по loopback-порту 127.0.0.1:8081 (наружу не публикуется):
# curl http://127.0.0.1:8081/health
PHOTO_AI_URL=http://photo-ai:8080
# Максимум пикселей входного изображения, более крупный вход уменьшается.
PHOTO_AI_MAX_PIXELS=4000000
# Устройство инференса: auto (CUDA, если контейнеру выдан GPU, иначе CPU), cuda, cpu.
# Явный cuda без доступной CUDA не роняет сервис: WARN в лог и работа на CPU.
# GPU-вариант собирается оверрайдом (отдельный образ whatido-photo-ai:cu126, GPU через CDI):
# docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d --build photo-ai
# Подробности установки NVIDIA Container Toolkit — в README, раздел «Запуск на NVIDIA GPU».
PHOTO_AI_DEVICE=auto
# Размер тайла инференса (0 — без тайлов). Меньше тайл — меньше памяти, медленнее.
# На GPU с 4 ГБ VRAM держите 256: при нехватке сервис сам пройдёт лестницу тайлов и уйдёт на CPU.
PHOTO_AI_TILE=256
# Модель восстановления лиц: gfpgan (по умолчанию) или codeformer.
# codeformer доступен только если модуль вендорен в photo-ai/vendor.
PHOTO_AI_FACE_MODEL=gfpgan
# Предзагрузка всех моделей при старте (1) или ленивая загрузка по требованию (0).
PHOTO_AI_LOAD_ALL=0
# Качество JPEG результата (70..100).
PHOTO_AI_JPEG_QUALITY=92
# Таймаут заданий с восстановлением лиц на стороне приложения (мс).
PHOTO_AI_FACE_TIMEOUT_MS=600000
# Сколько раз воркер повторит задание, если photo-ai недоступен (503/обрыв сети),
# не увеличивая attempts; после исчерпания — одна честная ошибка в задании.
PHOTO_AI_SOFT_MAX_RETRIES=60
# Пауза перед мягким повтором и её потолок (мс), задержка растёт вдвое до потолка.
PHOTO_AI_SOFT_BACKOFF_MS=10000
PHOTO_AI_SOFT_BACKOFF_MAX_MS=300000
# === Хранилище файлов (S3: SeaweedFS по умолчанию / MinIO) ===
# local — файлы в ./uploads (по умолчанию), s3 — объекты в бакете S3/MinIO.
STORAGE_DRIVER=local
# Читать локальную копию, если объект ещё не перенесён в S3 (1 — включено).
STORAGE_LOCAL_FALLBACK=1
# Оставлять локальную копию после выгрузки в S3 (1 — оставлять, 0 — удалять).
STORAGE_KEEP_LOCAL=0
# Сколько часов хранить локальный кэш оригиналов (для sharp/миниатюр), 0 — не чистить.
STORAGE_CACHE_MAX_AGE_HOURS=168
# Образ S3-сервиса. По умолчанию SeaweedFS (свободный S3-сервер).
# Для MinIO: S3_IMAGE=minio/minio:<тег> и запуск через docker-compose.minio.yml.
S3_IMAGE=chrislusf/seaweedfs:latest
S3_ENDPOINT=http://s3:9000
S3_REGION=us-east-1
S3_BUCKET=whatido
# Логин/пароль S3 (для SeaweedFS — AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY,
# для MinIO — MINIO_ROOT_USER/MINIO_ROOT_PASSWORD).
S3_ACCESS_KEY=whatido
S3_SECRET_KEY=замените-на-длинный-секрет
# Path-style адресация (1 — включено, нужно для MinIO и SeaweedFS).
S3_FORCE_PATH_STYLE=1
# Необязательный префикс ключей внутри бакета (например, prod).
S3_PREFIX=
# Показывать веб-консоль MinIO (on/off), только для docker-compose.minio.yml
MINIO_BROWSER=off