Один раз я закоммитил .env с реальными ключами в публичный репозиторий. Ключи ротировал через 15 минут, но осадок остался. С тех пор тема стала для меня чуть болезненной.
Первый подход который я пробовал — .env.example в репозитории, реальный .env у каждого разработчика локально. Работает, но синхронизация утомляет: добавил переменную, не забудь обновить example, предупреди команду. Человеческий фактор рано или поздно подводит.
Второй — Vault от HashiCorp. Мощно, надёжно, избыточно для большинства проектов где я работал. Настройка и поддержка отнимают больше чем дают, если у вас не энтерпрайз.
Сейчас пользуюсь 1Password Secrets Automation для рабочих проектов и pass (консольный менеджер паролей на GPG) для личного. Оба умеют отдавать секреты в переменные окружения без того чтобы они когда-либо лежали в файловой системе в открытом виде.
Для небольших проектов где нет смысла городить огород — шифрую .env через age и кладу зашифрованный файл в репозиторий. Ключ шифрования храню отдельно. Не идеально, но практично.
Главное правило которое я для себя вывел: секрет который лежит в git — уже не секрет, даже в приватном репозитории. Это вопрос времени.