تشغيل self-host¶
الفرق التي تشغّل CVE Radar على خوادم داخلية أو Kubernetes أو Docker تحتاج أكثر من سير العمل الافتراضي للمتصفّح. يغطي هذا الفصل قدرات الإنتاج ضمن نفس كود MIT: سجلات audit منظمة، mount للأسرار، RBAC، تعدد المستأجرين PostgreSQL، مقاييس Prometheus، مرايا airgap، واكتشاف المكدس في 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[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
يُظهر المخطط PostgreSQL الاختياري، وscraping Prometheus على /metrics، وسطور audit على stdout، وقنوات الإشعار بعد watch. في airgap تُستبدل المصادر العامة بمرايا محلية (انظر نشر airgap).
سجلات audit¶
CVE Radar يمكنه إخراج سطر JSON واحد لكل حدث audit على stdout لـ ELK أو Loki أو Splunk أو driver json-file في Docker.
| action | متى يُسجَّل |
|---|---|
scan |
بعد كل POST /api/scan (نجاح، فشل جزئي، أو خطأ) |
watch |
بعد كل POST /api/watch |
health |
عند AUDIT_HEALTH=true و GET /api/health?detailed=true |
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 مباشر | 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 |
في Kubernetes يُفضَّل mount ملفات Secret. راجع docker-compose.secrets.example.yml.
RBAC ومصادقة API¶
مع API_SECRET، كل /api/* ما عدا GET /api/health و GET /api/v1/health يتطلب مفتاح API. API_ROLE:
| الدور | الصلاحيات |
|---|---|
| admin | إعدادات، CRUD مكدسات tenant، 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" }. اجمع RBAC مع تعدد المستأجرين على منصات مشتركة.
إشعارات 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 | الافتراضي |
|---|---|---|
| الحد الأدنى للخطورة | NOTIFICATION_MIN_SEVERITY أو ALERT_MIN_SEVERITY |
HIGH |
| نافذة dedup (ms) | NOTIFICATION_DEDUP_MS |
900000 |
| تنسيق Slack | ALERT_WEBHOOK_FORMAT |
slack أو generic |
ALERT_WEBHOOK_URL القديم ما زال يعمل عبر NotificationService. NOTIFICATION_* يدعم mounts *_FILE — أو استخدم env من المنصة أو env file غير مُلتزَم. تحقق: GET /api/health?detailed=true → alerts.webhookConfigured. راجع التنبيهات و NOTIFICATIONS.md.
تعدد المستأجرين (PostgreSQL)¶
DATABASE_URL=postgres://cve_radar:cve_radar@127.0.0.1:5432/cve_radar
تُشغَّل migrations عند أول اتصال pool. تعريفات schema في server/db/schema.ts (Drizzle 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 |
مكدس بالمعرّف |
PUT |
/api/v1/tenants/stacks/:id |
تحديث |
DELETE |
/api/v1/tenants/stacks/:id |
حذف |
GET |
/api/v1/scans/history |
history للمستأجر |
GET |
/api/v1/scans/trends |
trends للمستأجر |
history و trends محدودة بـ tenant_id. بدون DATABASE_URL يبقى التطبيق single-tenant.
Prometheus و Grafana¶
GET /metrics. METRICS_ENABLED (افتراضي true)، METRICS_PROTECT للمصادقة.
| المقياس | النوع | الوصف |
|---|---|---|
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 |
لوحة Grafana: 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) بدل API query. GitHub و RSS وترجمة خارجية تُتخطى. env mirror مفقود لـ NVD/KEV → fail-closed. تحقق: curl …/api/health?detailed=true | jq .airgap. scripts/sync-mirrors.sh و scripts/sync-osv-bulk.sh.
اكتشاف Kubernetes¶
K8S_DISCOVERY_ENABLED=true
# K8S_DISCOVERY_NAMESPACES=production,staging
GET /api/v1/discovery/kubernetes — يتطلب auth في الإنتاج. عند التعطيل 503 K8S_DISCOVERY_DISABLED.
{
"enabled": true,
"images": ["haproxy", "nginx", "redis"],
"tools": ["HAProxy", "Nginx", "Redis"],
"unmapped": ["my-sidecar"]
}
ServiceAccount للقراءة فقط على deployments. اجمع مع عزل tenant.
مرجع سريع¶
| الموضوع | env |
|---|---|
| Audit | AUDIT_HEALTH, TRUST_PROXY_HOPS |
| Secrets | mount *_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/.