Distributed network port scanning and monitoring system for security purposes with multi-site scanner support, alerting, and web dashboard.
- Port Scanning: Masscan and Nmap-based port scanning with service detection
- NSE Vulnerability Scanning: Nmap Scripting Engine integration for CVE detection and vulnerability assessment
- 22 built-in scan profiles (Quick Scan, Full Vulnerability, Web App, Infrastructure, SSL/TLS Audit)
- Individual checks for EternalBlue, Shellshock, Heartbleed, SQL injection, XSS, and more
- Clone and customize profiles or create new ones from scratch
- Automatic CVE extraction from scan results with alert generation
- SSH Security Analysis: Automatic SSH server security auditing including:
- Authentication method detection (publickey, password, keyboard-interactive)
- Weak cipher and key exchange algorithm detection
- SSH version tracking with outdated version alerts
- Configuration regression detection between scans
- Multi-Site Scanning: Deploy scanner agents at different locations
- Greenbone (GVM) Vulnerability Scanning: Optional Greenbone Community Edition integration for comprehensive vulnerability assessment
- Connects via
python-gvmUnix socket bridge — no web UI needed - Scan config presets: Full and fast, Full and deep, Discovery, System Discovery
- Results with CVSS scores, CVE mapping, solution recommendations, and Quality of Detection
- Automatic alert generation for medium+ severity findings
- Connects via
- Alerting: Configurable alerts for new ports, policy violations, SSH security issues, NSE findings, and GVM vulnerabilities
- Compliance Reports: Export PDF and CSV reports for SSH security compliance
- Web Dashboard: React-based UI with dark mode support
- Docker and Docker Compose
- Git
-
Clone the repository:
git clone <repository-url> cd opm
-
Copy the environment file and configure:
cp .env.example .env # Edit .env with your preferred settings -
Start the development environment:
docker compose -f compose-dev.yml up --build
-
Access the services:
- Frontend: http://localhost:5173
- Backend API: http://localhost:8000
- API Documentation: http://localhost:8000/docs
- Database: localhost:3306
| Service | Port | Description |
|---|---|---|
| frontend | 5173 | React + Vite web dashboard |
| backend | 8000 | FastAPI REST API |
| db | 3306 | MariaDB database |
| scanner | - | Network scanner agent (Masscan, Nmap, NSE, Nuclei, SSH probe, GVM) |
The development environment uses bind mounts for hot-reloading:
./backend/src->/app/src(Backend)./frontend/src->/app/src(Frontend)./scanner/src->/app/src(Scanner)
Changes to source files will automatically trigger reloads.
The backend has a comprehensive test suite using pytest with async support.
cd backend
# Install dev dependencies (if not already installed)
uv pip install -e ".[dev]"
# Run all tests
.venv/bin/pytest tests/ -v
# Run specific test file
.venv/bin/pytest tests/test_auth.py -v
# Run with coverage
.venv/bin/pytest tests/ --cov=app --cov-report=term-missingTest categories:
test_security.py- Password hashing, JWT token handlingtest_auth.py- Authentication endpointstest_users.py- User managementtest_networks.py- Network CRUD operationstest_scans.py- Scan lifecycle managementtest_alerts.py- Alert operations
The frontend uses Vitest with React Testing Library.
cd frontend
# Install dependencies (if not already installed)
npm install
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run with coverage
npm run test:coverageTest categories:
api.test.ts- API utilities, error handling, fetch wrapperscanEstimate.test.ts- Scan estimation calculations (CIDR parsing, port counts)scanLogs.test.ts- Log formatting and date parsing utilitiesformatRelativeTime.test.ts- Relative time formatting (e.g., "5m ago")ThemeContext.test.tsx- Theme provider, localStorage persistenceAuthContext.test.tsx- Authentication hook, login/logout flowsProtectedRoute.test.tsx- Route guard component
See .env.example for all available configuration options.
Key variables:
JWT_SECRET: Secret key for JWT token signing (change in production!)ADMIN_EMAIL/ADMIN_PASSWORD: Initial admin credentialsSMTP_*: Email configuration for alerts
The scanner agent can be deployed on a different host to connect to your main STYLiTE Orbit Monitor server. This enables distributed scanning from multiple locations.
- Docker installed on the scanner host
- API key from the main server (create via the web dashboard or API)
- Network connectivity to the main server's backend API
First, build the scanner image (from the project root):
docker build -f scanner/Dockerfile --build-arg VERSION=$(cat VERSION) -t opm-scanner:latest scannerOr use a pre-built image from a registry:
docker pull your-registry/opm-scanner:latestThen run the scanner:
docker run -d \
--name opm-scanner \
--cap-add=NET_RAW \
--cap-add=NET_ADMIN \
--restart unless-stopped \
-e BACKEND_URL=https://your-server.com:8000 \
-e API_KEY=your-api-key-here \
-e POLL_INTERVAL=60 \
-e LOG_LEVEL=INFO \
opm-scanner:latestRequired environment variables:
BACKEND_URL: Full URL to your main server's backend API (e.g.,https://monitor.example.com:8000)API_KEY: Scanner API key obtained from the main server
Optional environment variables:
POLL_INTERVAL: Seconds between job polls (default: 60)LOG_LEVEL: Logging level - DEBUG, INFO, WARNING, ERROR (default: INFO)
-
Navigate to the scanner directory:
cd scanner -
Create a
.envfile with your configuration:cat > .env << EOF BACKEND_URL=https://your-server.com:8000 API_KEY=your-api-key-here POLL_INTERVAL=60 LOG_LEVEL=INFO EOF
-
Start the scanner:
docker compose up -d
-
View logs:
docker compose logs -f
The scanner will automatically connect to your main server and start processing scan jobs.
Note: The scanner requires NET_RAW and NET_ADMIN capabilities to perform network scans. These are automatically configured in the compose file.
GVM adds full vulnerability assessment powered by the Greenbone Community Edition. The scanner image includes GVM support — when a GVM socket is mounted, the scanner auto-detects as unified and handles both standard port scanning and Greenbone vulnerability assessment jobs.
The scanner auto-detects its capabilities at startup:
| Kind | When | Capabilities |
|---|---|---|
| standard | No GVM socket present | Masscan, Nmap, NSE, Nuclei, SSH probe |
| unified | GVM socket mounted + masscan present | All standard tools + GVM vulnerability scanning |
| gvm | GVM socket mounted, no masscan (Dockerfile.gvm) |
GVM vulnerability scanning only (lightweight bridge) |
A single Dockerfile produces both standard and unified scanners — the difference is purely runtime (whether a GVM socket is mounted).
- Main OPM stack running (
compose.ymlorcompose-dev.yml) - A Scanner record created in OPM (via web dashboard → Scanners) with the API key noted
- Sufficient disk space (~5 GB for vulnerability feeds on first sync)
-
Set the scanner API key:
export GVM_SCANNER_API_KEY=your-api-key-here -
Start the GVM stack:
docker compose -f compose-gvm.yml up -d
-
Wait for feed sync to complete (first startup takes a significant amount of time):
docker compose -f compose-gvm.yml logs -f gvmd
-
Set the GVM admin password:
docker compose exec --user gvmd gvmd gvmd --user=admin --new-password=admin # or: docker compose -f compose-gvm.yml exec --user gvmd gvmd gvmd --user=admin --new-password=admin
-
In the OPM web dashboard, set a network's scanner type to Greenbone and choose a scan config (e.g. Full and fast).
The compose stack includes the Greenbone Security Assistant (GSA) web interface for direct access to GVM:
docker compose -f compose-gvm.yml up -d gsaAccess at http://localhost:9392 — login with the credentials set in step 4 (default: admin/admin).
The GSA port can be changed via the GVM_GSA_PORT environment variable.
Note: GSA is optional — OPM already displays all GVM scan results in the host detail page.
| Variable | Default | Description |
|---|---|---|
GVM_SCANNER_API_KEY |
(required) | Scanner API key from OPM |
GVM_BACKEND_URL |
http://backend:8000 |
OPM backend URL |
GVM_POLL_INTERVAL |
60 |
Seconds between job polls |
GVM_LOG_LEVEL |
INFO |
Log level |
GVM_USER |
admin |
GVM admin username |
GVM_PASSWORD |
admin |
GVM admin password |
GVM_GSA_PORT |
9392 |
GSA web UI port |
For production, edit compose-gvm.yml and swap the build/image lines on opm-scanner-gvm:
# image: styliteag/opm-scanner:latest # uncomment this (same image, unified via socket)
# build: ... # comment outThen set GVM_BACKEND_URL=http://app:80 (the prod service name).
The scanner in compose-gvm.yml uses the same image as the standard scanner but with a GVM socket mounted. It communicates with GVM via Unix socket and with OPM via REST API.
OPM Backend <──REST──> opm-scanner (unified) <──Unix socket──> gvmd ──> ospd-openvas
+-------------+ +---------+ +----------+
| Frontend |<--->| Backend |<--->| Database |
| (React/Vite)| | (FastAPI)| | (MariaDB)|
+-------------+ +---------+ +----------+
^
|
+----------+----------+----------+
| | | |
+--------+ +--------+ +--------+ +--------+
|Scanner1| |Scanner2| |Scanner3| |Scanner4|
| (std) | | (std) | |(unified)| | (gvm) |
+--------+ +--------+ +--------+ +--------+
(Distributed scanners) | |
+----------+ |
| gvmd |<---+
+----------+
For comprehensive documentation, see the docs folder:
- API Reference - Complete API documentation
- Scanner Documentation - Deployment and operation guides
- Development - Setup and contribution guidelines
MIT