Онбординг душ
Это руководство проводит путь от пустого реестра до нескольких хостов в статусе connected — готовых получать Destiny. Quick Start подключал один хост; здесь та же механика масштабируется на множество душ, плюс разложены по полочкам covens, которыми вы потом таргетируете сценарии.
Предполагается, что Keeper уже поднят, первый Архонт создан и его JWT лежит в переменной TOKEN. Если нет — пройдите Quick Start (шаги 1–3) или Установку из пакетов.
Картина процесса
Заголовок раздела «Картина процесса»Онбординг каждого хоста — двусторонний обмен:
- Оператор регистрирует хост в Keeper-е (
POST /v1/souls) и получает одноразовый bootstrap-токен. - На хосте
soul initобменивает токен + CSR на постоянную mTLS-идентичность (SoulSeed). Приватный ключ генерируется на хосте и никогда его не покидает. - На хосте
soul runподнимает демон, который держит долгоживущий стрим к Keeper-у — хост переходит вconnected.
sequenceDiagram
participant Op as Оператор
participant K as Keeper
participant H as Хост (Soul)
Op->>K: POST /v1/souls
K-->>Op: bootstrap_token
Note over Op,H: доставка токена на хост
H->>K: soul init (CSR + токен)
K-->>H: SoulSeed
H->>K: soul run (mTLS-стрим)
K-->>H: status: connected
Идентификатор хоста (SID) равен его FQDN. Дальше по тексту примеры используют host-01.example.com … host-NN.example.com.
Шаг 1. Спланировать covens
Заголовок раздела «Шаг 1. Спланировать covens»Coven — стабильная логическая метка хоста: кластер, проект, окружение, ЦОД, тип железа. По covens вы позже таргетируете сценарии (on: [web, prod]). Метку назначают при регистрации, и она остаётся стабильной — поэтому продумать схему covens стоит до онбординга.
Ключевое правило: Coven — это только стабильные теги. Волатильная роль хоста (кто сейчас master, кто replica) — не Coven; она определяется живой проверкой во время прогона (Оркестрация → probe-роль). В Coven кладут то, что не меняется от прогона к прогону.
Пример схемы для нескольких душ:
| Хост | Covens | Смысл |
|---|---|---|
host-01.example.com | [web, prod, eu] | веб-узел, прод, регион EU |
host-02.example.com | [web, prod, eu] | веб-узел, прод, регион EU |
host-03.example.com | [db, prod, eu] | узел БД, прод, регион EU |
Один хост может нести несколько covens. Таргетинг по нескольким меткам берёт их пересечение (on: [web, prod] → только хосты, у которых есть обе метки).
Шаг 2. Зарегистрировать хосты и выпустить токены
Заголовок раздела «Шаг 2. Зарегистрировать хосты и выпустить токены»Регистрация — POST /v1/souls со стороны Keeper-а. На каждый хост:
curl -s -X POST http://keeper.example.com:8080/v1/souls \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"sid": "host-01.example.com", "transport": "agent", "covens": ["web", "prod", "eu"]}'В ответе — bootstrap_token (возвращается ровно один раз, TTL по умолчанию 24 часа) и expires_at. Запись хоста появляется в статусе pending.
Регистрация душ скриптом
Заголовок раздела «Регистрация душ скриптом»Регистрировать десятки хостов вручную неудобно. Типовой паттерн — цикл по списку FQDN, складывающий выпущенные токены в защищённый файл (mode 0600):
# hosts.txt: по одному FQDN на строкуwhile read -r sid; do token=$(curl -s -X POST http://keeper.example.com:8080/v1/souls \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d "{\"sid\": \"$sid\", \"transport\": \"agent\", \"covens\": [\"web\", \"prod\"]}" \ | jq -r '.bootstrap_token') printf '%s\t%s\n' "$sid" "$token" >> souls-tokens.tsvdone < hosts.txtchmod 0600 souls-tokens.tsvДальше каждый токен доставляется на свой хост (см. шаг 4). Способ доставки — выбор оператора: SSH/SCP, cloud-init, CI/CD-пайплайн, конфиг-менеджмент.
Шаг 3. Подготовить trust-материал на хостах
Заголовок раздела «Шаг 3. Подготовить trust-материал на хостах»Bootstrap-фаза (soul init) идёт по server-only TLS: хост обязан проверить серверный сертификат Keeper-а до того, как получит собственную идентичность. Доверие устанавливается не «как-нибудь», а явной предзагрузкой PKI-корня — того же CA, которым подписан серверный сертификат Keeper-а.
На каждый хост заранее положите этот CA-файл по пути, который укажете в soul.yml (keeper.tls.ca):
# ca.crt — корневой/issuing CA вашего PKI (тот же, что серверный cert Keeper-а)sudo install -d -m 0750 /var/lib/soul-stack/seedsudo install -m 0644 ca.crt /var/lib/soul-stack/seed/ca.crtОткуда взять ca.crt? Это issuing CA вашего PKI, полученный при выпуске серверного сертификата Keeper-а — для локального знакомства возьмите его быстрыми vault-командами из Quick Start → локальное знакомство; для прода — Установка из пакетов.
Если файл не положить — soul init остановится с keeper.tls.ca is empty. Если положить CA от другого корня — certificate validation failed.
Шаг 4. Заполнить soul.yml
Заголовок раздела «Шаг 4. Заполнить soul.yml»Минимальный конфиг агента — адрес Keeper-а, два порта (bootstrap и event-stream) и путь к доверенному CA:
# /etc/soul/soul.yml на host-01.example.comsid: host-01.example.com # = FQDN; по умолчанию берётся из hostnamepaths: modules: /var/lib/soul-stack/modules seed: /var/lib/soul-stack/seed # сюда soul init положит SoulSeedkeeper: endpoints: - host: keeper.example.com bootstrap_port: 9442 # server-only TLS, фаза soul init event_stream_port: 9443 # mTLS, фаза soul run priority: 1 tls: ca: /var/lib/soul-stack/seed/ca.crt # предзагружен на шаге 3Оба порта обязательны и явны — молчаливого ухода bootstrap на event-stream-порт нет. Несколько Keeper-ов перечисляются как несколько записей endpoints[] с разными priority (агент использует их как fallback-list).
Шаг 5. soul init — обменять токен на идентичность
Заголовок раздела «Шаг 5. soul init — обменять токен на идентичность»soul init определяет SID, генерирует приватный ключ + CSR, подключается к bootstrap-listener-у Keeper-а, предъявляет токен + CSR и атомарно раскладывает полученный SoulSeed в paths.seed.
Bootstrap-токен из шага 2 передаётся одним из двух способов:
SOUL_BOOTSTRAP_TOKEN='<bootstrap_token хоста>' soul init --config /etc/soul/soul.ymlБезопаснее: токен не виден в выводе ps и не попадает в историю shell.
soul init --token='<bootstrap_token хоста>' --config /etc/soul/soul.ymlФлаг имеет приоритет над переменной окружения.
При успехе SoulSeed (cert/key/ca) лежит в paths.seed, запись хоста переходит из pending. Если SoulSeed на хосте уже есть, init остановится — это защита от случайного перевыпуска идентичности.
Шаг 6. soul run — поднять демон
Заголовок раздела «Шаг 6. soul run — поднять демон»soul run --config /etc/soul/soul.ymlДемон поднимает долгоживущий EventStream к Keeper-у по mTLS (порт 9443) — после этого хост становится connected. В проде soul работает как systemd-сервис (systemctl enable --now soul); ручной запуск выше удобен для первой проверки.
Шаг 7. Проверить, что души connected
Заголовок раздела «Шаг 7. Проверить, что души connected»Опросить конкретный хост:
curl -s http://keeper.example.com:8080/v1/souls/host-01.example.com \ -H "Authorization: Bearer $TOKEN"# в ответе status: connectedОпросить весь реестр и отфильтровать по covens (например, увидеть все prod-хосты):
curl -s 'http://keeper.example.com:8080/v1/souls?coven=prod' \ -H "Authorization: Bearer $TOKEN"То же самое доступно в web-UI на /ui (вкладка с реестром хостов) и через CLI soulctl — см. soulctl.
Типовые спотыкания
Заголовок раздела «Типовые спотыкания»| Симптом | Вероятная причина | Что проверить |
|---|---|---|
soul init: connection refused | Keeper не слушает bootstrap-порт / firewall режет 9442 | Keeper запущен; открыт входящий bootstrap-порт с хоста; host/bootstrap_port в soul.yml верны |
soul init: certificate validation failed | предзагруженный CA не от того PKI-корня; или FQDN Keeper-а не в SAN серверного cert-а | keeper.tls.ca = тот же CA, что серверный cert; FQDN из endpoints[].host в SAN |
soul init: keeper.tls.ca is empty | CA-файл не указан/не положен | заполнить keeper.tls.ca и положить файл (шаг 3) |
soul init: bootstrap token invalid / expired / used | токен уже использован, истёк (TTL 24h) или SID не совпал | перевыпустить токен (POST /v1/souls/{sid}/issue-token, force при активном); сверить SID = FQDN |
soul init: invalid sid | FQDN не матчит ^[a-z0-9][a-z0-9.-]{0,253}$ | привести hostname к валидному lower-case FQDN либо задать sid: явно в soul.yml |
хост остаётся pending, не connected | EventStream-фаза (mTLS на event-stream-порту) не проходит | открыт входящий event-stream-порт; SoulSeed разложен в paths.seed; серверный cert и SoulSeed от одного PKI-корня |
Что дальше
Заголовок раздела «Что дальше»- Первый сервис на душах — раскатать состояние на подключённые хосты по их covens.
- Оркестрация сценарием — управлять порядком раскатки по душам.
- Установка из пакетов — прод-онбординг из deb/rpm с systemd.
- Безопасность → Идентичность — SID, SoulSeed, ротация, модель доверия.