# Хранение секретов на сервере: Vault и переменные окружения

> Хранение секретов на сервере: как настроить HashiCorp Vault, выдавать временные пароли для MySQL и защитить переменные окружения вместо файла .env.

## Что не так с паролями в .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-шифрование файлов и резервных копий](https://www.zevshost.net/ru/kb/gpg-shifrovanie-failov/), а о правах доступа — в материале про [права на файлы Linux](https://www.zevshost.net/ru/kb/linux-file-permissions/). Общий порядок настройки нового сервера описан в [чек-листе безопасности Linux-сервера](https://www.zevshost.net/ru/kb/server-security-checklist/).

---

Источник: https://www.zevshost.net/ru/kb/hranenie-sekretov-vault/
