Переменные окружения: где живут настройки и секреты
Что такое переменные окружения, зачем нужен файл .env, почему настройки разные в разработке и в продакшне и почему секреты нельзя класть во фронтенд.
Переменные окружения — это настройки, которые приложение получает снаружи при запуске, а не хранит в своём коде: адрес базы данных, ключи API, режим работы. Один и тот же код читает их и ведёт себя по-разному в зависимости от того, где запущен.
Если ты видел в проекте файл .env или строчки вроде process.env.DATABASE_URL — это они. Разберёмся, зачем они нужны, как устроены и где в проектах на вайбкоде с ними чаще всего ошибаются.
Зачем нужны переменные окружения
Представь, что адрес базы прописан прямо в коде. Тогда:
- чтобы подключиться к тестовой базе вместо боевой, надо менять код;
- пароль от базы попадает в Git и остаётся в истории навсегда, даже если потом его удалить;
- каждый, у кого есть доступ к репозиторию, получает доступ к данным.
Переменные окружения разделяют две вещи: что делает программа (код, одинаковый везде) и с чем она работает (настройки, свои для каждого места запуска). Код можно спокойно показывать подрядчику или выкладывать в открытый доступ, а настройки остаются у того, кто запускает.
Файл .env и как он работает
На сервере переменные задаются в панели хостинга или в конфигурации запуска. Локально их удобнее держать в файле .env в корне проекта — библиотека или фреймворк читает его при старте.
DATABASE_URL=postgres://localhost:5432/myapp
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_API_URL=http://localhost:3000
Три правила для этого файла:
.envвсегда в.gitignore. Проверь это сейчас, а не потом.- Рядом лежит
.env.example— те же имена, но без настоящих значений. Он в Git, и по нему новый человек понимает, что нужно заполнить. - Если
.envс настоящими ключами хоть раз попал в репозиторий, ключи считаются утёкшими. Их нужно перевыпустить, а не просто удалить файл.
Почему значения разные в каждом окружении
У нормального проекта как минимум два места запуска: твой компьютер и продакшн. Часто есть ещё стейджинг — копия для проверки перед выкаткой. Код везде один, а переменные свои:
- локально — тестовая база и тестовые ключи оплаты;
- на стейджинге — отдельная база с ненастоящими данными;
- в продакшне — боевая база и боевые ключи, которые знает только сервер.
Так случайный запуск на ноутбуке не спишет деньги с настоящей карты и не разошлёт письма клиентам. Если у тебя локально в .env лежат боевые ключи — это ровно та ситуация, от которой переменные должны защищать.
Главная ловушка: переменные во фронтенде
Здесь путаются чаще всего. Переменные окружения на сервере остаются на сервере. А переменные фронтенда при сборке вписываются прямо в JavaScript, который скачивает браузер. После этого их может прочитать любой посетитель через инструменты разработчика.
Фреймворки помечают такие переменные префиксом: NEXT_PUBLIC_, VITE_, REACT_APP_, EXPO_PUBLIC_. Префикс означает не «удобная переменная», а «эта строка будет публичной».
Что можно класть с таким префиксом:
- адрес твоего API;
- публичный ключ аналитики или карт;
- публичный ключ Supabase или Firebase — он рассчитан на то, что его увидят, и защищают данные правила доступа, а не он.
Что нельзя никогда:
- секретные ключи оплаты;
- ключи OpenAI, Anthropic и других платных API;
- служебные ключи базы, которые обходят правила доступа;
- пароли, токены почтовых сервисов, ключи подписи.
Если фронтенду нужно что-то, для чего требуется секрет, — например, вызвать ИИ, — запрос идёт через твой сервер или серверную функцию. Браузер просит сервер, сервер с секретом идёт к внешнему API.
Ещё пара тонкостей
- Переменные читаются при старте или при сборке. Поменял значение в панели хостинга — приложение нужно перезапустить, а фронтенд часто пересобрать. Иначе ты будешь час искать, почему ничего не изменилось.
- Пустое значение хуже ошибки. Если обязательной переменной нет, приложению лучше упасть при старте с понятным сообщением, чем запуститься и ходить с пустым ключом.
- Не логируй переменные целиком. Строчка «печатаю конфиг для отладки» — частый путь секрета в логи.
Коротко
- Переменные окружения — настройки, которые приложение получает при запуске, а не хранит в коде.
.envне попадает в Git; в Git лежит.env.exampleбез значений.- У разработки, стейджинга и продакшна разные значения, и боевые ключи есть только на сервере.
- Всё с префиксом
NEXT_PUBLIC_,VITE_и подобными уезжает в браузер и становится публичным. - После смены переменной приложение нужно перезапустить или пересобрать.
Если не уверен, какие ключи у тебя уже лежат в бандле, SUBXCAT может это проверить и навести порядок.