Безопасное хранение секретов на VPS: от .env до Vault
Пароли в коде, ключи в git, токены в истории bash — самый частый способ слить проект. Секреты нужно хранить отдельно от кода, шифровать в покое и выдавать процессам только на время. Пройдём путь от базового .env до systemd credentials, sops и HashiCorp Vault — по уровням зрелости.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Уровень 0: чего нельзя делать никогда
Сначала антипаттерны, которые убивают безопасность на корню:
- Секреты в git — даже удалённые, они остаются в истории коммитов навсегда
- Пароли в командной строке — попадают в ~/.bash_history и в вывод ps для всех пользователей
- Ключи с правами 644 — читает любой юзер системы
- Один пароль на всё — компрометация одного = компрометация всего
Проверьте, что не утекло в историю: grep -riE 'password|secret|api_key|token' ~/.bash_history. Если нашли — чистите историю и ротируйте секреты.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS для своих сервисовУровень 1: .env и переменные окружения
Базовый и рабочий подход — вынести секреты в .env файл вне репозитория с жёсткими правами:
cat > /etc/myapp/.env <<'EOF'
DB_PASSWORD=длинный-случайный-пароль
API_KEY=sk-...
EOF
chown appuser:appuser /etc/myapp/.env
chmod 600 /etc/myapp/.env
Обязательно добавьте .env в .gitignore:
echo '.env' >> .gitignore
echo '*.pem' >> .gitignore
echo 'secrets/' >> .gitignore
Приложение читает переменные из окружения, а не из кода. Минус: файл лежит в открытом виде, хоть и с правами 600.
Уровень 2: systemd credentials
systemd умеет подавать секреты сервису так, что они видны только ему и не торчат в окружении процесса (где их читает /proc/PID/environ). В unit-файле:
[Service]
LoadCredential=db_pass:/etc/myapp/db_pass
ExecStart=/usr/bin/myapp
# внутри сервиса секрет доступен как файл:
# $CREDENTIALS_DIRECTORY/db_pass
Плюс подхода: секрет доступен сервису как файл в каталоге $CREDENTIALS_DIRECTORY, но не наследуется дочерними процессами и не виден в общем окружении, что закрывает частую утечку через /proc. Ещё лучше — зашифрованные credentials, которые расшифровываются только на этом хосте:
systemd-creds encrypt --name=db_pass plaintext.txt /etc/myapp/db_pass.cred
# в unit:
# LoadCredentialEncrypted=db_pass:/etc/myapp/db_pass.cred
Уровень 3: sops для секретов в git
Иногда секреты нужно версионировать вместе с конфигами. sops (от Mozilla) шифрует значения в YAML/JSON, оставляя ключи читаемыми — можно спокойно коммитить. Шифрование через age:
apt install -y age
age-keygen -o ~/.age-key.txt # запомните публичный ключ из вывода
# устанавливаем sops (бинарь с GitHub releases)
export SOPS_AGE_KEY_FILE=~/.age-key.txt
sops --age <public_key> -e -i secrets.yaml
Теперь secrets.yaml в git содержит только шифротекст, а расшифровать может лишь владелец ключа: sops -d secrets.yaml. Ключ age храните вне репозитория и в бэкапе.
Уровень 4: HashiCorp Vault
Для нескольких сервисов и команды нужен централизованный секрет-менеджер. Vault хранит секреты зашифрованно, выдаёт их по токенам с политиками, ведёт аудит и умеет динамические секреты (временные креды к БД). Быстрый старт в dev-режиме для знакомства:
# бинарь vault с сайта HashiCorp
vault server -dev
export VAULT_ADDR='http://127.0.0.1:8200'
vault kv put secret/myapp db_password=супер-секрет
vault kv get secret/myapp
Важно: dev-режим держит всё в памяти и не для прода. В бою запускают Vault с постоянным хранилищем, TLS и auto-unseal. Зато вы получаете ротацию, аудит и выдачу секретов «по запросу» без вечных паролей в файлах.
Что выбрать и где это крутить
Не усложняйте раньше времени: для одного приложения хватит .env с правами 600 плюс systemd credentials. Секреты в git — sops. Много сервисов и команда — Vault. Главное — секреты вне кода, вне истории и с минимальными правами.
Любой из вариантов требует своего сервера с root-доступом — на shared-хостинге ни Vault, ни systemd credentials не поднять. VPS MAATRIX даёт полный контроль на AMD EPYC + NVMe от $8/мес: ставите Vault или sops, шифруете секреты, а ежедневные бэкапы страхуют от потери ключей. Локации UK, США и РФ, root-доступ, оплата картой РФ, СБП, криптой или токеном MAAT — зарубежный сервер, доступный из России.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS для своих сервисовОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Достаточно ли просто .env с chmod 600?
Для одного небольшого проекта — да, это уже сильно лучше секретов в коде. Для нескольких сервисов и команды переходите на systemd credentials, sops или Vault.
Vault не избыточен для маленького проекта?
Да, для одного приложения Vault — перебор. Он окупается, когда секретов много, есть команда и нужны аудит, ротация и динамические креды.
Как проверить, что секреты не утекли в git?
Прогоните репозиторий через gitleaks или trufflehog — они находят ключи и токены в истории коммитов. При находке ротируйте секрет и чистите историю.