Что не так с паролями в .env и в коде
Хранение секретов — паролей баз данных, API-ключей, приватных ключей SSH — часто сводится к файлу .env в корне проекта. Файл случайно коммитят в Git, копируют целиком на бэкап-сервер, читают через cat любым процессом с доступом на сервер. Утечка одного файла раскрывает сразу все сервисы.
Проблема глубже, чем «не коммитить .env». У пароля в текстовом файле нет истории обращений: неизвестно, кто и когда его читал, нельзя отозвать доступ одному сотруднику без смены пароля для всех остальных. Для этого существуют отдельные системы хранения секретов.
Переменные окружения: минимальный уровень защиты
Пока Vault не развёрнут, соблюдайте базовые правила для переменных окружения:
- Файл
.envдолжен иметь права 600 и принадлежать пользователю сервиса, а не root. - Добавляйте
.envв.gitignoreдо первого коммита, а не после утечки. - Не передавайте секреты через аргументы командной строки — они видны в выводе
ps auxвсем локальным пользователям. - В systemd используйте
EnvironmentFile=с правами 600, а неEnvironment=в юните — юнит-файлы читаемы всеми.
chmod 600 /etc/myapp/.env
chown myapp:myapp /etc/myapp/.env
Это снижает риск утечки, но не решает задачу ротации и аудита — для этого нужен отдельный сервис хранения секретов, например HashiCorp Vault.
HashiCorp Vault: как устроено хранение секретов
Vault — сервер, который хранит секреты в зашифрованном виде и выдаёт их по запросу через API, проверяя права клиента. Три ключевых понятия:
- Secrets engine — модуль хранения: KV для пар ключ-значение, Database для временных учётных записей MySQL и PostgreSQL, PKI для выпуска сертификатов.
- Seal и Unseal — Vault запускается в запечатанном состоянии, данные на диске зашифрованы мастер-ключом. Распечатать сервер можно только собрав 3 из 5 частей ключа.
- Lease и TTL — каждый выданный секрет живёт ограниченное время, по истечении TTL он отзывается автоматически.
Такая модель заменяет статичные пароли короткоживущими токенами и даёт полный журнал: кто, когда и какой секрет запросил.
Установка Vault на VPS: пошагово
Пример для Ubuntu 24.04 на VDS с 2 ГБ RAM — минимальная конфигурация для одного узла:
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vault
Настройте бэкенд хранения в файле /etc/vault.d/vault.hcl — для одного сервера подходит файловый storage, и запустите сервис:
sudo systemctl enable --now vault
export VAULT_ADDR='https://127.0.0.1:8200'
vault operator init
vault operator unseal
Команда vault operator init выводит 5 ключей распечатывания и один root-токен — сохраните их в разных местах, не на этом же сервере. Root-токен нужен только для первичной настройки политик, после чего его лучше отозвать.
Динамические секреты для базы данных
Вместо одного постоянного пароля к MySQL настройте Database secrets engine — Vault будет создавать временную учётную запись на каждый запрос:
vault secrets enable database
vault write database/config/mysql \
plugin_name=mysql-database-plugin \
connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/" \
allowed_roles="app-role" \
username="vaultadmin" password="StrongRootPass"
vault write database/roles/app-role \
db_name=mysql \
creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT, INSERT, UPDATE ON appdb.* TO '{{name}}'@'%';" \
default_ttl="1h" max_ttl="24h"
Приложение запрашивает учётные данные через API и получает логин с TTL 1 час. Через час учётная запись удаляется автоматически, даже если приложение забыло про неё. Компрометация одного токена не даёт постоянного доступа к базе.
Ротация, аудит и чек-лист
Включите audit device, чтобы каждый запрос секрета писался в лог:
vault audit enable file file_path=/var/log/vault_audit.log
Для статичных секретов настройте ротацию по расписанию через cron-задачу с одновременным обновлением пароля в целевой системе. Политики доступа выдавайте по принципу минимальных прав — отдельная политика на каждое приложение, а не общий root-токен.
- Секреты не лежат в Git и не передаются через аргументы командной строки.
- Файлы с переменными окружения имеют права 600 и владельца — пользователя сервиса.
- Для баз данных используются динамические секреты с TTL, а не постоянный пароль.
- Root-токен Vault отозван после настройки, для работы — именованные токены с политиками.
- Включён audit log, доступ к нему ограничен отдельной ролью.
Подробнее о шифровании самих файлов на диске — в статье про GPG-шифрование файлов и резервных копий, а о правах доступа — в материале про права на файлы Linux. Общий порядок настройки нового сервера описан в чек-листе безопасности Linux-сервера.