bolt Valebyte VPS від $4/міс — NVMe, запуск за 60 секунд.

Отримати VPS arrow_forward
eco Початковий Туторіал

Розгортання OpenBao на VPS: керування секретами, TLS, AppRole та резервне копіювання

calendar_month Oct 02, 2026 schedule 21 хв. читання visibility 82 переглядів
Развёртывание OpenBao на VPS: управление секретами, TLS, AppRole и резервное копирование
info

Потрібен сервер для цього гайду? Ми пропонуємо виділені сервери та VPS у 50+ країнах з миттєвим налаштуванням.

Потрібен сервер для цього гайду?

Розгорніть VPS або виділений сервер за хвилини.

Розгортання OpenBao на VPS: керування секретами, TLS, AppRole і резервне копіювання

TL;DR

У цьому посібнику ми розгорнемо OpenBao на Ubuntu 24.04 LTS, увімкнемо сховище Raft, захистимо вебінтерфейс і API через HTTPS, створимо політику та роль AppRole для застосунку, а потім налаштуємо автоматичні зашифровані резервні копії знімків Raft.

  • OpenBao працюватиме як systemd-сервіс з окремим системним користувачем.
  • Дані зберігатимуться у вбудованому Raft Storage без окремої бази даних.
  • Публічний доступ до API буде організовано через Caddy і TLS-сертифікат Let’s Encrypt.
  • Застосунки отримуватимуть секрети через AppRole з мінімально необхідними правами.
  • Знімки сховища регулярно вивантажуватимуться до зовнішнього S3-сумісного бакета через restic.
  • Усі операції перевіряються командами OpenBao CLI, curl і systemctl.

1. TL;DR

У цьому посібнику ми розгорнемо OpenBao на Ubuntu 24.04 LTS, увімкнемо сховище Raft, захистимо вебінтерфейс і API через HTTPS, створимо політику та роль AppRole для застосунку, а потім налаштуємо автоматичні зашифровані резервні копії знімків Raft.

  • OpenBao працюватиме як systemd-сервіс з окремим системним користувачем.
  • Дані зберігатимуться у вбудованому Raft Storage без окремої бази даних.
  • Публічний доступ до API буде організовано через Caddy і TLS-сертифікат Let’s Encrypt.
  • Застосунки отримуватимуть секрети через AppRole з мінімально необхідними правами.
  • Знімки сховища регулярно вивантажуватимуться до зовнішнього S3-сумісного бакета через restic.
  • Усі операції перевіряються командами OpenBao CLI, curl і systemctl.

2. Зміст

Стаття розрахована на адміністратора, який розгортає власне сховище секретів для невеликого SaaS, CI/CD, внутрішніх сервісів або домашньої інфраструктури. Команди наведено для Ubuntu 24.04 LTS і архітектури amd64.

У прикладі використовується один вузол OpenBao. Це не кластер високої доступності: у разі відмови VPS сервіс буде недоступний до відновлення машини, але дані можна відновити зі знімка Raft. Для критично важливої production-інфраструктури наприкінці статті розглянуто варіанти масштабування.

3. Що ми налаштовуємо і навіщо

Схема: 3. Что мы настраиваем и зачем
Схема: 3. Що ми налаштовуємо і навіщо

Проблема із секретами у конфігураційних файлах

Паролі баз даних, API-токени, ключі хмарних провайдерів і сертифікати часто потрапляють до Git, Docker Compose, змінних CI або резервних копій серверів. Навіть якщо секрет видалити з останнього коміту, він залишиться в історії репозиторію. Додаткова проблема — відсутність аудиту: зазвичай незрозуміло, який застосунок, коли і який секрет прочитав.

OpenBao вирішує це завдання як централізоване сховище секретів із контролем доступу. Секрети зберігаються всередині storage backend, а клієнт спочатку проходить автентифікацію, після чого отримує лише дозволені шляхи. OpenBao сумісний зі звичною моделлю API і CLI Vault, але розвивається як незалежний проєкт з відкритою ліцензією.

Архітектура нашого прикладу

Компонент Призначення Адреса
OpenBao Сховище секретів і API 127.0.0.1:8200
Raft Storage Зберігання даних і журналу консенсусу /opt/openbao/data
Caddy HTTPS, сертифікат, reverse proxy https://bao.example.com
AppRole Автентифікація машин і застосунків role_id і secret_id
restic Шифрування та надсилання резервних копій S3-сумісне сховище

Що вийде в результаті

Після виконання інструкції буде створено один OpenBao-вузол із KV v2 secrets engine. До нього можна записувати, наприклад, database/password або production/api-key. Застосунок входитиме через AppRole, отримуватиме короткоживучий токен і читатиме лише потрібний шлях.

Ззовні буде доступний лише TCP-порт 443. Порт OpenBao 8200 залишиться закритим для зовнішньої мережі, оскільки API буде доступний локально через Caddy. SSH дозволяється лише з адміністративної IP-адреси або через VPN.

Self-hosted або cloud-managed

Керовані сервіси секретів зручні: провайдер відповідає за оновлення, відмовостійкість і частину резервного копіювання. Їхні недоліки — вартість, залежність від зовнішньої платформи, обмеження за регіоном і необхідність довіряти постачальнику критично важливу інформацію.

Self-hosted OpenBao на VPS підходить, якщо потрібно контролювати розташування даних, використовувати власні процедури відновлення або скоротити постійні витрати. Натомість адміністратор сам відповідає за патчі, TLS, моніторинг, резервні копії та процедуру відновлення. Один VPS не можна вважати заміною повноцінному відмовостійкому кластеру.

Що важливо знати про seal і unseal

Під час ініціалізації OpenBao створює root token і ключі unseal. У production не можна зберігати їх у файлі на сервері. Для лабораторного прикладу використовується класична схема Shamir із п’ятьма ключами та порогом три: для розпечатування потрібні будь-які три ключі.

Втрата root token не знищує дані, але ускладнює адміністрування. Втрата достатньої кількості unseal-ключів унеможливлює розшифрування сховища. Ключі необхідно розподілити між довіреними адміністраторами та зберігати офлайн, наприклад у менеджері паролів і в зашифрованому фізичному резерві.

4. Яка VPS-конфігурація потрібна для цього завдання

Схема: 4. Какой VPS-конфиг нужен под эту задачу
Схема: 4. Яка VPS-конфігурація потрібна для цього завдання

OpenBao не потребує великої кількості CPU, якщо кількість запитів невелика. Головні вимоги — стабільний диск, достатній обсяг оперативної пам’яті та регулярні знімки. Для одного вузла важливіші надійність зберігання й наявність віддаленого backup, ніж десятки віртуальних ядер.

Сценарій CPU RAM Диск Мережа
Лабораторія 1 vCPU 1 ГБ 20 ГБ SSD 100 Мбіт/с
Невелика production-інсталяція 2 vCPU 2–4 ГБ 40–80 ГБ SSD/NVMe 100–1000 Мбіт/с
Кілька команд і CI/CD 4 vCPU 8 ГБ 100 ГБ NVMe 1 Гбіт/с

Практичний базовий варіант — 2 vCPU, 4 ГБ RAM, 60 ГБ SSD, публічний IPv4 або доступний IPv6, приватна мережа за наявності кількох вузлів і щоденні snapshots диска. Для цієї конфігурації можна взяти підходящий VPS з SSD, статичною IP-адресою та можливістю підключити зовнішній S3-бекап.

20 ГБ диска достатньо лише для невеликої кількості секретів і журналів. Сам OpenBao зберігає секрети в компактному вигляді, але робочий каталог Raft, системні логи та тимчасові файли все одно потребують запасу. Не слід використовувати переповнений диск: за нестачі місця запис до Raft може зупинитися.

Коли потрібен dedicated

Виділений сервер виправданий, якщо OpenBao обслуговує тисячі застосунків, зберігає великий обсяг динамічних секретів, працює разом із кількома важкими сервісами або потребує передбачуваної продуктивності диска. Dedicated також корисний за суворих вимог до фізичної ізоляції та локального контролю обладнання.

Для одного невеликого екземпляра OpenBao dedicated зазвичай надмірний. Раціональніше витратити бюджет на три VPS у різних зонах, зовнішнє резервне сховище, моніторинг і тестування відновлення. Важливо не плутати виділений сервер із кластером: один dedicated залишається однією точкою відмови.

Вплив локації

Локація впливає на затримку між застосунками та API OpenBao, вимоги до локалізації даних і час відновлення. Розміщуйте OpenBao ближче до застосунків, які звертаються до нього під час старту або регулярно отримують короткоживучі токени. Резервний S3-бакет бажано тримати в іншому відмовостійкому регіоні.

Якщо використовуються три вузли Raft, затримка між ними має бути невеликою та стабільною. Для кластера краще обирати один регіональний майданчик із кількома зонами доступності, а не розтягувати консенсус через континенти.

5. Підготовка сервера

Схема: 5. Підготовка сервера
Схема: 5. Підготовка сервера

Нижче передбачається чистий Ubuntu Server 24.04 LTS із доступом через SSH під користувачем, створеним провайдером. Замініть 203.0.113.10, admin і bao.example.com на власні значення. Усі команди виконуються від адміністративного користувача з правами sudo.

Створення адміністратора та SSH-ключа

Якщо у вас уже є окремий sudo-користувач, цей крок можна пропустити. Не закривайте поточну SSH-сесію, доки не перевірите новий вхід в окремому вікні.

# Створюємо окремого користувача для адміністрування
sudo adduser ops

# Додаємо користувача до групи sudo
sudo usermod -aG sudo ops

# Створюємо каталог для публічного ключа
sudo install -d -m 700 -o ops -g ops /home/ops/.ssh

# Копіюємо ключ поточного користувача до нового облікового запису
sudo cp ~/.ssh/authorized_keys /home/ops/.ssh/authorized_keys

# Виправляємо власника та права файлу ключів
sudo chown ops:ops /home/ops/.ssh/authorized_keys
sudo chmod 600 /home/ops/.ssh/authorized_keys

Перевірте вхід у новому терміналі:

# Підключаємося з локального комп’ютера та перевіряємо sudo
ssh [email protected]
sudo -v
whoami

Оновлення системи та базові утиліти

# Оновлюємо індекси пакетів і встановлюємо виправлення
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt full-upgrade -y

# Встановлюємо інструменти для інсталяції та діагностики
sudo apt install -y curl unzip jq ca-certificates gnupg lsb-release \
  ufw fail2ban chrony unattended-upgrades restic awscli

# Перезавантажуємо сервер, якщо оновилося ядро
sudo reboot

Після перезавантаження знову підключіться через SSH. Увімкніть автоматичне встановлення security-оновлень. Перезапуск OpenBao після оновлення має виконуватися в заздалегідь вибране вікно обслуговування.

# Увімкнюємо автоматичні оновлення безпеки Ubuntu
sudo dpkg-reconfigure -plow unattended-upgrades

# Перевіряємо синхронізацію часу
timedatectl status
chronyc tracking

Налаштування SSH

Вимикайте вхід за паролем лише після перевірки авторизації ключем. Для публічного сервера також забороняється вхід root. Порт SSH можна змінити, але це не замінює ключову автентифікацію та firewall.

# Створюємо окремий drop-in для sshd
sudo tee /etc/ssh/sshd_config.d/ hardening.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
AllowUsers ops
EOF

# Перевіряємо синтаксис конфігурації SSH
sudo sshd -t

# Застосовуємо налаштування без завершення поточних сесій
sudo systemctl reload ssh

Firewall і fail2ban

Відкрийте SSH лише з вашої адміністративної IP-адреси, якщо вона статична. Якщо адреса змінюється, дозвольте SSH із довіреної мережі або використовуйте VPN. Порт 8200 навмисно не відкривається: Caddy звертатиметься до OpenBao локально.

# Дозволяємо SSH лише з адміністративного IPv4
sudo ufw allow from 198.51.100.25 to any port 22 proto tcp

# Відкриваємо публічний HTTPS і тимчасово HTTP для отримання сертифіката
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Увімкнюємо firewall із політикою deny за замовчуванням
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable

# Перевіряємо активні правила
sudo ufw status verbose

Увімкніть jail для SSH. Якщо SSH доступний лише через VPN, вкажіть підмережу VPN у списку trusted IP.

# Увімкнюємо та запускаємо захист SSH
sudo systemctl enable --now fail2ban

# Перевіряємо стан jail sshd
sudo fail2ban-client status sshd

6. Встановлення ПЗ — покроково

Схема: 6. Встановлення ПЗ — покроково
Схема: 6. Встановлення ПЗ — покроково

У прикладі використовується OpenBao 2.2.x, системна служба systemd, Caddy 2.10.x і restic 0.18.x. Перед production-встановленням перевірте актуальний стабільний реліз на офіційній сторінці OpenBao та зафіксуйте конкретну версію. Не можна використовувати URL із плаваючим словом latest в автоматичному скрипті оновлення.

Крок 1. Створення системного користувача

# Створюємо користувача без shell для процесу OpenBao
sudo useradd --system --home /etc/openbao --shell /usr/sbin/nologin openbao

# Створюємо каталоги конфігурації, даних і TLS
sudo install -d -o openbao -g openbao -m 750 /etc/openbao
sudo install -d -o openbao -g openbao -m 750 /opt/openbao/data
sudo install -d -o openbao -g openbao -m 750 /etc/openbao/tls

Крок 2. Завантаження OpenBao

Нижче показано приклад для amd64. Для ARM64 замініть amd64 на arm64. Версія має бути однаковою на всіх вузлах кластера. Після завантаження рекомендується звірити SHA256 з контрольною сумою з офіційного релізу.

# Фіксуємо версію, щоб оновлення були контрольованими
export OPENBAO_VERSION=2.2.0

# Завантажуємо офіційний архів OpenBao для Linux amd64
curl -fL -o /tmp/openbao.zip \
  "https://github.com/openbao/openbao/releases/download/v${OPENBAO_VERSION}/openbao_${OPENBAO_VERSION}_linux_amd64.zip"

# Розпаковуємо бінарний файл до каталогу системних програм
sudo unzip -o /tmp/openbao.zip -d /usr/local/bin

# Призначаємо власника та безпечні права на бінарний файл
sudo chown root:root /usr/local/bin/openbao
sudo chmod 0755 /usr/local/bin/openbao

# Перевіряємо встановлену версію
openbao version

Якщо в релізі використовується інший шаблон назви архіву, візьміть точну назву asset зі сторінки релізу. Не підміняйте офіційний бінарний файл збіркою невідомого походження.

Крок 3. Встановлення Caddy

Caddy автоматично отримує та продовжує сертифікати Let’s Encrypt. Для цього DNS-ім’я має вказувати на публічний IPv4 або IPv6 сервера, а порти 80 і 443 мають бути доступні з Інтернету.

# Додаємо ключ офіційного репозиторію Caddy
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
  | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

# Додаємо репозиторій Caddy для Ubuntu
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
  | sudo tee /etc/apt/sources.list.d/caddy-stable.list

# Встановлюємо Caddy 2.x і перевіряємо його стан
sudo apt update
sudo apt install -y caddy
sudo systemctl enable --now caddy
caddy version

Крок 4. Встановлення systemd unit

# Створюємо службу OpenBao з окремим користувачем і обмеженнями systemd
sudo tee /etc/systemd/system/openbao.service > /dev/null <<'EOF'
[Unit]
Description=OpenBao secrets management server
Documentation=https://openbao.org/docs/
After=network-online.target
Wants=network-online.target

[Service]
User=openbao
Group=openbao
ExecStart=/usr/local/bin/openbao server -config=/etc/openbao/openbao.hcl
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
AmbientCapabilities=CAP_IPC_LOCK
CapabilityBoundingSet=CAP_IPC_LOCK
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
ReadWritePaths=/opt/openbao/data

[Install]
WantedBy=multi-user.target
EOF

# Перечитуємо unit-файли systemd
sudo systemctl daemon-reload

Крок 5. Встановлення CLI-змінних

# Створюємо локальний профіль для адміністратора OpenBao
tee -a ~/.profile > /dev/null <<'EOF'
export BAO_ADDR='https://bao.example.com'
EOF

# Завантажуємо змінну до поточної оболонки
source ~/.profile

# Перевіряємо, що CLI встановлено та доступно
openbao version

Команда openbao є основним CLI. У старих скриптах може траплятися команда vault; не змішуйте бінарні файли та змінні середовища без перевірки сумісності.

7. Конфігурація

Схема: 7. Конфігурація
Схема: 7. Конфігурація

Конфігурація OpenBao та Raft

Спочатку створюємо конфігурацію. OpenBao прослуховує лише loopback через HTTP, а TLS завершується на Caddy. Це допустимий варіант, оскільки трафік між двома процесами не залишає сервер. Якщо між reverse proxy та OpenBao є окрема мережа або інший хост, внутрішній TLS є обов’язковим.

# Створюємо конфігурацію OpenBao з Raft Storage та локальним listener
sudo tee /etc/openbao/openbao.hcl > /dev/null <<'EOF'
ui = true
disable_mlock = true

storage "raft" {
  path    = "/opt/openbao/data"
  node_id = "bao-1"
}

listener "tcp" {
  address         = "127.0.0.1:8200"
  cluster_address = "127.0.0.1:8201"
  tls_disable     = true
}

api_addr     = "https://bao.example.com"
cluster_addr = "http://127.0.0.1:8201"

telemetry {
  disable_hostname = true
  prometheus_retention_time = "24h"
}
EOF

# Призначаємо конфігурації власника та закриті права
sudo chown openbao:openbao /etc/openbao/openbao.hcl
sudo chmod 640 /etc/openbao/openbao.hcl

# Перевіряємо конфігурацію без запуску сервера
sudo -u openbao /usr/local/bin/openbao operator validate-config /etc/openbao/openbao.hcl

# Запускаємо OpenBao та додаємо його до автозавантаження
sudo systemctl enable --now openbao

# Переглядаємо останні повідомлення служби
sudo systemctl status openbao --no-pager
sudo journalctl -u openbao -n 50 --no-pager

Reverse proxy та HTTPS через Caddy

Замініть домен на власне DNS-ім’я. Електронну адресу можна вказати в глобальному блоці Caddy для сповіщень про сертифікати. Поки DNS не вказує на сервер, Caddy не зможе отримати сертифікат.

# Налаштовуємо HTTPS reverse proxy для OpenBao
sudo tee /etc/caddy/Caddyfile > /dev/null <<'EOF'
{
    email [email protected]
}

bao.example.com {
    encode gzip

    reverse_proxy 127.0.0.1:8200 {
        header_up X-Forwarded-Proto {scheme}
        header_up X-Forwarded-Host {host}
    }

    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        X-Content-Type-Options "nosniff"
        Referrer-Policy "no-referrer"
    }
}
EOF

# Перевіряємо синтаксис Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile

# Перезчитуємо конфігурацію без зупинки Caddy
sudo systemctl reload caddy

# Перевіряємо HTTPS-заголовки та відповідь API
curl -I https://bao.example.com/v1/sys/health

Код відповіді health endpoint залежить від стану OpenBao. Для неініціалізованого або запечатаного сервера часто повертається HTTP 501 або 503, що не означає несправність reverse proxy. Важливо побачити коректний TLS-сертифікат і JSON-відповідь від OpenBao.

Ініціалізація сховища

Ініціалізацію виконують один раз. Результат команди містить unseal-ключі та initial root token. Не записуйте вивід в історію shell, чат, тікети або звичайний файл на сервері. Запустіть команду з локального адміністратора, який має зашифроване місце для зберігання результату.

# Перевіряємо стан до ініціалізації
openbao status

# Ініціалізуємо Raft із п’ятьма ключами та порогом три
openbao operator init -key-shares=5 -key-threshold=3

Збережіть п’ять ключів у різних довірених адміністраторів. Далі розпечатайте сервер, передавши три ключі в інтерактивному режимі. Не передавайте ключі через аргументи командного рядка: вони можуть потрапити в історію або список процесів.

# Вводимо перший unseal key інтерактивно
openbao operator unseal

# Повторюємо ще для двох різних ключів
openbao operator unseal
openbao operator unseal

# Перевіряємо, що сховище розпечатано
openbao status

Авторизуйтеся за допомогою initial root token лише в адміністративній сесії. Після створення постійних адміністративних політик root token слід прибрати до офлайн-сховища та не використовувати для застосунків.

KV v2 та політика доступу

KV v2 зберігає версії секретів і підтримує читання, запис, видалення та відновлення версій. Увімкнемо secrets engine за шляхом secret/, потім створимо застосунок із доступом лише до secret/data/myapp/.

# Експортуємо root token лише в поточну оболонку
read -rsp "OpenBao root token: " BAO_TOKEN
export BAO_TOKEN
echo

# Увімкнемо KV v2 за шляхом secret/
openbao secrets enable -path=secret kv-v2

# Записуємо тестовий секрет
openbao kv put secret/myapp/config \
  DB_HOST="127.0.0.1" \
  DB_NAME="appdb" \
  API_ENDPOINT="https://api.example.com"

# Перевіряємо читання секрету
openbao kv get secret/myapp/config

Створіть policy-файл. Для KV v2 шлях API містить data, а CLI приховує цю деталь. Дозвіл list не надає читання значень, але його слід видавати лише там, де застосунку справді потрібен список ключів.

# Створюємо мінімальну політику для застосунку
sudo tee /tmp/myapp-policy.hcl > /dev/null <<'EOF'
path "secret/data/myapp/" {
  capabilities = ["read"]
}

path "secret/metadata/myapp/" {
  capabilities = ["list"]
}
EOF

# Завантажуємо policy в OpenBao
openbao policy write myapp-readonly /tmp/myapp-policy.hcl

# Видаляємо тимчасовий файл із політикою
shred -u /tmp/myapp-policy.hcl

AppRole для застосунку

AppRole призначений для машинної автентифікації. role_id можна вважати ідентифікатором ролі, а secret_id — секретом, який має зберігатися в захищеному deployment-секреті. Встановимо короткий час життя токена та обмежимо кількість його використань.

# Увімкнемо метод автентифікації AppRole
openbao auth enable approle

# Створюємо роль з обмеженим TTL та політикою читання
openbao write auth/approle/role/myapp \
  token_policies="myapp-readonly" \
  token_ttl=1h \
  token_max_ttl=4h \
  secret_id_ttl=24h \
  secret_id_num_uses=2

# Отримуємо role_id, який можна передати в deployment-систему
openbao read -field=role_id auth/approle/role/myapp/role-id

# Генеруємо одноразовий secret_id
openbao write -field=secret_id -f \
  auth/approle/role/myapp/secret-id

Передайте два значення застосунку через захищений механізм CI/CD або секрети оркестратора. Не додавайте їх у Dockerfile, Git-репозиторій, systemd unit або загальнодоступний лог. Після тесту перевірте, що застосунок не може читати чужі шляхи.

# Виконуємо login через AppRole та отримуємо тимчасовий client_token
export ROLE_ID="replace-with-role-id"
export SECRET_ID="replace-with-secret-id"

export APP_TOKEN="$(
  curl -fsS \
    --request POST \
    --data "{\"role_id\":\"${ROLE_ID}\",\"secret_id\":\"${SECRET_ID}\"}" \
    https://bao.example.com/v1/auth/approle/login \
  | jq -r '.auth.client_token'
)"

# Читаємо дозволений секрет
curl -fsS \
  -H "X-OpenBao-Token: ${APP_TOKEN}" \
  https://bao.example.com/v1/secret/data/myapp/config | jq

# Перевіряємо відмову в доступі до чужого шляху
curl -sS -o /tmp/denied.json -w "%{http_code}\n" \
  -H "X-OpenBao-Token: ${APP_TOKEN}" \
  https://bao.example.com/v1/secret/data/other-app/config

Керування root token

Після перевірки AppRole не використовуйте root token для щоденних завдань. Створіть окрему адміністративну policy з обмеженими операціями та видайте персональний токен кожному оператору. Root token можна відкликати, а для аварійних дій генерувати новий recovery-процесом згідно з внутрішнім регламентом.

# Відкликаємо root token після завершення первинного налаштування
openbao token revoke "$BAO_TOKEN"

# Видаляємо токен із поточної оболонки
unset BAO_TOKEN

Перевірка працездатності

# Перевіряємо health endpoint через публічний HTTPS
curl -fsS https://bao.example.com/v1/sys/health | jq

# Перевіряємо стан Raft та sealed status
openbao status

# Перевіряємо, що порт 8200 не прослуховує зовнішню адресу
sudo ss -lntp | grep -E ':8200|:443'

# Перевіряємо стан обох служб
systemctl is-active openbao
systemctl is-active caddy

# Переглядаємо помилки за останні 15 хвилин
sudo journalctl -u openbao --since "15 minutes ago" -p warning
sudo journalctl -u caddy --since "15 minutes ago" -p warning

8. Резервні копії та обслуговування

Схема: 8. Резервні копії та обслуговування
Схема: 8. Резервні копії та обслуговування

Що необхідно резервувати

Основне джерело даних — знімок Raft. Він містить стан OpenBao, включно з KV-секретами, політиками та налаштуваннями auth methods. Додатково збережіть конфігурацію /etc/openbao/openbao.hcl, systemd unit, Caddyfile і процедуру відновлення.

Unseal-ключі та root token не слід включати до звичайного серверного backup. Вони мають зберігатися окремо та бути доступними кільком уповноваженим людям. Якщо зашифрувати backup ключем, який зберігається на тому самому VPS, втрата VPS знищить і дані, і ключ розшифрування.

Створення знімка Raft

Знімок виконується через API та не потребує зупинки OpenBao. Для backup-користувача створіть токен із правом read на endpoint snapshot. Цей токен не повинен мати адміністративних прав.

# Создаём каталог для временного snapshot
sudo install -d -o ops -g ops -m 700 /var/backups/openbao

# Создаём снимок Raft через локальный API
curl -fsS \
  -H "X-OpenBao-Token: ${BAO_BACKUP_TOKEN}" \
  https://bao.example.com/v1/sys/storage/raft/snapshot \
  -o /var/backups/openbao/raft-$(date -u +%Y%m%dT%H%M%SZ).snap

# Проверяем, что файл непустой
ls -lh /var/backups/openbao/

Точне право для snapshot endpoint залежить від версії OpenBao та використовуваного шляху. Перевірте policy API вашої версії перед видачею токена. Ніколи не робіть snapshot endpoint доступним без автентифікації.

Шифрування backup через restic і S3

Restic шифрує дані до надсилання в S3. Для production використовуйте окремий бакет, окремі access key з мінімальними правами та пароль restic із менеджера секретів. У прикладі змінні винесено у файл із правами 600; цей файл не повинен потрапляти до Git.

# Создаём каталог с параметрами резервного копирования
sudo install -d -o root -g root -m 700 /etc/openbao

# Сохраняем параметры только для root
sudo tee /etc/openbao/backup.env > /dev/null <<'EOF'
export AWS_ACCESS_KEY_ID='replace-me'
export AWS_SECRET_ACCESS_KEY='replace-me'
export RESTIC_REPOSITORY='s3:https://s3.example.net/openbao-prod'
export RESTIC_PASSWORD='replace-with-long-random-password'
export RESTIC_COMPRESSION='auto'
EOF

# Закрываем файл с секретами
sudo chmod 600 /etc/openbao/backup.env

# Инициализируем restic repository один раз
sudo bash -c 'source /etc/openbao/backup.env && restic init'

Для суворішої моделі зберігайте credentials у systemd credentials, окремому секретному сховищі або використовуйте IAM-роль, якщо VPS перебуває у сумісному хмарному середовищі. Не надсилайте до зовнішнього backup весь каталог даних Raft звичайним rsync: узгоджений snapshot безпечніший для відновлення.

Скрипт автоматичного backup

# Создаём скрипт backup-снимка и выгрузки в restic
sudo tee /usr/local/sbin/openbao-backup.sh > /dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077

source /etc/openbao/backup.env

tmpdir="$(mktemp -d /var/backups/openbao.XXXXXX)"
cleanup() {
    rm -rf "$tmpdir"
}
trap cleanup EXIT

snapshot="$tmpdir/raft.snap"
metadata="$tmpdir/metadata.txt"

curl --fail --silent --show-error \
    -H "X-OpenBao-Token: ${BAO_BACKUP_TOKEN}" \
    "https://bao.example.com/v1/sys/storage/raft/snapshot" \
    -o "$snapshot"

{
    date -u
    hostname
    openbao version
    sha256sum "$snapshot"
} > "$metadata"

restic backup "$snapshot" "$metadata" --tag openbao-raft

restic forget \
    --tag openbao-raft \
    --keep-daily 7 \
    --keep-weekly 4 \
    --keep-monthly 12 \
    --prune

restic check
EOF

# Разрешаем запуск только root
sudo chmod 700 /usr/local/sbin/openbao-backup.sh

# Добавляем backup token в защищённый environment-файл
sudo sh -c 'printf "\nexport BAO_BACKUP_TOKEN='\''replace-with-backup-token'\''\n" >> /etc/openbao/backup.env'
sudo chmod 600 /etc/openbao/backup.env

Команда restic check перевіряє цілісність структури репозиторію, але не замінює тестове відновлення. Перший запуск виконайте вручну та переконайтеся, що в S3 з’явилися зашифровані об’єкти.

systemd timer замість cron

# Создаём service unit для backup
sudo tee /etc/systemd/system/openbao-backup.service > /dev/null <<'EOF'
[Unit]
Description=OpenBao encrypted Raft backup
After=network-online.target openbao.service
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/openbao-backup.sh
User=root
EOF

# Создаём таймер ежедневного запуска в 03:15 UTC
sudo tee /etc/systemd/system/openbao-backup.timer > /dev/null <<'EOF'
[Unit]
Description=Daily OpenBao backup timer

[Timer]
OnCalendar=-- 03:15:00 UTC
Persistent=true
RandomizedDelaySec=15m

[Install]
WantedBy=timers.target
EOF

# Включаем таймер и проверяем расписание
sudo systemctl daemon-reload
sudo systemctl enable --now openbao-backup.timer
sudo systemctl start openbao-backup.service
sudo systemctl list-timers openbao-backup.timer
sudo journalctl -u openbao-backup.service -n 50 --no-pager

Перевірка відновлення

Відновлення слід тестувати на окремому тимчасовому VPS або ізольованому контейнері. Не можна перевіряти його поверх робочого production-сховища. Для відновлення потрібні чистий OpenBao тієї самої або сумісної версії, конфігурація Raft і snapshot.

# Получаем последний snapshot из restic в отдельный каталог
sudo mkdir -p /tmp/openbao-restore
sudo restic restore latest --tag openbao-raft \
  --target /tmp/openbao-restore

# Проверяем найденные файлы
find /tmp/openbao-restore -type f -maxdepth 5 -ls

Далі зупиніть тестовий OpenBao, замініть його порожнє Raft storage і виконайте restore через CLI або API відповідно до документації версії. Після відновлення перевірте unseal, читання тестового секрету, AppRole login і політики. Запишіть фактичний час відновлення та виправте процедуру, якщо вона потребує ручних дій, які ніхто не зможе виконати в аварійній ситуації.

Оновлення

Перед оновленням створіть свіжий Raft snapshot і збережіть поточну версію. Для одного вузла використовуйте maintenance window: зупиніть сервіс, замініть бінарний файл, запустіть OpenBao та перевірте health endpoint. Не видаляйте старий бінарник до успішної перевірки.

У кластері з трьох або п’яти вузлів оновлення виконується по одному вузлу з контролем quorum. Це не означає, що можна без перевірки змішувати будь-які версії: ознайомтеся з compatibility notes конкретного релізу. Після оновлення одного вузла перевірте стан Raft і лише потім переходьте до наступного.

# Перед обновлением сохраняем состояние и snapshot
openbao status
sudo systemctl start openbao-backup.service

# После замены бинарника перезапускаем сервис
sudo systemctl restart openbao

# Проверяем API, sealed status и последние ошибки
curl -fsS https://bao.example.com/v1/sys/health | jq
openbao status
sudo journalctl -u openbao -n 100 --no-pager

9. Усунення несправностей і FAQ

OpenBao відповідає помилкою «connection refused» на порту 8200

Спочатку перевірте стан процесу командою systemctl status openbao і журналом journalctl -u openbao -n 100. Потім виконайте ss -lntp | grep 8200: listener має бути на 127.0.0.1:8200. Якщо service завершився, найчастіше причина в помилці HCL, неправильному власнику каталогу Raft або зайнятому порту. Запустіть openbao operator validate-config і виправте знайдену проблему.

HTTPS повертає 502 Bad Gateway

Код 502 означає, що Caddy не може підключитися до upstream. Переконайтеся, що OpenBao запущений і слухає 127.0.0.1:8200, а в Caddyfile вказано саме цю адресу. Перевірте curl http://127.0.0.1:8200/v1/sys/health локально та журнал journalctl -u caddy. Після зміни конфігурації виконайте caddy validate, потім systemctl reload caddy.

Сертифікат Caddy не випускається

Перевірте DNS-записи A та AAAA: обидва мають вести на сервер, або видаліть помилковий AAAA-запис. Порти 80 і 443 мають бути відкриті в UFW і зовнішньому firewall провайдера. Перегляньте журнал journalctl -u caddy. Let’s Encrypt також обмежує частоту запитів, тому не слід багаторазово видаляти та створювати конфігурацію під час діагностики.

Після перезавантаження OpenBao знову sealed

За Shamir seal це нормальна поведінка: після запуску потрібно ввести встановлену кількість unseal-ключів. Автоматично зберігати ці ключі на тому самому сервері небезпечно. Введіть потрібну кількість ключів вручну або налаштуйте підтримуваний auto-unseal через зовнішній KMS/HSM. Переконайтеся, що ключі розподілені між адміністраторами та що процедуру unseal перевірено до аварії.

AppRole login повертає 400 або 403

Перевірте, що увімкнено шлях auth/approle, role_id належить правильній ролі, а secret_id не закінчився та не використаний дозволену кількість разів. Виконайте openbao read auth/approle/role/myapp адміністративним токеном і перевірте TTL. Якщо login успішний, але читання секрету повертає 403, перегляньте policy: для KV v2 потрібен шлях secret/data/..., а не лише secret/....

Яка VPS-конфігурація мінімально підійде?

Для лабораторії достатньо 1 vCPU, 1 ГБ RAM і 20 ГБ SSD, але це не найкращий production-варіант. Для невеликої робочої системи обирайте щонайменше 2 vCPU, 2–4 ГБ RAM, 40 ГБ SSD і стабільну статичну IP-адресу. Обов’язково додайте зовнішній backup. Якщо на тому самому VPS працюють CI runners, бази даних або reverse proxy для багатьох сервісів, збільште пам’ять до 8 ГБ або винесіть OpenBao на окрему машину.

Що обрати — VPS чи dedicated для цього завдання?

Для одного OpenBao-вузла та невеликої кількості застосунків VPS зазвичай раціональніший: ресурсів достатньо, а масштабування можна виконати додаванням вузлів. Dedicated потрібен за суворої фізичної ізоляції, високого навантаження, великої кількості сусідніх сервісів або вимог до передбачуваного диска. Однак dedicated сам по собі не забезпечує високої доступності. Для HA важливіші три вузли Raft і коректна мережа між ними.

Чи можна зберігати snapshot на тому самому VPS?

Локальна копія корисна для швидкого відновлення після помилкового видалення, але не захищає від відмови диска, компрометації сервера або видалення VPS. Використовуйте локальний snapshot як проміжний файл, а потім надсилайте його в окреме S3-сумісне сховище з шифруванням restic. Зберігайте кілька поколінь backup і періодично виконуйте тестове відновлення на окремій машині.

Чи потрібно відкривати порт 8200 в Інтернеті?

В описаній схемі — ні: OpenBao слухає лише loopback, а зовнішній доступ іде через Caddy по HTTPS. Це зменшує поверхню атаки та спрощує firewall. Порт 8200 потрібно відкрити лише між вузлами, якщо ви створите Raft-кластер; тоді обмежте доступ приватною мережею та налаштуйте внутрішній TLS. Не публікуйте API напряму без шифрування та контролю мережевого доступу.

Як зрозуміти, що резервне копіювання справді працює?

Перевірте успішний exit code systemd-сервісу, наявність нового snapshot у restic і дату останнього backup. Команда restic snapshots покаже збережені покоління, а restic check перевірить структуру репозиторію. Найнадійніша перевірка — відновити snapshot на тимчасовому вузлі, розпечатати OpenBao, прочитати тестовий секрет і перевірити вхід через AppRole. Backup без перевіреного restore не можна вважати робочим.

10. Висновки та наступні кроки

Схема: 10. Висновки та наступні кроки
Схема: 10. Висновки та наступні кроки

У результаті OpenBao працює на окремому VPS із Raft Storage, HTTPS через Caddy, машинною автентифікацією AppRole та зашифрованими віддаленими резервними копіями. Секрети відокремлені від вихідного коду, а застосунок отримує лише необхідні права та обмежений у часі токен.

Наступним кроком створіть моніторинг health endpoint, строку дії TLS-сертифіката, вільного місця та успішності backup. Потім налаштуйте тривузловий Raft-кластер, якщо простій одного VPS неприйнятний. Насамкінець автоматизуйте ротацію secret_id, регулярне тестове відновлення та процедуру оновлення OpenBao через maintenance window.

Чи був цей гайд корисним?

Ваш відгук допомагає нам покращувати гайди.

Share this post:

Надішліть гайд тому, кому він може стати в пригоді.

Telegram VKVK WhatsApp Facebook LinkedIn XX

розгортання openbao на vps: керування секретами, tls, approle та резервне копіювання
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.