---
title: 'HashiCorp Vault: безопасное хранение секретов на VPS | Zomro'
description: ''
image: 'https://cdn.zomro.com/uploads/blog/a48%40server-panel.net/2026/05/31/image_2U9iefJ_q50.jpg'
---

![opened image]()

  * [Zomro](https://zomro.com/rus/)
  * [FAQ](https://zomro.com/rus/blog/faq/)
  * HashiCorp Vault: безопасное хранение секретов на VPS 



# HashiCorp Vault: безопасное хранение секретов на VPS

21-05-2026

![](https://cdn.zomro.com/uploads/blog/a48%40server-panel.net/2026/05/31/image_2U9iefJ_q50.jpg)

Хранить пароли базы данных, API-ключи и токены в `.env`-файлах на сервере - плохая практика. При компрометации сервера или случайном попадании файла в git все секреты утекают сразу. HashiCorp Vault решает эту задачу: секреты хранятся зашифрованными, доступ управляется через политики, каждое чтение секрета логируется. Разберём установку через Docker, инициализацию и интеграцию с приложениями.

## Почему Vault, а не просто зашифрованный файл

Зашифрованный файл требует ключа для расшифровки - и этот ключ где-то нужно хранить. Vault решает проблему иначе:

  * Секреты зашифрованы ключами, которые никогда не хранятся на диске в открытом виде

  * Доступ к секретам управляется через токены и политики

  * Каждый доступ к секрету записывается в audit log

  * Поддерживается ротация секретов без перезапуска приложений

  * Секреты могут генерироваться динамически (временные credentials для БД)




Vault 1.16 - актуальная версия на момент написания статьи.

## 

## 

## Установка через Docker

На VPS с Ubuntu 24.04 самый простой способ развернуть Vault - Docker.
    
    
    # Установка Docker, если ещё нет
    curl -fsSL https://get.docker.com | bash
    
    # Создаём директории
    mkdir -p /opt/vault/{config,data,logs}

Конфиг Vault `/opt/vault/config/vault.hcl`:
    
    
    storage "file" {
      path = "/vault/data"
    }
    
    listener "tcp" {
      address     = "0.0.0.0:8200"
      tls_disable = "true"
    }
    
    api_addr = "http://127.0.0.1:8200"
    cluster_addr = "http://127.0.0.1:8201"
    
    ui = true

Запуск через Docker:
    
    
    docker run -d \
      --name vault \
      --cap-add=IPC_LOCK \
      -p 127.0.0.1:8200:8200 \
      -v /opt/vault/config:/vault/config \
      -v /opt/vault/data:/vault/data \
      -v /opt/vault/logs:/vault/logs \
      --restart unless-stopped \
      hashicorp/vault:1.16 vault server -config=/vault/config/vault.hcl
    
    docker ps | grep vault

Флаг `--cap-add=IPC_LOCK` нужен, чтобы Vault мог блокировать память и предотвращать запись секретов в swap.

![](https://cdn.zomro.com/uploads/blog/a48%40server-panel.net/2026/05/31/image_hZAleh9_q50.jpg)

## 

## 

## Инициализация Vault

При первом запуске Vault находится в состоянии "sealed" (запечатан) - его нужно инициализировать.
    
    
    # Устанавливаем переменную окружения
    export VAULT_ADDR='http://127.0.0.1:8200'
    
    # Инициализация: создаём 5 ключей, нужно 3 для unseal
    docker exec vault vault operator init -key-shares=5 -key-threshold=3

Вывод будет выглядеть примерно так:
    
    
    Unseal Key 1: abc123...
    Unseal Key 2: def456...
    Unseal Key 3: ghi789...
    Unseal Key 4: jkl012...
    Unseal Key 5: mno345...
    
    Initial Root Token: hvs.CAESIJK...

**Сохраните unseal-ключи и root token в надёжном месте.** Без 3 из 5 ключей данные восстановить невозможно. В реальных проектах ключи распределяют по разным людям или сохраняют в разных хранилищах.

## 

## 

## Unseal - разблокировка

После каждого рестарта Vault запечатан. Для разблокировки вводим 3 из 5 ключей:
    
    
    docker exec -it vault vault operator unseal abc123...
    docker exec -it vault vault operator unseal def456...
    docker exec -it vault vault operator unseal ghi789...
    
    # Проверяем статус
    docker exec vault vault status

Статус после успешного unseal:
    
    
    Key             Value
    ---             -----
    Seal Type       shamir
    Initialized     true
    Sealed          false
    Total Shares    5
    Threshold       3
    Version         1.16.0
    HA Enabled      false

Автоматический unseal через переменные окружения (для разработки - не для продакшена!):
    
    
    # В docker-compose.yml
    environment:
      - VAULT_DEV_ROOT_TOKEN_ID=myroot
      - VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200

В dev-режиме (`vault server -dev`) unseal не нужен, но данные хранятся только в памяти.

## 

## 

## Работа с секретами KV

### Авторизация
    
    
    export VAULT_ADDR='http://127.0.0.1:8200'
    export VAULT_TOKEN='hvs.CAESIJK...'
    
    # Или через docker exec
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=hvs.CAESIJK... vault vault status

### 

### Включение KV secrets engine
    
    
    # KV v2 поддерживает версионирование секретов
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=$ROOT_TOKEN \
      vault vault secrets enable -path=secret kv-v2

### 

### Запись секретов
    
    
    # Записываем секреты для приложения
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=$ROOT_TOKEN \
      vault vault kv put secret/myapp/database \
        host="localhost" \
        port="5432" \
        name="myapp_db" \
        username="dbuser" \
        password="SuperSecretPass123"
    
    # Записываем API-ключи
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=$ROOT_TOKEN \
      vault vault kv put secret/myapp/api \
        stripe_key="sk_live_..." \
        sendgrid_key="SG...."

### 

### Чтение секретов
    
    
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=$ROOT_TOKEN \
      vault vault kv get secret/myapp/database
    
    # Только конкретное поле
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=$ROOT_TOKEN \
      vault vault kv get -field=password secret/myapp/database
    
    # JSON-вывод
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=$ROOT_TOKEN \
      vault vault kv get -format=json secret/myapp/database | jq .data.data

![](https://cdn.zomro.com/uploads/blog/a48%40server-panel.net/2026/05/31/image_UQjPf4x_q50.jpg)

## 

## 

## Политики доступа

Root token даёт полный доступ - для приложений создают ограниченные политики.

Создаём файл политики `/tmp/myapp-policy.hcl`:
    
    
    # Читать секреты конкретного приложения
    path "secret/data/myapp/*" {
      capabilities = ["read"]
    }
    
    # Просматривать список (не значения)
    path "secret/metadata/myapp/*" {
      capabilities = ["list"]
    }

Применяем политику:
    
    
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=$ROOT_TOKEN \
      vault vault policy write myapp-read /tmp/myapp-policy.hcl

Создаём токен с этой политикой:
    
    
    docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=$ROOT_TOKEN \
      vault vault token create -policy=myapp-read -ttl=720h
    
    # Вывод:
    # token    hvs.CAESIHab...
    # token_ttl 720h

Этот токен передаётся приложению. Он может только читать секреты из `secret/data/myapp/` \- ничего больше.

## 

## 

## Интеграция с приложениями

### Через переменные окружения (bash-скрипт)

Создаём `/opt/myapp/load-secrets.sh`:
    
    
    #!/bin/bash
    export VAULT_ADDR='http://127.0.0.1:8200'
    export VAULT_TOKEN='hvs.CAESIHab...'
    
    # Получаем секреты и экспортируем
    DB_CREDS=$(vault kv get -format=json secret/myapp/database | jq -r '.data.data')
    
    export DB_HOST=$(echo $DB_CREDS | jq -r '.host')
    export DB_PASSWORD=$(echo $DB_CREDS | jq -r '.password')
    export DB_NAME=$(echo $DB_CREDS | jq -r '.name')
    
    # Запускаем приложение с переменными
    exec "$@"

Использование:
    
    
    chmod +x /opt/myapp/load-secrets.sh
    /opt/myapp/load-secrets.sh node /opt/myapp/server.js

### 

### Через HTTP API

Любое приложение может получить секреты через REST API:
    
    
    curl -s \
      -H "X-Vault-Token: hvs.CAESIHab..." \
      http://127.0.0.1:8200/v1/secret/data/myapp/database | jq .data.data

### 

### Python-пример
    
    
    import hvac
    import os
    
    client = hvac.Client(
        url='http://127.0.0.1:8200',
        token=os.environ['VAULT_TOKEN']
    )
    
    secret = client.secrets.kv.v2.read_secret_version(
        path='myapp/database',
        mount_point='secret'
    )
    
    db_password = secret['data']['data']['password']
    db_host = secret['data']['data']['host']

### 

### Node.js-пример
    
    
    const fetch = require('node-fetch');
    
    async function getSecret(path) {
      const response = await fetch(`http://127.0.0.1:8200/v1/secret/data/${path}`, {
        headers: { 'X-Vault-Token': process.env.VAULT_TOKEN }
      });
      const data = await response.json();
      return data.data.data;
    }
    
    const dbCreds = await getSecret('myapp/database');

## 

## 

## Версионирование секретов KV v2

KV v2 хранит историю изменений:
    
    
    # Получить версию 2
    vault kv get -version=2 secret/myapp/database
    
    # Список версий
    vault kv metadata get secret/myapp/database
    
    # Откатить к версии 1
    vault kv rollback -version=1 secret/myapp/database

## 

## 

## Автоматический unseal через systemd

Для автоматического запуска после перезагрузки без ручного unseal используют Transit auto-unseal или AWS KMS. Простой вариант для одиночного сервера - скрипт с ключами (не самый безопасный, но практичный):
    
    
    cat > /opt/vault/unseal.sh << 'EOF'
    #!/bin/bash
    export VAULT_ADDR='http://127.0.0.1:8200'
    sleep 5  # ждём запуска контейнера
    vault operator unseal KEY1
    vault operator unseal KEY2
    vault operator unseal KEY3
    EOF
    chmod 600 /opt/vault/unseal.sh

Защитите этот файл - только root должен иметь к нему доступ.

## 

## 

## Мониторинг и аудит

Включение audit log:
    
    
    vault audit enable file file_path=/vault/logs/audit.log

Просмотр кто что читал:
    
    
    cat /opt/vault/logs/audit.log | jq 'select(.type=="response") | {time: .time, path: .request.path, client: .request.remote_address}'

![](https://cdn.zomro.com/uploads/blog/a48%40server-panel.net/2026/05/31/image_00vSha1_q50.jpg)

## 

## 

## Итог

Vault решает задачу управления секретами через три механизма: хранилище с шифрованием, политики доступа по токенам и полный audit trail. Для небольшого VPS достаточно KV v2 через Docker с file-хранилищем. Главное - сразу создавать отдельные токены для каждого приложения с минимально необходимыми правами, а root token использовать только для администрирования. Регулярно ротируйте application-токены командой `vault token renew` или создавайте новые.

Похожие статьи

[Как установить PHP 8.4, 7.4 и другие на Debian 13](https://zomro.com/rus/blog/faq/654-how-to-install-php-84-74-and-others-on-debian-13) [Что такое SSL‑сертификат и как он работает](https://zomro.com/rus/blog/faq/680-what-is-an-ssl-certificate-and-how-does-it-work) [ISP: Как привязать DNS-хостинг к панели ISPmanager](https://zomro.com/rus/blog/faq/100-isp-kak-privjazat-dns-hosting-k-paneli-ispmanager) [Как добавить правило в Брандмауэр Windows Server 2012, 2016, 2019](https://zomro.com/rus/blog/faq/273-kak-dobavit-pravilo-v-brandmaujer-windows-server-2012-2016-2019) [Как создать пользователя и добавить домен в панель HestiaCP?](https://zomro.com/rus/blog/faq/247-kak-sozdat-polzovatelja-i-dobavit-domen-v-panel-hestiacp)

[ Сервер для Forex от €7.95/мес ](/rus/server-for-forex)
