Self-host эксплуатация¶
Команды, развёртывающие CVE Radar на внутренних серверах, Kubernetes или Docker, нуждаются в возможностях production из той же MIT-кодовой базы: audit-логи JSON, mount секретов, RBAC, мультитenant PostgreSQL, метрики Prometheus, offline-зеркала и обнаружение стека в Kubernetes.
Enterprise-уровня и лицензионных блокировок нет. Переменные окружения меняют только операционное поведение. См. Эксплуатация и Конфигурация.
flowchart TB
classDef ui fill:#e9edf5,stroke:#00baba,color:#253343
classDef api fill:#f3fcfc,stroke:#008c8c,color:#253343
classDef data fill:#fff7ed,stroke:#eda232,color:#253343
classDef ext fill:#f5f5f5,stroke:#666,color:#253343
subgraph deploy["Self-host развёртывание"]
Browser[Browser SPA]:::ui
API[Express API]:::api
PG[(PostgreSQL опционально)]:::data
Metrics["GET /metrics"]:::api
Audit[stdout audit JSON]:::ext
end
Browser --> API
API --> PG
API --> Metrics
API --> Audit
API --> Feeds[NVD / OSV / mirrors]:::ext
API --> Notify[Slack / SMTP / webhooks]:::ext
На схеме: опциональный Postgres, scrape Prometheus на /metrics, audit в stdout и исходящие уведомления после watch. В airgap публичные feeds заменяются локальными зеркалами (см. Airgap).
Audit-логирование¶
Одна JSON-строка на событие в stdout для ELK/Loki/Splunk или Docker json-file.
| action | Когда |
|---|---|
scan |
После каждого POST /api/scan |
watch |
После каждого POST /api/watch |
health |
При AUDIT_HEALTH=true и detailed health |
export |
Пока только в браузере |
{
"audit": true,
"ts": "2026-06-06T14:30:00.000Z",
"action": "scan",
"ip": "10.0.0.42",
"stack": ["redis", "nginx"],
"duration_ms": 8420,
"sources_failed": ["NVD"],
"result_count": 12,
"mode": "full"
}
TRUST_PROXY_HOPS за reverse proxy. Заголовки CVE и ключи API не логируются.
docker logs cve-radar 2>&1 | grep '"audit":true'
Секреты¶
| env | *_FILE |
|---|---|
NVD_API_KEY |
NVD_API_KEY_FILE |
GITHUB_TOKEN |
GITHUB_TOKEN_FILE |
DEEPL_API_KEY |
DEEPL_API_KEY_FILE |
ALERT_WEBHOOK_URL |
ALERT_WEBHOOK_URL_FILE |
NOTIFICATION_SLACK_WEBHOOK_URL |
— |
NOTIFICATION_DISCORD_WEBHOOK_URL |
— |
NOTIFICATION_TELEGRAM_BOT_TOKEN |
— |
NOTIFICATION_SMTP_PASS |
mount через env file в Compose |
API_SECRET |
API_SECRET_FILE |
Пример Compose: docker-compose.secrets.example.yml. В Kubernetes — mount Secret как файлы.
RBAC и API¶
С API_SECRET все /api/* кроме GET /api/health и GET /api/v1/health требуют ключ. API_ROLE:
| Роль | Права |
|---|---|
| admin | Настройки, tenant CRUD, scan/watch, translate, meta и history |
| scanner | scan/watch/validate, translate, meta и history |
| viewer | meta и history — без scan |
| auditor | history/trends и meta — без scan |
По умолчанию admin. viewer на POST /api/scan получает 403 { "code": "FORBIDDEN" }.
Уведомления watch¶
Self-host часто нужны out-of-band алерты при новых CVE в watch. CVE Radar отправляет уведомления асинхронно после POST /api/watch с непустым newVulns — ответ HTTP не меняется.
| Канал | env |
|---|---|
| Slack | NOTIFICATION_SLACK_WEBHOOK_URL или legacy ALERT_WEBHOOK_URL |
| Discord | NOTIFICATION_DISCORD_WEBHOOK_URL |
| Telegram | NOTIFICATION_TELEGRAM_BOT_TOKEN, NOTIFICATION_TELEGRAM_CHAT_ID |
| SMTP | NOTIFICATION_SMTP_HOST, FROM, TO; опционально PORT, USER, PASS |
| Webhook | NOTIFICATION_WEBHOOK_URL |
| Параметр | env | По умолчанию |
|---|---|---|
| Мин. severity | NOTIFICATION_MIN_SEVERITY / ALERT_MIN_SEVERITY |
HIGH |
| Dedup (ms) | NOTIFICATION_DEDUP_MS |
900000 |
| Формат Slack | ALERT_WEBHOOK_FORMAT |
slack / generic |
Legacy ALERT_WEBHOOK_URL работает через NotificationService. NOTIFICATION_* поддерживает mounts *_FILE. Проверка: GET /api/health?detailed=true → alerts.webhookConfigured. См. Оповещения и NOTIFICATIONS.md.
Мультитenant (PostgreSQL)¶
DATABASE_URL=postgres://cve_radar:cve_radar@127.0.0.1:5432/cve_radar
Migrations при первом подключении pool. Schema в server/db/schema.ts (Drizzle ORM) для постепенной ORM-миграции; runtime-запросы tenant/stack и scan-history используют Drizzle через getDb() (общий pool pg).
X-Tenant-Id: arvancloud-sre
| Method | Path | Описание |
|---|---|---|
POST |
/api/v1/tenants |
Создать tenant |
GET |
/api/v1/tenants/stacks |
Список стеков |
POST |
/api/v1/tenants/stacks |
Создать стек |
GET |
/api/v1/tenants/stacks/:id |
Стек по UUID |
PUT |
/api/v1/tenants/stacks/:id |
Обновить стек |
DELETE |
/api/v1/tenants/stacks/:id |
Удалить стек |
GET |
/api/v1/scans/history |
History tenant |
GET |
/api/v1/scans/trends |
Trends tenant |
History фильтруется по tenant_id. Legacy /api/* пишет в default.
Prometheus и Grafana¶
GET /metrics. METRICS_ENABLED (true), METRICS_PROTECT для auth.
| Метрика | Тип | Описание |
|---|---|---|
cve_radar_scans_total |
counter | scan/watch |
cve_radar_vulns_found |
gauge | последний успешный scan |
cve_radar_scan_duration_seconds |
histogram | длительность |
cve_radar_source_reachable |
gauge | upstream |
cve_radar_cache_entries_total |
gauge | размер cache |
Дашборд: docs/self-hosted/grafana/cve-radar-dashboard.json.
sum(rate(cve_radar_scans_total{status="success"}[5m]))
/ sum(rate(cve_radar_scans_total[5m]))
Airgap-развёртывание¶
AIRGAPPED=true
NVD_MIRROR_URL=http://internal-mirror/nvd
KEV_MIRROR_URL=http://internal-mirror/kev/catalog.json
# OSV — mirror или bulk:
OSV_MIRROR_URL=http://internal-mirror/osv
# OSV_BULK_PATH=/data/osv/extracted
С OSV_BULK_PATH OSV читается из локального JSON (scripts/sync-osv-bulk.sh / make sync-osv-bulk) без query API. GitHub/RSS/перевод отключены. Нет mirror env для NVD/KEV → fail-closed. jq .airgap на detailed health. scripts/sync-mirrors.sh, scripts/sync-osv-bulk.sh.
Kubernetes discovery¶
K8S_DISCOVERY_ENABLED=true
# K8S_DISCOVERY_NAMESPACES=production,staging
GET /api/v1/discovery/kubernetes — auth в production. Отключено → 503 K8S_DISCOVERY_DISABLED.
{
"enabled": true,
"images": ["haproxy", "nginx", "redis"],
"tools": ["HAProxy", "Nginx", "Redis"],
"unmapped": ["my-sidecar"]
}
SA только read на deployments. Сочетайте с tenant.
Краткий справочник¶
| Тема | env |
|---|---|
| Audit | AUDIT_HEALTH, TRUST_PROXY_HOPS |
| Secrets | *_FILE |
| RBAC | API_SECRET, API_ROLE |
| Уведомления | NOTIFICATION_*, ALERT_WEBHOOK_URL |
| Tenant | DATABASE_URL, X-Tenant-Id |
| Metrics | METRICS_ENABLED, METRICS_PROTECT |
| Airgap | AIRGAPPED, *_MIRROR_URL, OSV_BULK_PATH |
| K8s | K8S_DISCOVERY_ENABLED, K8S_DISCOVERY_NAMESPACES |
| Enrichment | EPSS_ENABLED, COMPLIANCE_ENABLED |
Maintainer-копии: docs/self-hosted/.
Домой · Назад: Эксплуатация