Architecture

ScanRook is a multi-service vulnerability scanning platform deployed on a bare-metal Kubernetes cluster. Three components — a Next.js web app, a Go dispatcher, and a Rust scanner — work together to process scan jobs via PostgreSQL and S3.

System overview

Three services connected by PostgreSQL and S3/MinIO.

Loading diagram...

Cluster topology

Three-node bare-metal cluster with dedicated namespaces.

Loading diagram...
NamespaceContents
scanrookscanrook-web (3), scanrook-dispatcher (1), redis (1)
dbCNPG pg-shared cluster (3 instances, 50 GiB PVC each)
storageMinIO (1 replica, 50 GiB PVC)
ingress-nginxIngress controller (NodePort 30080/30443)
monitoringPrometheus, Grafana, Loki, Promtail, node-exporter, kube-state-metrics
argocdArgoCD (GitOps deployment)
longhorn-systemLonghorn distributed block storage
cnpg-systemCloudNativePG operator
kube-systemCilium CNI, CoreDNS, Hubble

Scan pipeline

End-to-end data flow from file upload to scan results.

Loading diagram...

Registry scan flow

How container images are pulled from registries and scanned.

Loading diagram...

For public images, no credentials are needed. Private registries use encrypted credentials stored per-organization in PostgreSQL, decrypted at dispatch time with AES-256-GCM.

Network flow

How traffic flows from the internet to pods and back out.

Loading diagram...

Inbound: All external HTTPS traffic terminates at the Caddy edge-proxy, which forwards plain HTTP to the ingress-nginx NodePort. Ingress rules route to the appropriate ClusterIP service.

Outbound: Scan pods use HTTP_PROXY/HTTPS_PROXY environment variables pointing to a Squid proxy for external API calls (OSV, NVD, EPSS, container registries). This allows network policy enforcement and caching.

Data stores

PostgreSQL tables, S3 buckets, and Redis usage.

PostgreSQL tables

TablePurposeKey columns
scan_jobsJob queue and status trackingid (UUID), status, bucket, object_key, summary_json, scan_type
scan_eventsProgress timeline per jobjob_id, stage, detail, pct, created_at
scan_findingsNormalized vulnerability findingsjob_id, cve_id, severity, package, version, cvss
scan_filesFile inventory from scanned artifactsjob_id, path, entry_type, size, sha256
scan_packagesPackage inventory (SBOM)job_id, ecosystem, name, version, source

S3 buckets

BucketPurposeLifecycle
deltaguardUploaded artifacts (tars, binaries, ISOs)7-day expiry
reportsScan report JSON files90-day expiry
registry-pullsPulled container image tarsCleaned after scan

Redis

Single-instance Redis used for NextAuth session caching and token revocation. Session data is stored with a 7-day TTL. Token version checks enable instant session invalidation across all web replicas.