Skip to main content

Environment Variables

Полный список переменных окружения API. Валидация происходит при старте через Zod (apps/api/env.schema.ts) — приложение не запустится с невалидными значениями.

Адреса API — origin без пути

NEXT_PUBLIC_API_URL, API_BASE_URL и API_URL содержат только origin: https://bitrate.me, не https://bitrate.me/api. Префикс добавляют сами клиенты — apps/api объявляет setGlobalPrefix('api'), и оба fetch-клиента строят путь как ${base}/api/v1/….

Указав префикс в переменной, получишь /api/api/v1/… и 404 на каждом запросе. Ошибка коварна тем, что приложение стартует нормально и падает только при обращении к API.

NEXT_PUBLIC_* впекаются в бандл при сборке — их изменение требует пересборки приложения, перезапуска контейнера недостаточно.

Какой файл читается когда

В репозитории два независимых механизма, и они не пересекаются. Значение, положенное не в тот файл, молча игнорируется: приложение упадёт на валидации так, будто переменной нет вовсе.

ЗапускЧитаетсяКак
pnpm dev нативноapps/api/.env*, apps/web-player/.env*приложение само загружает свой файл
task dev:up, task prod:up в Dockerтолько корневой .envподстановка ${VAR} в compose

Вызывай стеки через task, а не через docker compose напрямую. Compose ищет .env рядом с compose-файлом, поэтому команда docker compose -f infra/docker-compose.prod.yaml читает infra/.env, не находит его и молча подставляет пустые строки во все ${VAR}. Задачи в Taskfile.yml передают --env-file .env явно.

Per-app файлы до контейнера не доходят по двум причинам сразу: ни один сервис в infra/docker-compose.*.yaml не объявляет env_file, а .dockerignore исключает .env, .env.development и .env*.local из сборочного контекста. Внутрь образа попадает только .env.example.

Почему у контейнеров явный список, а не env_file

Каждый сервис перечисляет свои переменные в environment: поимённо. Это дороже в сопровождении, но список видно при ревью, и в контейнер не утекает ничего лишнего — например, секреты соседнего приложения.

У этого есть следствие, которое стоит помнить: переменная, отсутствующая в environment: сервиса, не попадёт в него, даже если она есть в корневом .env. Добавляя новую переменную, её нужно прописать и в .env, и в environment: нужного сервиса.

Обязательное и опциональное в compose

Форма записи в environment: определяет, что увидит приложение, когда переменная не задана:

ЗаписьЗаданаНе задана
KEY=${KEY}значениепустая строка
KEY (голое имя)значение из .envне передаётся, в приложении undefined

Разница существенна: Zod-схема пропускает undefined для .optional(), но пустая строка провалит z.url() и .min(32). Поэтому опциональные переменные (SMTP_*, S3_*, SENTRY_DSN, METRICS_TOKEN, USER_WEB_HOST) записаны голыми именами — «опционально» должно означать «отсутствует», а не «пусто».

Основные

ПеременнаяОбязательнаПо умолчаниюОписание
NODE_ENVнетlocallocal / development / production / test
PORTнет3000Порт HTTP-сервера
WEB_HOSTдаURL фронтенда (CORS + OAuth redirect). Пример: http://localhost:3001

Auth / JWT

ПеременнаяОбязательнаПо умолчаниюОписание
JWT_SECRETдаСекрет для подписи JWT (минимум 10 символов)
JWT_ACCESS_EXPIRES_INнет5mСрок действия access token
JWT_REFRESH_EXPIRES_INнет30dСрок действия refresh token
ACCESS_TOKEN_NAMEнетaccess_tokenИмя HttpOnly cookie с access token
REFRESH_TOKEN_NAMEнетrefresh_tokenИмя HttpOnly cookie с refresh token

OAuth

Все опциональны — если не заданы, соответствующий провайдер недоступен.

ПеременнаяОписание
OAUTH_GOOGLE_CLIENT_IDGoogle OAuth Client ID
OAUTH_GOOGLE_CLIENT_SECRETGoogle OAuth Client Secret
OAUTH_FACEBOOK_APP_IDFacebook App ID
OAUTH_FACEBOOK_APP_SECRETFacebook App Secret
API_BASE_URLБазовый URL API для OAuth callback. Пример: http://localhost:3000

База данных

ПеременнаяОбязательнаОписание
DATABASE_URLдаPostgreSQL connection string. Пример: postgresql://user:pass@localhost:5432/bitrate

Redis

ПеременнаяОбязательнаПо умолчаниюОписание
REDIS_HOSTдаХост Redis
REDIS_PORTнет6379Порт Redis

Почта

Все опциональны. Если не заданы — письма для сброса пароля логируются в консоль (dev-режим).

ПеременнаяПо умолчаниюОписание
SMTP_HOSTSMTP-сервер
SMTP_PORT587SMTP-порт
SMTP_USERSMTP логин
SMTP_PASSSMTP пароль
EMAIL_FROMАдрес отправителя

Мониторинг

ПеременнаяОбязательнаОписание
SENTRY_DSNнетDSN проекта в Sentry. Если не задан — Sentry инициализируется без DSN (ошибки не отправляются)

Шаблон .env

# Core
NODE_ENV=local
PORT=3000
WEB_HOST=http://localhost:3001

# Auth
JWT_SECRET=your-super-secret-key-min-10-chars
JWT_ACCESS_EXPIRES_IN=5m
JWT_REFRESH_EXPIRES_IN=30d

# Database
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/bitrate

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379

# OAuth (optional)
OAUTH_GOOGLE_CLIENT_ID=
OAUTH_GOOGLE_CLIENT_SECRET=
OAUTH_FACEBOOK_APP_ID=
OAUTH_FACEBOOK_APP_SECRET=
API_BASE_URL=http://localhost:3000

# Mail (optional)
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
EMAIL_FROM=

# Sentry (optional)
SENTRY_DSN=