Переменные окружения для API-ключей объяснены для нетехнических создателей: держите ключи вне подсказок и репозиториев, разделяйте dev/staging/prod и безопасно вращайте ключи.

API-ключ похож на пароль для сервиса, с которым общается ваше приложение (платежи, почта, карты, AI, аналитика). Он говорит сервису «этот запрос от моего аккаунта», поэтому сервис может списывать деньги, применять лимиты и давать доступ.
Ключи протекают, потому что их часто сначала вставляют ради скорости. Вы вставили его в чат, файл настроек или заметку «только на время», и он остался там там, где вы не планировали делиться.
Распространённые пути случайной утечки: подсказки в чатах (особенно если вы быстро собираете продукт с помощью инструментов вроде vibe-coding), коммит ключа в репозиторий или загрузка zip «на ревью», вставка ключа в скриншот или запись экрана, оставление его в общем документе или командном чате, либо хардкод ключа в фронтенд-коде, который виден каждому в браузере.
Риск не абстрактен. Самое быстрое неприятное следствие — неожиданные счета: кто-то использует ваш ключ тысячами запросов. Далее — доступ к данным: если ключ читает данные клиентов или отправляет письма, злоумышленник сможет сделать то же самое. В худшем случае ключ с широкими правами может привести к захвату аккаунта (например, если по нему можно создавать новые ключи).
Вам не нужно быть экспертом по безопасности, чтобы получить большую часть пользы. Небольшая привычка помогает: относитесь к ключам как к «секретам» и держите их вне подсказок и репозиториев. Именно для этого существуют переменные окружения: храните секрет в защищённом месте, а приложение читайте его во время выполнения, не встраивая в код или скриншоты.
Если запомнить одно правило, то это: код — что делает ваше приложение, конфигурация — как оно себя ведёт, а секреты — что оно никогда не должно раскрывать.
Код — это логика, которую вы пишете и публикуете (экраны, кнопки, вычисления, вызовы API). Его можно безопасно делиться с коллегами, и он обычно попадает в репозиторий.
Конфигурация — это настройка, которая может быть публичной без вреда. Подумайте: имя приложения, регион запуска, feature-флаги или базовый URL сервиса. Если кто-то увидит это, он не сможет потратить ваши деньги, получить приватные данные или выдать себя за вас.
Секреты — это ключи от королевства: API-ключи, пароли к базе, приватные токены, ключи подписи. Если посторонний их получит, он сможет действовать как ваше приложение.
Переменная окружения — это просто подписанный слот, который приложение читает при запуске. Код ищет метку (например, STRIPE_SECRET_KEY) и использует хранимое там значение. Такое разделение делает переменные окружения удобными для API-ключей: код остаётся одинаковым, а секрет находится вне подсказок, файлов и репозитория.
Разделение кода и секретов упрощает исправления. Если вы случайно раскрыли секрет, вы можете заменить значение, не меняя код.
Практический подход к окружениям: одинаковые метки, разные значения.
Например, можно использовать метку PAYMENTS_KEY везде: в dev — тестовый ключ, в staging — ограниченный, в prod — полноценный живой ключ. Если вы деплоите через платформу типа Koder.ai, это хорошо ложится: одно и то же приложение разворачивается в разных окружениях с разными настройками окружения.
Секрет — любое значение, которое даёт кому-то силу, которой быть не должно. Если посторонний его получит, он сможет войти, потратить ваши деньги, прочитать данные или выдать себя за приложение.
Типичные секреты: API-ключи, пароли к базам данных, приватные токены доступа, ключи подписи и секреты вебхуков. Если значение может создавать, удалять, списывать, читать приватные данные или подписывать запросы — относитесь к нему как к секрету.
Некоторые значения кажутся безобидными, но всё равно чувствительны. Например, write-токены: они могут не выглядеть как «пароли», но позволяют атакующему вносить изменения, загружать файлы, отправлять письма или писать в базу данных. То же касается admin-ключей, JSON-файлов сервисных аккаунтов и любых длинных случайных строк.
Не всё требует секретной обработки. Обычно не секретны: feature-флаги (которые меняют только интерфейс или поведение, но не доступ), публичные URL, текст интерфейса, идентификаторы аналитики и внутренние ID, которые сами по себе не дают доступа к данным. Если значение должно быть видно во фронтенде или в документации — скорее всего, это не секрет.
Быстрый тест: если вас расстроит, что это появилось в публичном чате или закоммичено в публичный репозиторий — это секрет.
Ведите короткий письменный список секретов вашего приложения. Для каждого указывайте назначение (платежи, почта, база, хранилище), где хранится (dev, staging, prod), кто владелец (вы, коллега, аккаунт вендора) и есть ли у него права записи. Этот список поможет при вращении ключей, чтобы не гадать.
Большинство утечек — не работа хакеров. Это обычные моменты, когда кто-то копирует значение, чтобы решить проблему, а потом забывает, что оно стало видимым. Хорошее правило: если это можно искать, синхронизировать, переслать или показать по экрану — считайте это публичным.
Чат — одна из основных причин. Люди вставляют полные API-ключи в подсказки, командные чаты или сообщения в техподдержку, потому что так быстро. Но чаты сохраняются и могут быть распространены. Если нужна помощь, вставляйте только последние 4–6 символов и имя ключа, например STRIPE_SECRET_KEY ...9f2a.
Git — классическая ловушка. Вы добавили ключ «только на время», закоммитили и потом удалили. Секрет остаётся в истории коммитов. Он также может распространиться через форки, скопированные сниппеты или диффы pull request.
Скриншоты и записи экрана протекают сильнее, чем думают люди. Демонстрационное видео может захватить экран настроек, командную строку или сообщение об ошибке с токеном. Даже размытый текст опасен, если видны другие части экрана.
Трекеры задач и заметки — тихий источник. Тикеты, чеклисты и общие документы копируются между командами и подрядчиками. Считайте их публичными журналами.
Пара привычек предотвращает большинство утечек:
Если вы работаете в Koder.ai, придерживайтесь той же логики: держите чувствительные значения в настройках окружения, а не в чате, где вы описываете приложение.
Цель проста: приложение должно читать секреты из окружения, а не из подсказки, кода или файлов, которые попадают в Git.
Файл .env — это простой текстовый файл на вашем компьютере с парами ключ=значение. Он упрощает локальную настройку, но и легко может протечь, поэтому относитесь к нему как к кошельку.
Создайте локальный .env и убедитесь, что он игнорируется Git (через .gitignore). Чтобы поделиться именами переменных с коллегами, отдавайте пример .env.example с заполнителями, но без реальных значений.
Выбирайте понятные имена, чтобы было ясно, за что они отвечают и где должны использоваться:
OPENAI_API_KEYSTRIPE_SECRET_KEYDATABASE_URLSENDGRID_API_KEYS3_ACCESS_KEY_IDПонятные имена снижают количество ошибок при настройке dev, staging и production.
При старте приложение спрашивает у операционной системы: «Есть ли значение для OPENAI_API_KEY?» Если значение есть, приложение его использует. Если нет — приложение должно рано завершиться с понятной ошибкой, а не работать в неисправном режиме.
Практическая привычка: логировать факт наличия переменной (да/нет), но никогда не выводить сам секрет.
Не вставляйте ключи в потоки чатов или тикеты. Используйте менеджер паролей (общий сейф) или другой защищённый канал и давайте доступ только по необходимости. Если кто-то уходит из команды, вращайте ключ.
Пример: основатель экспортирует проект Koder.ai и запускает его локально. Он хранит .env на своём ноутбуке, коммитит только .env.example и делится реальными ключами через общий менеджер паролей.
Представьте окружения как три отдельные комнаты.
Dev — ваш ноутбук или песочница, где вы быстро меняете вещи. Staging — безопасная копия продакшена для тестирования полной версии без влияния на пользователей. Prod — то, чем пользуются ваши клиенты.
Простое правило: одинаковые имена переменных везде, меняются только значения. Код читает STRIPE_SECRET_KEY во всех окружениях, но каждое окружение подставляет своё значение.
Небольшая таблица (даже в заметке) поможет:
| Имя переменной (одно и то же везде) | Dev значение | Staging значение | Prod значение |
|---|---|---|---|
PAYMENTS_API_KEY | тестовый ключ | staging-ключ | боевой ключ |
APP_BASE_URL | localhost URL | staging-домен | custom-домен |
DATABASE_URL | локальная БД | staging БД | prod БД |
Нельзя использовать боевые ключи в dev. Dev-ключи часто разделяют между коллегами и имеют широкие права.
Чтобы держать окружения в порядке с небольшой командой, договоритесь о нескольких правилах:
STRIPE_KEY vs STRIPE_API_KEY).Если вы используете хостинговый конструктор вроде Koder.ai, рассматривайте каждый таргет развёртывания (dev, staging, prod) как отдельное окружение с собственными значениями секретов, хотя код тот же.
Вращение секрета — это сознательная замена API-ключа по расписанию. Если всё сделать правильно, вращение скучное: вы меняете ключ, проверяете, что всё работает, и отключаете старый.
Самая безопасная модель — «два ключа на короткое время». Многие провайдеры позволяют иметь более одного активного ключа. Это перекрытие держит приложение рабочим во время переключения.
Простое окно вращения:
Если провайдер не поддерживает несколько активных ключей, выбирайте период с низкой нагрузкой и ожидайте краткого простоя. Цель та же: поменять секрет в одном месте, не трогая код.
Если думаете, что ключ утёк, действуйте сначала, расследуйте потом. Отзовите ключ сразу, затем выпустите новый и обновите переменную окружения. После стабилизации ищите, где он мог выйти: подсказки в чате, логи сборки, скриншоты, старые коммиты или общие документы.
Пример: вы сделали небольшой CRM в Koder.ai, он использует почтовый API. Вы создаёте новый почтовый ключ, ставите его в настройках окружения приложения, отправляете тестовое письмо и затем отзываете старый ключ.
CI/CD — это автоматизированный конвейер, который собирает и разворачивает приложение при пуше, и ему часто нужны те же секреты, что и приложению.
Главное правило: не провозите API-ключи в логах сборки, исходниках или подсказках. Рассматривайте pipeline как ещё одну машину, которой нужно передать секреты контролируемым способом.
Постарайтесь отделять секреты, нужные только при сборке, от секретов, нужных при запуске.
Секреты сборки нужны в процессе сборки (например, для скачивания приватного пакета). Секреты рантайма нужны после деплоя (вызовы Stripe, отправка почты). Если можно держать ключи только на рантайме, риск их запекания в бандле, кэше артефактов или выводе в лог уменьшается.
Быстрая проверка: если секрет нужен в браузере — это не секрет. Публичные «ключи для браузера» допустимы, но серверные API-ключи должны оставаться на сервере.
Используйте хранилище секретов платформы хостинга по окружениям, чтобы dev, staging и prod имели разные значения.
Если вы деплоите с хостингом Koder.ai, задавайте секреты как переменные окружения для каждого окружения вместо вставки ключей в код или конфиги. Тогда приложение читает их при запуске (например, PAYMENTS_API_KEY в проде и тестовый в staging).
Чтобы держать прод в безопасности, ограничьте, кто может смотреть и менять продовые секреты. Сведите группу «view secrets» к минимуму и по возможности разделяйте права на деплой и на изменение секретов. Также используйте отдельные ключи для окружений, чтобы staging не имел доступа к данным prod.
Большинство утечек — это повседневные сокращения, которые потом переносятся в следующие проекты.
.env)Если ключ внутри исходников, он попадёт в бэкапы, скриншоты, общие zip-архивы и историю git.
Фикс:
.env в .gitignore до первого коммита.Когда вы вставляете реальный ключ в чат, вы теряете контроль над тем, где этот текст сохранится или с кем поделятся. Если вы пользуетесь инструментом вроде Koder.ai, соблазн поместить всё в чат велик. Вместо этого используйте заполнители типа PAYMENTS_API_KEY=REDACTED и опишите проблему.
Хорошая привычка: копируйте сообщения об ошибках, а не учётные данные.
Один ключ для dev, staging и prod превращает одну утечку в инцидент побольше. Если коллеги делятся одним ключом, вы не сможете понять, кто им пользовался.
Фикс: создавайте разные ключи для окружений, а если провайдер позволяет — и для людей или отдельных приложений.
Распространённая ловушка — вывод «всей конфигурации» при старте. Часто туда попадают токены.
Фикс: логируйте только необходимое (например, «Stripe key loaded: yes») и маскируйте значения (показывайте последние 4 символа), когда нужно определить, какой ключ активен.
Пример: если staging падает, не выводите полный ключ. Выведите STRIPE_KEY ending in 9K2P, чтобы подтвердить, что задеплоили нужный ключ без раскрытия значения.
Перед тем как отпустить продукт, сделайте спокойный проход, посвящённый только секретам.
api_key, secret, token и именам провайдеров. Проверьте общие документы, скриншоты и вставленные в чаты фрагменты. Если ключ когда-либо был в git или документе, считайте его сожжённым и замените.Пример: если приложение использует платежный и почтовый API, у вас должны быть две отдельные пары ключей для dev, staging и prod и явный владелец для каждого. При деплое (через хостинг или платформу вроде Koder.ai) вы подставляете правильные env vars в нужное окружение, а не копируете их в подсказки, код или репозитории.
Майя — нетехнический основатель, она делает простой веб‑сервис: пользователи платят подписку, приложение отправляет квитанции и письма для сброса пароля. Она держит подсказки и репозиторий чистыми, называя секреты настройками, которые живут вне кода и подставляются во время выполнения через переменные окружения.
Небольшой набор переменных, которые она определяет (имена одинаковы везде; меняются только значения):
APP_ENV = development / staging / productionAPP_BASE_URL = http://localhost:3000 / https://staging.example.com / https://example.comPAYMENTS_PROVIDER_SECRET_KEY = тестовый ключ (dev) / тестовый ключ (staging) / боевой ключ (prod)EMAIL_PROVIDER_API_KEY = sandbox ключ (dev) / ограниченный ключ (staging) / полный ключ (prod)DATABASE_URL = локальная БД (dev) / staging DB (staging) / production DB (prod)Простое правило: dev и staging работают в тестовом режиме и на отдельных данных. Прод использует живые ключи и реальные данные. Так ошибка в staging не спишет реальные деньги и не пришлёт письма реальным клиентам.
Реальное событие вращения: подрядчик, у которого был доступ, уходит. Майя предполагает, что старые ключи могли быть скомпрометированы. Она создаёт новые ключи в дашбордах платежей и почты, обновляет значения окружений для всех окружений. Сначала вращает прод в тихое время, проверяет регистрацию, платежи и письма, а затем вращает staging и dev. Если что-то ломается, она быстро откатывает к прежней рабочей конфигурации.
Следующие шаги, чтобы не превратить это в хаос позже:
Напишите одностраничный «Список переменных окружения» для приложения (имя, назначение, где задано и кто имеет доступ). Поставьте ежемесячный 10‑минутный обзор, чтобы удалить неиспользуемые ключи и вращать всё, что рисковано.
Если вы уже работаете с Koder.ai (koder.ai), это помогает держать всё организованным: можно управлять деплоями и настройками окружения в одном месте. Снимки и откат тоже полезны, когда изменение конфигурации приводит к простою и нужно быстро восстановиться.
API-ключ может быстро привести к неожиданным расходам и иногда даёт доступ к приватным данным или правам вроде отправки писем. Относитесь к нему как к паролю: если кто-то получит ключ, он часто сможет действовать от имени вашего приложения.
Поместите секреты в переменные окружения, чтобы значение хранилось вне кода и вне того, что вы можете вставить, закоммитить или снять на скриншоте. Приложение читает секрет по имени (например, STRIPE_SECRET_KEY), а код остаётся безопасным для совместного использования.
Секрет — это всё, что позволит постороннему потратить деньги, получить доступ к приватным данным или выдать себя за ваше приложение. API-ключи, пароли БД, приватные токены, ключи подписи и webhook-секреты — это секреты; публичные идентификаторы и настройки только для интерфейса обычно не являются секретами.
Чаще всего секреты просачиваются через чаты, подсказки, тикеты, скриншоты и коммиты в git (включая историю коммитов). Хорошее правило — считать публичным всё, что можно найти, синхронизировать, переслать или показать по экрану.
Можно держать локальный .env для удобства, но никогда не коммитить его. Коммитьте .env.example с заполнителями, чтобы коллеги знали имена переменных без реальных значений.
Используйте одинаковые имена переменных во всех окружениях и меняйте только значения. Например, PAYMENTS_API_KEY есть в dev, staging и prod, но в dev будет тестовый ключ, а в prod — рабочий.
Нет. Серверные API-ключи не должны находиться в фронтенд-коде, потому что любой может их прочитать в браузере. Если нужно вызвать сервис безопасно, маршрутизируйте запрос через бэкенд и храните секреты на сервере.
Создайте новый ключ, обновите переменную окружения, перезапустите или задеплойте приложение и проверьте реальный рабочий сценарий. Когда убедитесь, что всё работает, отзовите старый ключ.
Немедленно отзовите или отключите скомпрометированный ключ и сгенерируйте новый, затем обновите окружение и задеплойте. После стабилизации приложения поищите источник утечки (чаты, коммиты, скриншоты) и устраните его.
Храните секреты в настройках окружения для каждого окружения и держите их вне проектного чата и исходного кода. Если конфигурация ломает систему, используйте снимки (snapshots) и откат, чтобы быстро вернуть рабочее состояние, не возвращая утёкшие ключи.