Skip to content

Repository files navigation

NmapWebUI

A modern web-based frontend for Nmap built with Go, Gin, GORM, Redis, and robfig/cron.

Architecture Overview

Layer Technology
Web Framework Gin
Task Queue Redis (BRPOP)
Scheduler robfig/cron
Database SQLite via GORM
Auth JWT + bcrypt
Frontend Go html/template + Tailwind CSS (built to a static file, no CDN)
Live Updates Server-Sent Events (SSE) via Redis pub/sub
Nmap Execution os/exec subprocess

Project Structure

nmapwebui/
├── cmd/
│   ├── server/main.go      # HTTP server entrypoint
│   └── worker/main.go      # Background worker entrypoint
├── internal/
│   ├── config/             # Configuration (env vars)
│   ├── db/                 # GORM database init + migrations
│   ├── models/             # GORM models
│   ├── middleware/         # JWT auth middleware
│   ├── handlers/           # HTTP handlers (auth, targets, scans, reports, admin, SSE)
│   ├── services/           # Business logic (nmap, locking, reports)
│   └── scheduler/          # Cron-based schedule checker
├── templates/              # Go html/template pages (base.html holds the shared shell)
├── static/
│   ├── css/input.css       # Tailwind source; app.css is the committed build output
│   ├── js/common.js        # Shared UI helpers (API wrapper, toasts, modals, pagination)
│   └── vendor/             # Chart.js and Font Awesome, vendored for offline use
├── tailwind.config.js      # Tailwind content paths and theme
├── scripts/vendor.sh       # Fetches pinned Chart.js / Font Awesome releases (dev only)
├── Dockerfile              # Multi-stage build
├── docker-compose.yml      # Server + Worker + Redis
├── Makefile                # Build/run shortcuts
└── go.mod

Quick Start

Prerequisites

  • Go 1.22+
  • Redis
  • Nmap installed on the system
  • GCC (for SQLite CGO)

Local Development

# 1. Copy environment config
cp .env.example .env

# 2. Start Redis
redis-server

# 3. Build and run the server
make run

# 4. In another terminal, start the worker
make worker

The server starts at http://localhost:51111 (override with PORT in .env). Log in with the superadmin credentials from .env. Both binaries load .env from the working directory automatically; real environment variables take precedence.

Frontend assets

The UI has no runtime CDN dependency: Tailwind is compiled to static/css/app.css, and Chart.js and Font Awesome are vendored under static/vendor/. These outputs are committed, so running, building and the Docker image need only Go.

No Node is involved. Tailwind runs as its standalone binary, downloaded once into bin/ by the Makefile, and libraries are fetched with curl from pinned release URLs. Rebuild only after changing templates or static/css/input.css, or to upgrade a library:

make css          # download Tailwind binary if missing, rebuild app.css
make css-watch    # rebuild on every template change
make vendor       # re-fetch Chart.js and Font Awesome (versions pinned in scripts/vendor.sh)
make frontend     # vendor + css

Docker Compose

# Starts Redis, Web Server, and Worker
make deploy

# View logs
make logs

Access at http://localhost:51111.

Makefile Commands

Command Description
make run / make worker Build and run the server / worker locally
make frontend / make css Rebuild vendored assets and Tailwind CSS (standalone binary, no Node)
make deploy Build with layer cache and restart (fast for code-only changes)
make deploy-full Full rebuild without cache (needed when Dockerfile changes)
make restart Restart containers without rebuilding
make logs Tail container logs
make down Stop containers, preserves database and reports
make down-clean Stop containers and delete all data (volumes removed)

Data Persistence

The database (app.db) and scan reports are stored in a Docker volume (app_data). This data persists across make deploy, make down, and container restarts.

To preserve data: always use make down (runs docker-compose down). To reset everything: use make down-clean (runs docker-compose down -v).

Key Features

Scan Profiles

Built-in profiles: quick_scan, intense_scan, ping_scan, service_scan, os_detection, comprehensive, plus custom argument support.

Scheduler (robfig/cron + Redis Locks)

  • Supports daily, weekly, monthly, and interval schedules
  • Exactly-once execution via Redis distributed locks
  • Schedule checker runs every 60 seconds
  • Window-based deduplication prevents duplicate triggers

Concurrency Control / Duplicate Prevention

Two layers of locking prevent race conditions:

  1. Redis lock (nmapwebui:lock:task:{task_id}) — ensures only one worker runs a given task at a time
  2. DB state check — queued/running scan runs block new ad-hoc runs

Live Updates (SSE)

Connect to /api/sse/scans/:run_id/events for real-time progress:

  • progress events from nmap --stats-every parsing
  • status events (starting, running, completed, failed, cancelled)
  • Heartbeat keepalive for connection stability

Cancelling Scans

POST /api/scans/runs/:id/cancel stops a run. Queued runs are finalised immediately. For running scans the API sets a short-lived Redis flag (nmapwebui:scan:{run_id}:cancel); the worker polls it once a second, kills the nmap process and marks the run cancelled.

Report Diff

GET /api/reports/:id/diff compares a report with the previous report of the same task: hosts that appeared or disappeared, up/down status changes, and per-host ports that opened, closed or changed service/version. The report page renders this as a "Changes since previous scan" panel and marks new and closed ports inline.

Host Inventory and Exposure

GET /api/hosts aggregates the latest report of every task into one row per IP address: status, open ports, services, which tasks cover it, first and last seen. GET /api/hosts/:ip adds the port history across all reports. Open ports are tagged by a heuristic in internal/services/exposure.go ("high" for remote-admin, database, file-sharing and ICS services such as Telnet, RDP, SMB, Redis or Modbus; "medium" for services worth an inventory check such as SSH or alternate HTTP). It is a prioritisation aid, not a vulnerability rating.

Command Palette and Shortcuts

Ctrl/⌘ K or / opens a palette that searches hosts, tasks, target groups, reports and runs (GET /api/search?q=) and lists navigation commands. g followed by d/h/a/t/r/p/s jumps to a section, n creates a task, d toggles compact table density and ? lists everything.

Account Settings

/settings lets each user change their email, the timezone used to evaluate schedules, and their password (GET/PUT /api/me). Last login is recorded on sign-in.

Health

GET /api/health reports Redis reachability, the number of worker processes with a live heartbeat, and the queue depth. The UI header indicator polls it so a missing worker is visible immediately.

Report Management

Nmap outputs saved as:

  • XML (-oX) — parsed into structured Host/Port findings
  • Normal text (-oN) — raw output for download
  • PDF and HTML — generated on demand from the parsed findings. PDFs are drawn in pure Go with go-pdf/fpdf; no external renderer is required.

Authentication

  • JWT access tokens (cookie + Bearer header)
  • Role-based access (user / admin)
  • Password hashing with bcrypt

API Endpoints

Prefix Description
/api/auth Login, register, logout
/api/targets CRUD for target groups & hosts (PUT /api/targets/:id replaces the target list)
/api/scans Scan tasks & runs. Lists support q, scheduled, status, task_id filters; POST .../runs/:id/cancel stops a run
/api/schedules Enable/disable scheduled scanning
/api/reports List (filter by task_id, from, to, q), view, diff, download XML/TXT/CSV/PDF
/api/hosts Host inventory from the latest report per task; /api/hosts/:ip for detail and history
/api/search Global search for the command palette
/api/me Own profile: email, timezone, password
/api/health Redis, worker heartbeat and queue depth
/api/admin Admin stats & user listing
/api/sse Server-Sent Events for live scan progress

Configuration

Set via .env file or environment variables:

SECRET_KEY=change-me-in-production
DATABASE_URL=instance/app.db
REDIS_URL=redis://localhost:6379/0
NMAP_REPORTS_DIR=instance/reports
DEBUG=false
ACCESS_TOKEN_EXPIRE_MINUTES=120
NMAP_WORKER_POOL_SIZE=2

Security Notes

  • Nmap arguments are passed as a list to exec.Command to avoid shell injection
  • Custom arguments should still be validated at the UI layer
  • Passwordless sudo may be required for privileged scans (-O, -sS, etc.)
  • The Docker containers use NET_RAW and NET_ADMIN capabilities for raw packet scans

License

MIT

About

A web-based application that serves as a user-friendly wrapper for the Nmap network scanner. This application allows authenticated users to manage targets, define and execute Nmap scans, view scan reports, and schedule recurring scans.

Resources

Stars

18 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages