env-master
ENСоздать аккаунт

Почему .env-файлам не место в продакшене

Короткий ответ: .env на ноутбуке разработчика — удобный формат для локального запуска, а .env на прод-сервере — это секрет, лежащий открытым текстом на диске, чьи копии вы больше не контролируете. Он попадает в бэкапы, слои образов, артефакты CI и домашние синхронизации; его читает любой процесс с доступом к файловой системе; при утечке вы не узнаете об этом из самого файла. Замена — не «спрятать файл получше», а убрать его из деплоя: сервис при старте сам забирает значения из хранилища по своей машинной identity, и каждое такое чтение остаётся в журнале.

Файл на диске не умеет молчать

Проблема .env в проде — не в формате, а в свойствах файла как носителя:

  • Копии размножаются сами. Файл попадает в резервные копии хоста, в снапшоты диска, в слой Docker-образа, если его забыли в .dockerignore, в архив артефактов CI. Удалить оригинал — не значит удалить копии.
  • Прочитать может любой процесс на хосте. Права 600 защищают от других пользователей, но не от процесса, работающего под тем же, — а именно под ним работает и всё, что вы запускаете рядом с приложением.
  • Файл не фиксирует чтение. Кто и когда открыл файл, не знает никто. Инцидент расследуется по косвенным следам, если расследуется вообще.

«У нас не файл, а переменные окружения» — не ответ

Переменные, выставленные в настройках оркестратора или CI, избавляют от файла, но не от проблемы. Значение в переменной окружения видно через /proc/<pid>/environ любому процессу с нужными правами, попадает в crash-дампы и отчёты об ошибках, отображается в интерфейсе оркестратора всем, у кого есть доступ к проекту. Главное — оно по-прежнему раздаётся человеком и хранится у стороннего потребителя (CI, PaaS) в открытом виде: хранилище секретов подменяется настройками деплоя, у которых нет ни аудита чтения, ни ротации.

Как выглядит доставка без файла

В env-master сервис — сущность первого класса со своей machine identity. При старте SDK аутентифицируется по client credentials, получает короткоживущий токен и забирает значения — шифртекст плюс ключ, обёрнутый под эту конкретную identity. Расшифровка происходит в памяти самого сервиса: машинный путь честно клиентский, сервер открытое значение в этом сценарии не производит (где граница на самом деле — написано на странице безопасности и в модели угроз, без слова «zero-knowledge»).

Дальше значения живут только в памяти процесса: на диске их нет, в образе их нет, в настройках CI их нет. Каждое чтение — записано в журнал, доступ identity можно сузить до списка ключей (DB_*, а не всё окружение), а значение с видимостью restricted человеку не показывается вообще — его получает только сервис.

Как переехать, не останавливая сервис

Переезд не требует переписывать приложение в один вечер:

  1. Заведите проект и перенесите значения. envmaster import .env --dry-run покажет план до записи и сам отметит, что похоже на секрет (быстрый старт).
  2. Выдайте сервису identity со скоупом на его окружение и набор ключей.
  3. Подключите SDK — это замена чтения process.env на клиент, который держит значения в памяти и сам обновляет токен.
  4. Промежуточный шаг для легаси: envmaster run -- <команда> передаёт значения дочернему процессу через окружение, не записывая их на диск, — приложение менять не нужно вообще.
  5. Удалите файл с серверов, из CI и из бэкапов — теперь он никому не нужен.

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

Аварийный выход остаётся открытым всегда: выгрузка окружения обратно в обычный .env — одна команда CLI. Хранилище, из которого нельзя уйти, — это не хранилище, а заложник.

← Все статьи