Переменные окружения
Что и зачем вписывать в конфигурацию
Все три приложения читают один .env в корне репозитория. Файл ищется вверх по дереву от рабочей директории, так что запускать процессы можно из любой папки внутри проекта.
Большинство переменных подхватываются при перезапуске. Пересобирать фронты нужно только ради GOOGLE_ANALYTICS_ID, YANDEX_METRIKA_ID, COLOR_MODE_PREFERENCE и COLOR_MODE_FALLBACK: они подключают модули на этапе сборки.
Файл важнее окружения
Порты читаются сначала из .env, и только потом из переменных окружения. Так сделано из-за игровых панелей вроде Pterodactyl: они инжектят свой SERVER_PORT под аллокацию, и без этого приоритета бэкенд уезжал бы на чужой порт. Основное имя теперь BACKEND_PORT, старое SERVER_PORT тоже читается.
Обязательное
Без этих четырёх приложение не стартует.
| Переменная | Что это |
|---|---|
BASEURL | Публичный адрес сайта, например https://example.com |
API_BASEURL | Адрес API, например https://api.example.com |
DATABASE_NAME | Имя базы |
JWT_KEY | Секрет для подписи токенов |
ADMIN_BASEURL можно не заполнять — тогда возьмётся BASEURL с портом из ADMIN_PORT. Серверу он нужен, чтобы разрешить админке CORS.
Проект и время
SITENAME=UnicoreCMS
TIMEZONE=UTC
CLIENT_PORT=3000
ADMIN_PORT=4000
BACKEND_PORT=5000Временем в проекте управляет одна ручка TIMEZONE. В этой зоне время пишется в базу и показывается на сайте. Берите UTC: он не зависит от переводов часов и не поедет при переносе сервера в другую страну.
База данных
DATABASE_TYPE=mysql
DATABASE_HOST=127.0.0.1
DATABASE_PORT=3306
DATABASE_USER=unicore
DATABASE_PASSWORD=...
DATABASE_NAME=unicoreDATABASE_TYPE понимает mysql, mariadb и postgres.
Секреты
JWT_KEY=...
ENCRYPTION_KEY=
ENCRYPTION_KEY_PREVIOUS=JWT_KEY подписывает токены доступа. ENCRYPTION_KEY шифрует данные в базе: хеши паролей, пароли RCON, секреты 2FA. Держите их разными, чтобы утечка одного не роняла второе. Если ENCRYPTION_KEY пустой, берётся JWT_KEY.
Оба генерируются одинаково:
openssl rand -hex 32Потеря ENCRYPTION_KEY необратима
Без ключа никто не сможет войти, а пароли RCON и секреты 2FA не расшифруются. Положите его в бэкап отдельно от базы, иначе бэкап бесполезен.
Смена ключа шифрования
Старый ключ переезжает в ENCRYPTION_KEY_PREVIOUS, новый вписываете в ENCRYPTION_KEY. Дальше одна команда:
pnpm --filter unicore-server exec node dist/cli/main.js crypto-rewrapОна перешифрует пароли RCON и секреты 2FA. Пароли пользователей перешифруются сами при следующем успешном входе. Когда все зашли, ENCRYPTION_KEY_PREVIOUS можно чистить.
Пароли
PASSWORD_ALGORITHM=argon2id
PASSWORD_ARGON2_MEMORY=65536
PASSWORD_ARGON2_TIME=3
PASSWORD_ARGON2_PARALLELISM=4
PASSWORD_BCRYPT_COST=12По умолчанию argon2id. Старые bcrypt-хеши читаются в любом случае и молча переезжают на текущий алгоритм при следующем входе, так что миграцию запускать не нужно.
Токены и прокси
JWT_EXPIRES=15m
JWT_REFRESH_EXPIRES=7d
TRUST_PROXY=
CORS_ORIGINS=Чаще всего странные баги на продакшене устраивает TRUST_PROXY. Если сайт стоит за nginx и переменная пустая, сервер у всех клиентов видит IP прокси. Сразу ломаются троттлинг, антифлуд на сбросе пароля, IP-фильтр API-ключей и проверка вебхуков платёжек.
| Схема | Значение |
|---|---|
| nginx на том же хосте | loopback |
| Один прокси перед приложением | 1 |
docker-compose с профилем nginx | 1 |
| Приложение смотрит в интернет напрямую | оставить пустым |
Пустое значение при живом прокси открывает ещё и дыру: клиент сможет подделать свой IP заголовком X-Forwarded-For.
В CORS_ORIGINS источники перечисляются через запятую. Пустое значение означает BASEURL плюс ADMIN_BASEURL, для большинства проектов этого достаточно.
Почта
MAIL_FROM=no-reply@example.com
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASSWORD=
SMTP_SECURE=falseВместо хоста и порта можно указать SMTP_SERVICE, то есть имя провайдера из списка nodemailer (gmail, yandex, mail.ru и другие). Остальное подставится само.
Без рабочего SMTP не уйдут письма активации и сброса пароля. Если активация почты вам не нужна, отключите её в настройках сайта — иначе новые игроки останутся с неактивированными аккаунтами.
Прочее
RECAPTCHA_PUBLIC=
RECAPTCHA_SECRET=
COLOR_MODE_PREFERENCE=light
COLOR_MODE_FALLBACK=light
REAL_DECIMALS=2
VIRTUAL_DECIMALS=2
INGAME_DECIMALS=2Используется reCAPTCHA третьей версии, пустые ключи просто выключают проверку. В *_DECIMALS задаётся число знаков после запятой для реальной, виртуальной и внутриигровой валюты.
Интеграции
Ключи платёжек, мониторингов и соцсетей описаны там, где о них речь:
- Платёжные системы —
UNITPAY_*,FREEKASSA_*,ENOTIO_*,PAYOK_*,ANYPAY_*,CENTAPP_* - Голосования —
MCTOP_*,MCRATE_*,TOPCRAFT_*,MINECRAFTRATING_*,MONITORINGMINECRAFT_* - Новости и вебхуки —
VK_LONGPOLL,VK_APIKEY,DISCORD_CLIENT_ID,DISCORD_CLIENT_SECRET
Каждая интеграция включается своим *_ENABLED=1. Если включить интеграцию и не заполнить её ключи, сервер откажется стартовать и напишет, чего именно не хватает. Это лучше, чем молча не работающая оплата.