Docs / Эксплуатация
Секреты, бэкапы, алерты
Штатные операции: доставка секретов в контейнеры, резервное копирование и восстановление, уведомления об инцидентах, SSO/TLS и плановая ротация ключа.
Секреты
Секрет — это именованный JSON (поле content), зашифрованный AES-256-GCM.
Ключ шифрования (data key) свой у каждой записи; при заданном
SECRET_MASTER_KEY он оборачивается мастер-ключом.
Привязка и режимы
- Привязка — список имён контейнеров через запятую; сравнение точное, по имени контейнера (не сервиса compose).
- Режим
file— файл по путиfile_pathили/run/secrets/<project>.json. - Режим
env—/etc/profile.d/<project>.shсexport KEY="value"иsourceв rc-файлы; влияет только на новые shell-сессии.
Когда выполняется доставка
- На событие
container.start— всем привязанным секретам. - При старте приложения и переподключении к Docker — reconcile запущенных контейнеров (дебаунс 30 секунд).
- Вручную — кнопка в строке секрета,
POST /api/secrets/{id}/push. - Автоматически после сохранения секрета, если включены
pushиexec.
Проверка доставки
Перед запуском команды Digraph сверяет целевой путь с картой mount'ов контейнера. Побеждает самый длинный mount, поэтому read-only mount перекрывает writable-родителя. Недоступный путь отклоняется сразу, без exec:
GET /api/secrets/targets
# [{"name":"vuln-scanner","read_only":true,
# "mounts":[{"path":"/cache","kind":"volume","rw":true},
# {"path":"/tmp","kind":"tmpfs","rw":true}]}]
POST /api/secrets/1/push
# {"results":[{"container":"vuln-scanner","status":"pushed","path":"/cache/demo.json"}]}
Если команда всё же выполнилась с ошибкой, в results[] будет status: "error" и текст из контейнера — например, Read-only file system.
Ограничения
- Нужен
/bin/sh: distroless и scratch не поддерживаются. - Read-only rootfs: используйте tmpfs или writable mount; иначе push отклоняется.
- Контейнер с
USERбез прав на каталог: укажите writable путь или tmpfs с нужным uid. - Файл живёт в writable layer: пересоздание контейнера его стирает; авто-push выполнится на старте.
- Нет истории версий: сохранение перезаписывает содержимое.
Бэкапы и восстановление
Архив содержит SQLite (VACUUM INTO) и каталог compose-проектов, плюс манифест с размерами и SHA-256 каждого файла.
| Параметр | Где | Значение |
|---|---|---|
| Расписание | /#/settings и /#/backups | 1–168 часов |
| Ретенция | там же | 1–50 архивов |
| Каталог | BACKUP_DIR | /data/backups |
| Restore | BACKUP_RESTORE_ENABLED=true | по умолчанию выключен |
Restore двухфазный: архив проверяется (манифест, размеры, SHA-256, отсутствие path traversal, лимит распаковки 4 GiB) и ставится в очередь; подмена базы и проектов происходит на следующем старте.
# поставить локальный архив в очередь
curl -X POST localhost:9090/api/backup/files/<name>/restore \
-H "Authorization: Bearer $TOKEN" \
-d '{"confirm":"RESTORE"}'
docker compose restart docker-stat # применить на старте
Bootstrap-секреты в архив не входят. AUTH_TOKEN, JWT_SIGNING_KEY и SECRET_MASTER_KEY лежат в зашифрованном override-файле, а PORTAL_TOKEN — в .env. Храните их отдельно; в манифест пишется только отпечаток.
Обновление версии
Образы версионированы: обновление — смена VERSION в .env,
без пересборки. Sidecar'ы обновляются вместе с контуром; миграции SQLite
применяются при старте.
cd deploy/contour
sed -i 's/^VERSION=.*/VERSION=v0.2.0/' .env
docker compose -f docker-compose.yml -f docker-compose.contour.override.yml pull
docker compose -f docker-compose.yml -f docker-compose.contour.override.yml up -d
cd ../portal
sed -i 's/^VERSION=.*/VERSION=v0.2.0/' .env
docker compose -f docker-compose.yml -f docker-compose.portal.override.yml pull
docker compose -f docker-compose.yml -f docker-compose.portal.override.yml up -d
Откат — вернуть предыдущий VERSION и повторить. Перед обновлением сделайте архив в /#/backups.
Алерты и вебхуки
Контур
Фоновый evaluator работает без открытого браузера. Правила: unhealthy, stopped, restarting, CPU/RAM хоста, устаревший сбор. Есть grace-период, состояние и retry-очередь в SQLite, HMAC-SHA256-подпись запросов.
- Пороги и grace — в
/#/settings→ Alerts. - Пересылка Docker/API-событий настраивается по типам (container, network, volume, image, api).
- История переходов и статистика доставок доступны в настройках.
Портал
Watchdog опрашивает /api/ready всех контуров и ведёт статусы online / degraded / offline. Каналы уведомлений: generic webhook, Slack incoming webhook, PagerDuty Events v2, SMTP email. Настройка и тест — в /#/settings портала.
SSO и TLS
Портал
OIDC настраивается в /#/settings → Portal → Single sign-on: issuer, client ID, secret, redirect URL, scopes, allowlist по email/домену и текст кнопки. Секрет шифруется и не возвращается в браузер.
- Redirect:
https://<домен>/api/portal/auth/oidc/callback. - Пароль портала (
PORTAL_TOKEN) остаётся вторым входом. - После сохранения клиент OIDC пересоздаётся без рестарта.
TLS на контуре
Сертификаты монтируются в контейнер, пути — внутри его файловой системы. Добавьте в свой override:
services:
docker-stat:
volumes:
- ./certs:/etc/digraph/certs:ro
environment:
TLS_CERT_FILE: /etc/digraph/certs/cert.pem
TLS_KEY_FILE: /etc/digraph/certs/key.pem
TLS_REDIRECT_ADDR: ":8080" # HTTP → 308 HTTPS
TLS_PUBLIC_HOST: digraph.example:8443
Ротация мастер-ключа
/#/settings→ Security → Rotate master key, подтверждение словомROTATE.- Сервер пере-оборачивает все data key секретов и AI-ключ в одной транзакции и показывает новый ключ один раз.
- Передайте ключ в контейнер как явную переменную окружения — она перекрывает значение из зашифрованного конфига:
services: docker-stat: environment: SECRET_MASTER_KEY: "<новый ключ>" - Перезапустите контур: без нового ключа при старте будет предупреждение и
[decrypt failed]в ответах.
Env-оверрайд — временное решение. Чтобы вернуться к одному конфигу, перевыпустите override в генераторе с тем же паролем и уберите переменную из compose; при этом сменятся все токены, поэтому токен контура в портале придётся обновить (генератор покажет новый AUTH_TOKEN).