Конфігурація
Бекенд налаштовується лише через змінні оточення. Значення за замовчуванням і правила обов'язковості нижче взято з коду конфігураційних модулів, а не з .env.example.
Як завантажується конфігурація
.envчитаєdotenvчерезimport "dotenv/config". Цей рядок стоїть першим у точці входуsrc/index.ts, уsrc/sentry-bootstrap.ts, у скриптахsrc/db/create-database.ts,src/db/seed.tsтаsrc/scripts/send-test-email.ts. Файл шукається в поточній робочій директорії процесу, тобто зазвичай цеpackages/backend/.env.- Кожен файл у
src/config/один раз читаєenvзnode:processпід час імпорту й повертаєObject.freeze(...). Якщо змінити змінну після старту, процес її не побачить. - PostgreSQL-налаштування збирає одна функція
resolveDatabaseConfig()уsrc/config/database.ts. Її використовують застосунок,db:create(create-database.ts) іdrizzle.config.ts, тож defaults однакові всюди.drizzle.config.tsне імпортуєdotenv. - Булеві та цілі значення розбирає одна пара функцій,
parseBooleanіparseInteger, черезcreateEnvReader. Правила — у розділі Булеві та цілі значення. - Після імпорту конфігурацій
src/index.tsвикликаєvalidateRuntimeConfig(). Вона кидає помилку й зупиняє старт, якщо комбінація змінних неприпустима. Нижче ці перевірки позначено як «throw на старті».
Булеві та цілі значення
Усі булеві та цілі змінні .env читає той самий код (env-reader.ts). Він збирає всі знайдені проблеми одного модуля й повідомляє їх разом через validateRuntimeConfig() (Invalid <область> configuration: ...), з назвою змінної.
| Тип | Приймається | Порожньо / не задано | Інше значення |
|---|---|---|---|
| boolean | true, 1, yes, on → true; false, 0, no, off → false. Регістр і пробіли по краях неважливі | default змінної | помилка старту (не «false») |
| integer | десяткові цифри, без знака, у межах змінної {min, max} (включно), безпечне ціле | default змінної | помилка старту (1e3, 0x10, -5, 1.5, 5ms) |
Це змінило поведінку порівняно з окремими парсерами, які були раніше: AUTH_PHONE_ENABLED=yes тепер true (раніше auth.ts знав лише 1/true); True та TRUE тепер true скрізь (раніше parseBoolean був чутливий до регістру, і APP_IS_PRODUCTION=True давав false); одруківка в булевій змінній (CSRF_ENFORCE=flase) більше не тихо дає false, а зупиняє старт; AUTH_*=1e3 і PORT=abc більше не приймаються і не підміняються default-ом (раніше PORT, SMTP_PORT мовчки поверталися до 3000/587); порожнє значення в змінних rate limit більше не помилка, а default. Прості строкові змінні, розміри в байтах (APP_MAX_BODY_SIZE, ...), тривалості (SESSION_ANON_TTL) і частки (SENTRY_TRACES_SAMPLE_RATE) мають власні правила, описані біля змінних.
Production-like режим
appConfig.isProductionLike дорівнює APP_IS_PRODUCTION, якщо змінну задано. Інакше він дорівнює true, коли APP_ENV (або NODE_ENV, якщо APP_ENV відсутня) після trim().toLowerCase() має значення production або prod. Від цього режиму залежить таке:
SESSION_COOKIE_HOST_PREFIXза замовчуванням вмикається, і cookie сесії отримує назву__Host-uapi. ТодіAPP_URLмає починатися зhttps://, інакше на старті буде throw.AUTH_SMS_PROVIDER=fakeзаборонено: на старті буде throw.
Окремо від isProductionLike, APP_ENV впливає на інші місця напряму:
secureу cookie (cookies.ts,session.ts) дорівнюєAPP_ENV !== 'local'.- CSP
connect-srcуcsp.tsне пропускаєws:таhttp:, колиAPP_ENVдорівнюєproductionабоprod. Тут порівняння точне, без нормалізації.
Застосунок і сервер
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
APP_NAME | Назва застосунку | uwebsockets-api | Ні | app.ts |
APP_KEY | Секрет застосунку; запасний ключ для хешування OTP | немає (undefined) | Так, якщо AUTH_PHONE_ENABLED=true і немає AUTH_OTP_HMAC_KEY: потрібно ≥ 32 символи, інакше throw на старті | app.ts |
APP_ENV | Назва оточення: production-like режим, secure у cookie, CSP, default для Sentry environment | немає | Ні, але без неї cookie мають secure: true, бо undefined !== 'local' | app.ts, cookies.ts, session.ts, csp.ts |
NODE_ENV | Запасне джерело назви оточення, коли APP_ENV не задано | немає | Ні | app.ts |
APP_IS_PRODUCTION | Явно вмикає або вимикає production-like режим | виводиться з APP_ENV/NODE_ENV | Ні | app.ts |
APP_URL | Публічний URL бекенда (кінцевий / обрізається) | "" | Так, якщо SESSION_COOKIE_HOST_PREFIX увімкнено: має бути https://, інакше throw | app.ts |
FRONTEND_URL | URL фронтенда для посилань у листах | значення APP_URL | Ні | app.ts |
LANDING_URL | URL лендингу | "" | Ні | app.ts |
DOMAIN | Хост (і порт, якщо не 80/443) для wsUrl: фронтенд підключається до ws(s)://<DOMAIN>/<API_PATH_PREFIX>/websocket (get-ws-url-service.ts). Локально — 127.0.0.1:3000 | 127.0.0.1 | Ні | app.ts |
HOST | Адреса, на якій слухає сервер | 0.0.0.0 | Ні | app.ts |
PORT | TCP-порт | 3000 (так само для значень поза 1–65535) | Ні | app.ts |
APP_UNIX_PATH | Шлях до Unix-сокета замість TCP. Порожнє значення (APP_UNIX_PATH=) означає «не задано» | немає | Ні | app.ts |
SERVE_STATIC | Роздавати статичні файли з бекенда | false | Ні | app.ts |
STATIC_MAX_MEMORY_FILE_SIZE | Найбільший файл статики в RAM, байти; більші віддаються стрімінгом з диска | 1048576 | Ні | app.ts |
STATIC_MAX_MEMORY_TOTAL | Бюджет RAM для статики разом зі стислими варіантами, байти | 67108864 | Ні | app.ts |
DOC_PAGE | Вмикає GET /<prefix>/doc/routes (лише разом з APP_ENV=manual-test і SERVE_STATIC=true, див. маршрутизацію) | false | Ні | app.ts |
Маршрутизація і CDN
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
API_PATH_PREFIX | Префікс HTTP-маршрутів (крайні / прибираються) | api | Ні | app.ts |
CDN_URL | Базовий URL CDN | "" | Ні | app.ts |
Ліміти тіла запиту
Значення задаються в байтах: лише додатне безпечне ціле число, записане цифрами (пробіли навколо допускаються). Будь-що інше — abc, 0, -1, 1.5, 1e6, 0x10, Infinity, число понад Number.MAX_SAFE_INTEGER — замінюється на default. Ліміт за типом тіла описано в Життєвому циклі запиту.
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
APP_MAX_BODY_SIZE | Загальний ліміт тіла | 2097152 (2 MiB) | Ні | app.ts |
APP_MAX_JSON_BODY_SIZE | Ліміт для JSON | 2097152 (2 MiB) | Ні | app.ts |
APP_MAX_MULTIPART_BODY_SIZE | Ліміт для multipart | 52428800 (50 MiB) | Ні | app.ts |
APP_MAX_OCTET_BODY_SIZE | Ліміт для application/octet-stream | 52428800 (50 MiB) | Ні | app.ts |
Чому такі defaults:
- 2 MiB для JSON і решти типів. Реальні JSON-тіла значно менші, а зниження до 1 MiB змінило б поведінку без вигоди.
- 50 MiB для multipart — політика сумісності. Фактична потреба менша: файлові ліміти сервісів — 10 MB для аватара (
avatar-service.ts) і 5 MB для скриншота бази знань (knowledge-base-service.ts), плюс невелика multipart-обгортка. Тож ліміт тіла можна знизити, не зачепивши наявні маршрути. - 50 MiB для octet.
octet-маршрутів у шаблоні немає.
Під час розгортання:
- Проксі. Ліміт проксі перед backend (
client_max_body_sizeу nginx, ліміти CDN) має бути не меншим за потрібний ліміт тіла, інакше великі запити відріже проксі зі своєю відповіддю, а не backend з 413. - Пам'ять. Тіло збирається в пам'яті. Приблизна оцінка самих буферів тіла:
≈ кількість одночасних запитів × maxMultipartBodySize × 2. Це не верхня межа пам'яті процесу: парсери ще створюють рядки, об'єкти й копії даних. Для аварійного зниження єAPP_MAX_MULTIPART_BODY_SIZE.
Безпека: CORS, CSRF, проксі, CSP
Докладніше про ці механізми див. на сторінці Безпека.
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
ENABLED_CORS | Вмикає обробку CORS | false | Ні | cors.ts |
CORS_ALLOWED_ORIGINS | Whitelist origin через кому, без wildcard | [] | Ні, але з порожнім списком жоден cross-origin запит не пройде | cors.ts |
CREDENTIONALS_CORS | Access-Control-Allow-Credentials (назва змінної саме з такою орфографією) | false | Ні | cors.ts |
CSRF_ENFORCE | Відхиляти CSRF-порушення з 403; false — лише логувати | true | Ні | csrf.ts |
CSRF_STRICT_ORIGIN | Відхиляти небезпечні запити без Origin і Referer | true | Ні | csrf.ts |
CSRF_ALLOWED_ORIGINS | Точні origin для CSRF через кому (без шляху і / в кінці) | [] | Так у production-like; інакше fallback на APP_URL/FRONTEND_URL | csrf.ts |
TRUST_PROXY | Довіряти заголовкам проксі для визначення IP | false | Ні | network.ts |
TRUSTED_PROXY_CIDRS | CIDR довірених проксі через кому | [] | Ні | network.ts |
CSP_ENABLED | Вмикає глобальну Content-Security-Policy | true | Ні | csp.ts |
CSP_REPORT_ONLY | Надсилати всі глобальні політики як -Report-Only | false | Ні | csp.ts |
CSP_REPORT_URI | Абсолютний http(s) URL отримувача звітів (шлях дозволено) | "" | Ні | csp.ts |
CSP_API_ORIGIN | Origin HTTP API для connect-src (= VITE_BASE_URL) | origin APP_URL | Ні, якщо API на тому ж origin, що й APP_URL | csp.ts |
CSP_WS_ORIGIN | Origin WebSocket (ws:/wss:) | origin getWsUrl() | Ні, але потрібен за проксі з іншим WS-доменом | csp.ts |
CSP_SENTRY_ORIGIN | Origin Sentry ingest для connect-src | "" | Так, якщо фронтенд шле події в Sentry | csp.ts |
CSP_EXTRA_CONNECT_SRC | Додаткові origins для connect-src через кому (http(s)/ws(s)) | "" | Ні | csp.ts |
CSP_EXTRA_IMG_SRC | Додаткові origins для img-src через кому (http(s)) | "" | Ні | csp.ts |
Rate limit
Значення читаються за контрактом цілих: дробові, від'ємні, 1e3, Infinity, NaN і нечислові значення валять старт (Invalid rate limit configuration), порожнє значення дає default. Деталі в розділі Обмеження частоти запитів.
| Змінна | Призначення | Default | Обов'язковість | Джерело |
|---|---|---|---|---|
HTTP_GLOBAL_RATE_LIMIT_MAX | L1: максимум API-запитів з одного IP за вікно; 0 вимикає | 600 | Ні | rate-limit.ts |
HTTP_GLOBAL_RATE_LIMIT_WINDOW_MS | Вікно L1 (fixed window), мс, ціле > 0 | 60000 | Ні | rate-limit.ts |
WS_UPGRADE_RATE_LIMIT_MAX | Upgrade рівень 1 (пам'ять процесу): максимум з одного IP за вікно; 0 вимикає | 120 | Ні | rate-limit.ts |
WS_UPGRADE_RATE_LIMIT_WINDOW_MS | Вікно upgrade-ліміту (sliding log), мс, ціле > 0 | 60000 | Ні | rate-limit.ts |
WS_UPGRADE_SHARED_RATE_LIMIT_MAX | Upgrade рівень 2 (Redis, спільний): максимум з одного IP за вікно; 0 вимикає рівень 2 | 60 | Ні | throttle-policies.ts |
WS_UPGRADE_SHARED_RATE_LIMIT_WINDOW_MS | Вікно рівня 2 (sliding log), мс, ціле > 0 | 60000 | Ні | throttle-policies.ts |
WS_ADMIN_RECHECK_INTERVAL_MS | Як часто інстанс перечитує з БД роль своїх admin-з'єднань (Відкликання admin-доступу); межа затримки відкликання; цілі мс | 30000 | Ні; не ціле число або поза 100…3600000 — throw на старті | websocket.ts |
SUPPORT_CHAT_USER_RATE_LIMIT_MAX | Повідомлень чату підтримки від одного користувача за вікно (Допуск повідомлення); понад ліміт — відповідь 429 | 20 | Ні; не ціле число або < 1 — помилка конфігурації | throttle-policies.ts |
SUPPORT_CHAT_USER_RATE_LIMIT_WINDOW_MS | Вікно цього ліміту, мс | 60000 | Ні | throttle-policies.ts |
SUPPORT_OPEN_CHAT_USER_RATE_LIMIT_MAX | Відкриттів чату (привітань) від одного користувача за вікно | 5 | Ні | throttle-policies.ts |
SUPPORT_OPEN_CHAT_USER_RATE_LIMIT_WINDOW_MS | Вікно цього ліміту, мс | 60000 | Ні | throttle-policies.ts |
RATE_LIMIT_REDIS_TIMEOUT_MS | Таймаут команди окремого Redis-з'єднання спільних лімітів, мс | 50 | Ні | rate-limit.ts |
Спільні auth-ліміти (Redis)
Читає реєстр throttle-policies.ts. Значення мають бути цілими ≥ 1 (контракт): 0 чи невалідне значення валить старт (Invalid throttle policy configuration), бо захист чутливої дії вимкнути не можна. Повна таблиця політик — у розділі Обмеження частоти запитів.
| Змінна | Призначення | Default |
|---|---|---|
AUTH_LOGIN_MAX_ATTEMPTS_PER_IP | Спроби входу з одного IP за вікно (рахується кожна спроба) | 20 |
AUTH_LOGIN_MAX_ATTEMPTS_PER_IDENTIFIER | Спроби входу на один email/телефон за вікно; скидається після успіху | 40 |
AUTH_LOGIN_WINDOW_SECONDS | Вікно обох login-лімітів, с | 900 |
AUTH_CHANGE_PASSWORD_MAX_ATTEMPTS_PER_USER | Спроби зміни пароля на користувача за вікно; скидається після успіху | 10 |
AUTH_CHANGE_PASSWORD_WINDOW_SECONDS | Вікно ліміту зміни пароля, с | 900 |
AUTH_FORGOT_PASSWORD_MAX_REQUESTS_PER_IP_PER_HOUR | Запити листа скидання пароля з одного IP | 10 |
AUTH_FORGOT_PASSWORD_MAX_REQUESTS_PER_EMAIL_PER_HOUR | Запити листа скидання пароля на один email | 3 |
AUTH_RESEND_VERIFICATION_MAX_PER_USER_PER_HOUR | Повторні листи підтвердження email на користувача | 3 |
AUTH_LOGIN_UNVERIFIED_RESEND_INTERVAL_MS | Інтервал, не частіше за який лист підтвердження надсилається повторно після входу в непідтверджений акаунт (мс) | 300000 |
AUTH_RESET_PASSWORD_MAX_ATTEMPTS_PER_IP_PER_HOUR | Спроби скидання пароля за токеном з одного IP | 20 |
AUTH_VERIFY_EMAIL_MAX_ATTEMPTS_PER_IP_PER_HOUR | Спроби підтвердження email за токеном з одного IP | 20 |
Наявні AUTH_SMS_*, AUTH_EMAIL_REGISTER_* і AUTH_EMAIL_LINK_* (розділ «Автентифікація: email і телефон» нижче) теж потрапляють у реєстр і з тією самою валідацією.
Сесія і cookies
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
SESSION_COOKIE_HOST_PREFIX | Cookie __Host-uapi замість uapi | значення isProductionLike | Ні; якщо увімкнено, cookie має бути secure (APP_ENV ≠ local), а APP_URL має бути https://, інакше throw | session.ts |
SESSION_ANON_TTL | Строк дії анонімної сесії (cookie і запис anon_session у Redis), ковзний; формат metautil duration: 2h, 30m | 2h | Ні; не додатна тривалість — throw на старті | session.ts |
SESSION_TOKEN_CHECK_TIMEOUT_MS | Дедлайн читання users.session_token на кожен автентифікований запит (Відкликання сесій). Це statement_timeout окремого пулу з 5 зʼєднань (сервер скасовує запит) і межа очікування зʼєднання; цей самий пул обмежує періодичну перевірку ролей WS-адмінів (Відкликання admin-доступу); пул додається до основного (10), тож у max_connections має бути запас; цілі мс | 2000 | Ні; не ціле число або поза 1…60000 — throw на старті | session.ts |
Строк життя сесії (24 год), httpOnly, sameSite: 'Lax' і maxAge cookie (3600) задані в коді й через env не змінюються.
Автентифікація: email і телефон
Числові значення розбираються через Number(). Значення, що не є скінченним числом, замінюється на default.
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
AUTH_STRICT_REGISTRATION | Строгий режим реєстрації | true | Ні | auth.ts |
AUTH_PHONE_ENABLED | Вмикає вхід за телефоном | false | Ні | auth.ts |
AUTH_OTP_HMAC_KEY | Ключ HMAC для OTP | немає, fallback на APP_KEY | Так, якщо AUTH_PHONE_ENABLED=true і APP_KEY порожній: потрібно ≥ 32 символи, інакше throw | auth.ts |
AUTH_SMS_PROVIDER | SMS-провайдер | unsupported | Ні; значення fake має додаткові умови (дивіться нижче) | auth.ts |
AUTH_SMS_PROVIDER_ALLOW_FAKE | Дозволяє провайдер fake | false | Так (true), якщо AUTH_SMS_PROVIDER=fake, інакше throw | auth.ts |
AUTH_FAKE_SMS_CODE | Код, який повертає fake-провайдер | 123456 | Так (непорожній), якщо AUTH_SMS_PROVIDER=fake, інакше throw | auth.ts |
AUTH_SMS_CHALLENGE_TTL_SECONDS | Строк дії SMS-челенджу | 600 | Ні | auth.ts |
AUTH_SMS_RESEND_COOLDOWN_SECONDS | Пауза перед повторною відправкою SMS | 60 | Ні | auth.ts |
AUTH_SMS_MAX_INVALID_ATTEMPTS | Ліміт невдалих спроб введення коду | 5 | Ні | auth.ts |
AUTH_SMS_MAX_CONFIRM_ATTEMPTS_PER_IP_PER_HOUR | Ліміт підтверджень з одного IP за годину | 20 | Ні | auth.ts |
AUTH_SMS_MAX_SENDS_PER_PHONE_PER_HOUR | Ліміт SMS на номер за годину | 3 | Ні | auth.ts |
AUTH_SMS_MAX_SENDS_PER_IP_PER_HOUR | Ліміт SMS з одного IP за годину | 10 | Ні | auth.ts |
AUTH_EMAIL_REGISTER_MAX_ATTEMPTS_PER_EMAIL_PER_HOUR | Ліміт реєстрацій на email за годину | 3 | Ні | auth.ts |
AUTH_EMAIL_REGISTER_MAX_ATTEMPTS_PER_IP_PER_HOUR | Ліміт реєстрацій з одного IP за годину | 10 | Ні | auth.ts |
AUTH_EMAIL_LINK_MAX_ATTEMPTS_PER_TARGET_PER_HOUR | Ліміт email-посилань на адресу за годину | 3 | Ні | auth.ts |
AUTH_EMAIL_LINK_MAX_ATTEMPTS_PER_USER_PER_HOUR | Ліміт email-посилань на користувача за годину | 3 | Ні | auth.ts |
AUTH_EMAIL_LINK_COOLDOWN_SECONDS | Пауза між email-посиланнями | 60 | Ні | auth.ts |
Окрім умов у таблиці, AUTH_SMS_PROVIDER=fake у production-like режимі призводить до throw на старті навіть тоді, коли інші умови виконано.
OAuth
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
GOOGLE_CLIENT_ID | Client ID Google | "" | Ні (потрібна для Google OAuth) | oauth.ts |
GOOGLE_CLIENT_SECRET | Client secret Google | "" | Ні (потрібна для Google OAuth) | oauth.ts |
GOOGLE_REDIRECT_URI | Redirect URI Google | "" | Ні (потрібна для Google OAuth) | oauth.ts |
FACEBOOK_CLIENT_ID | Client ID Facebook | "" | Ні (потрібна для Facebook OAuth) | oauth.ts |
FACEBOOK_CLIENT_SECRET | Client secret Facebook | "" | Ні (потрібна для Facebook OAuth) | oauth.ts |
FACEBOOK_REDIRECT_URI | Redirect URI Facebook | "" | Ні (потрібна для Facebook OAuth) | oauth.ts |
GITHUB_CLIENT_ID | Client ID GitHub | "" | Ні (потрібна для GitHub OAuth) | oauth.ts |
GITHUB_CLIENT_SECRET | Client secret GitHub | "" | Ні (потрібна для GitHub OAuth) | oauth.ts |
GITHUB_REDIRECT_URI | Redirect URI GitHub | "" | Ні (потрібна для GitHub OAuth) | oauth.ts |
GITLAB_CLIENT_ID | Client ID GitLab | "" | Ні (потрібна для GitLab OAuth) | oauth.ts |
GITLAB_CLIENT_SECRET | Client secret GitLab | "" | Ні (потрібна для GitLab OAuth) | oauth.ts |
GITLAB_REDIRECT_URI | Redirect URI GitLab | "" | Ні (потрібна для GitLab OAuth) | oauth.ts |
OAUTH_FRONTEND_SUCCESS_URL | Куди перенаправити після успішного входу | /?oauth=success | Ні | oauth.ts |
OAUTH_FRONTEND_ERROR_URL | Куди перенаправити після помилки | /?error=oauth_failed | Ні | oauth.ts |
База даних
Порожнє значення вважається незаданим. Докладніше див. на сторінці База даних.
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
DB_CONNECTION | Тип клієнта БД | pg | Ні | database.ts |
PGSQL_HOST | Хост PostgreSQL | 127.0.0.1 | Ні | database.ts |
PGSQL_PORT | Порт PostgreSQL | 5432; не ціле число з 1–65535 — throw на старті | Ні | database.ts |
PGSQL_USER | Користувач БД | postgres | Ні | database.ts |
PGSQL_PASSWORD | Пароль БД | "" | Залежить від сервера БД | database.ts |
PGSQL_SSL | Шифрування з'єднання з PostgreSQL: false, true (TLS з перевіркою сертифіката) або require (TLS без перевірки). Інше значення — throw на старті; у production-like з false — попередження | false | Ні | database.ts |
PGSQL_DB_NAME | Назва бази | vibe_template | Ні | database.ts |
Seed
Читає лише db:seed --demo (run-seed.ts); застосунок ці змінні не використовує. Якщо email або пароль порожні, відповідний акаунт пропускається (missing_credentials). Див. База даних → Seed.
| Змінна | Призначення | Default | Обов'язковість (умова) |
|---|---|---|---|
SEED_ADMIN_EMAIL | Email demo-адміна | — | Ні (лише для --demo) |
SEED_ADMIN_PASSWORD | Пароль demo-адміна | — | Ні (лише для --demo) |
SEED_USER_EMAIL | Email звичайного demo-користувача | — | Ні (опційно) |
SEED_USER_PASSWORD | Пароль звичайного demo-користувача | — | Ні (опційно) |
Redis
Для REDIS_HOST, REDIS_PORT, REDIS_PASSWORD і REDIS_PREFIX використовується ||, тому порожній рядок теж замінюється на default. REDIS_PORT (1…65535), REDIS_COMMAND_TIMEOUT_MS і REDIS_LOGOUT_ALL_DEADLINE_MS (цілі >= 1) читаються за контрактом цілих: порожній рядок дає default, інше недійсне значення — помилка старту Invalid Redis configuration: ... з validateRuntimeConfig. Як основний клієнт використовує ці значення — Відмова Redis.
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
REDIS_HOST | Хост Redis | 127.0.0.1 | Ні | redis.ts |
REDIS_PORT | Порт Redis | 6379 | Ні | redis.ts |
REDIS_PASSWORD | Пароль Redis | null | Ні | redis.ts |
REDIS_PREFIX | Префікс ключів (до 16 символів) | uwebsocket: | Ні | redis.ts |
REDIS_COMMAND_TIMEOUT_MS | Таймаут команди основного клієнта (сесії, WS-токени), мс | 500 | Ні | redis.ts |
REDIS_LOGOUT_ALL_DEADLINE_MS | Дедлайн усього циклу SCAN/DEL у logoutAll, мс | 2000 | Ні | redis.ts |
Сховище S3
Жодна змінна з цієї групи не має default (undefined). Усі вони потрібні для роботи з файлами в S3.
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
S3_REGION | Регіон | немає | Для S3 | disk.ts |
S3_ACCESS_KEY_ID | Access key | немає | Для S3 | disk.ts |
S3_SECRET_ACCESS_KEY | Secret key | немає | Для S3 | disk.ts |
S3_ENDPOINT | Endpoint S3-сумісного сховища | немає | Для S3 | disk.ts |
S3_BUCKET | Bucket | немає | Для S3 | disk.ts |
S3_PREFIX | Загальний префікс ключів | немає | Ні | disk.ts |
S3_STATIC_DATA_PREFIX | Префікс статичних даних | немає | Ні | disk.ts |
S3_DYNAMIC_DATA_PREFIX | Префікс динамічних даних | немає | Ні | disk.ts |
Пошта (SMTP)
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
SMTP_ENABLED | Вмикає надсилання пошти | false | Ні | mail.ts |
SMTP_HOST | SMTP-хост | "" | Так, якщо SMTP_ENABLED=true | mail.ts |
SMTP_PORT | SMTP-порт | 587 | Ні | mail.ts |
SMTP_SECURE | Пряме TLS-з'єднання | false | Ні | mail.ts |
SMTP_REQUIRE_TLS | Вимагати STARTTLS | true | Ні | mail.ts |
SMTP_IGNORE_TLS | Не використовувати STARTTLS | false | Ні | mail.ts |
SMTP_USER | Логін SMTP | "" | Залежить від сервера | mail.ts |
SMTP_PASSWORD | Пароль SMTP | "" | Залежить від сервера | mail.ts |
SMTP_FROM_EMAIL | Адреса відправника | "" | Так, якщо SMTP_ENABLED=true | mail.ts |
SMTP_FROM_NAME | Ім'я відправника | "" | Ні | mail.ts |
SMTP_REPLY_TO | Адреса Reply-To | "" | Ні | mail.ts |
Push-сповіщення (Web Push)
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
VAPID_PUBLIC_KEY | Публічний VAPID-ключ | "" | Для push | push.ts |
VAPID_PRIVATE_KEY | Приватний VAPID-ключ | "" | Для push | push.ts |
VAPID_SUBJECT | VAPID subject | mailto:admin@vibe-template.example | Ні | push.ts |
AI
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
LOG_LEVEL | Рівень логів pino: fatal, error, warn, info, debug, trace, silent; інше значення зупиняє старт | info | Ні | logging.ts |
RESPONSE_VALIDATION_CONTRACT | Реакція на порушення контракту відповіді (ResponseSchema): strict або log, див. Перевірка відповідей; інше значення зупиняє старт | strict, у production log | Ні | response-validation.ts |
READINESS_CHECK_TIMEOUT_MS | Таймаут кожної перевірки GET /ready (PostgreSQL, Redis), мс, 50–30000 | 1000 | Ні | health.ts |
AI_TEXT_DRIVER | Текстовий AI-драйвер: openai, xai або mistral; інше значення зупиняє старт | openai | Ні | ai.ts |
AI_REQUEST_TIMEOUT_MS | Ліміт на один виклик AI-провайдера (мс, ціле ≥ 1000); перевищення → 504 upstream_timeout | 60000 | Ні | ai.ts |
AI_SUPPORT_DAILY_TOKEN_BUDGET | Токенів на користувача на добу UTC для чату підтримки (Допуск повідомлення, ADR 0003); понад — відповідь 429 support_budget_exceeded. 0 вимикає облік | 200000 | Ні; не невід'ємне ціле — помилка конфігурації; 0 у production-like — помилка старту | ai.ts |
AI_SUPPORT_PROMPT_ALLOWANCE_TOKENS | Запас у резерві відповіді на системний промпт, контекст бази знань та історію, розмір яких невідомий на допуску | 8000 | Ні; не невід'ємне ціле — помилка конфігурації | ai.ts |
AI_USAGE_STORE_PROMPTS | Чи зберігати текст промпту в llm_text_usage.final_prompt (Що журнал зберігає від промпту). За замовчуванням — лише SHA-256 і довжина | false | Ні; не булеве значення за контрактом — помилка конфігурації | ai.ts |
AI_USAGE_PROMPT_RETENTION_DAYS | Скільки днів тримати текст промпту, коли він зберігається; старіший очищає llm:purge-prompts | 30 | Ні; не ціле ≥ 1 — помилка конфігурації | ai.ts |
PROMPT_CACHE_TTL_MS | TTL кешу промптів у процесі (мс, ≥ 1000); інші інстанси бачать оновлення промпту із цією затримкою | 60000 | Ні | ai.ts |
SUPPORT_DEFAULT_LANGUAGE | Мова відповідей Support AI, коли клієнт не передав свою (код з APP_LOCALE_CODES) | en | Ні | support.ts |
SUPPORT_EMBEDDING_BATCH_SIZE | Статей в одному запиті embeddings при переіндексації (1–2048) | 50 | Ні | support.ts |
SUPPORT_SEARCH_MAX_DISTANCE | Максимальна косинусна відстань статті до запиту (0–2], далі стаття не йде в контекст | 0.8 | Ні | support.ts |
OPENAI_API_KEY | Ключ OpenAI (чат та embeddings) | "" | Для драйвера openai та embeddings | ai.ts |
OPENAI_CHAT_MODEL | Модель чату OpenAI | gpt-5.4-mini | Ні | ai.ts |
OPENAI_CHAT_API_URL | Endpoint chat completions | https://api.openai.com/v1/chat/completions | Ні | ai.ts |
OPENAI_EMBEDDING_MODEL | Модель embeddings | text-embedding-3-small | Ні | ai.ts |
OPENAI_EMBEDDING_DIMENSIONS | Розмірність embeddings; має дорівнювати розмірності колонки (1536), інакше старт зупиняється | 1536 | Ні | ai.ts |
XAI_API_KEY | Ключ xAI | "" | Для драйвера xAI | ai.ts |
XAI_CHAT_MODEL | Модель чату xAI | grok-4.3 | Ні | ai.ts |
MISTRAL_API_KEY | Ключ Mistral | "" | Для драйвера Mistral | ai.ts |
MISTRAL_TEXT_MODEL | Текстова модель Mistral | mistral-medium-latest | Ні | ai.ts |
Sentry і спостережуваність
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
SENTRY_DSN | DSN Sentry; без нього Sentry вимкнено | немає | Для Sentry | sentry.ts |
SENTRY_ENABLED | Вимикач Sentry; працює лише разом з непорожнім DSN | true | Ні | sentry.ts |
SENTRY_ENVIRONMENT | Назва оточення в Sentry | значення APP_ENV | Ні | sentry.ts |
SENTRY_RELEASE | Реліз | немає | Ні | sentry.ts |
SENTRY_TRACES_SAMPLE_RATE | Частка трасувань, від 0 до 1 | 0 (некоректне значення дає warning і 0) | Ні | sentry.ts |
TURN (WebRTC)
| Змінна | Призначення | Default | Обов'язковість (умова) | Читає файл |
|---|---|---|---|---|
TURN_SECRET | Спільний секрет для тимчасових TURN-облікових даних (TTL 3600 с задано в коді) | "" | Для TURN | turn.ts |
TURN_HOST | Хост TURN-сервера | "" | Для TURN | turn.ts |
Модуль support.ts містить лише системні промпти AI-підтримки й не читає змінних оточення.
Відповідність .env.example
packages/backend/.env.example містить усі змінні, які читає бекенд, крім NODE_ENV (запасне джерело для APP_ENV). Змінних, яких код не читає, у файлі немає.
TURN_SECRETіTURN_HOSTчитаєconfig/turn.ts, але цей модуль поки ніхто не імпортує.- Назва
CREDENTIONALS_CORSмістить друкарську помилку, але саме так її читає код, тому змінювати її не можна.
Як запустити проєкт локально, див. на сторінці Початок роботи. Загальний огляд бекенда див. у розділі Backend.