Self-hostable port-scan organizer for penetration testers. Ingest
nmapoutput, normalize it across Client → Project → Assessment → Host → Port, and pivot from any port to the list of IPs that have it open — with a one-click.txtexport.
PortRaven is plugin-extensible in the spirit of nuclei. The core ships
with built-in nmap import + live-scan plugins; future collectors (smb-loot,
ftp-loot, …) plug into the same typed pipeline.
Pre-alpha. Milestone 1 in progress — currently scaffolding the repo. See the spec for the v1 plan.
One binary on the host, one command to set everything up. Bloodhound-CLI-style
ergonomics — no editing .env files by hand, no remembering compose flags.
From a fresh Kali box:
# Prereqs: just git + Go (Docker is auto-installed by the CLI below)
sudo apt install -y git golang-go make
# Clone, build the CLI, and run install
git clone https://github.com/0testsa/PortRaven.git
cd PortRaven
make cli
./backend/bin/portraven-cli installInside install, the CLI will:
- Detect missing Docker and offer to install it (apt on Kali/Debian/Ubuntu,
dnf on Fedora, pacman on Arch). Answer
Yand it runs the apt commands with sudo. After that it asks you tonewgrp docker(or open a new terminal) and re-run install — group changes don't take effect in the current shell. - Detect a missing portraven image and offer to build it from the
Dockerfile in your checkout (~3-5 min). Answer
Yand it runsdocker buildfor you. - Generate secrets, write
./portraven/.env(0600), pullpostgres:15-alpine, start the stack, and print the URL + admin password.
Output ends with the URL, the admin user, and the generated admin password. Day-to-day commands:
./backend/bin/portraven-cli status # health + login URL
./backend/bin/portraven-cli down # stop (keeps your data)
./backend/bin/portraven-cli up # start it again
./backend/bin/portraven-cli logs -f # tail server logs
./backend/bin/portraven-cli update # pull a newer image + recreate
./backend/bin/portraven-cli reset-password # locked out? generates a new admin pw
./backend/bin/portraven-cli backup engagement.tgz # snapshot DB + loot
./backend/bin/portraven-cli restore engagement.tgz # restore from snapshot (destructive)
./backend/bin/portraven-cli uninstall # drop everything (destructive)The state directory defaults to ./portraven/ next to wherever you run
install. Pass --dir /some/path to put it elsewhere; pass --port 9000
to bind a different host port; pass --bind 0.0.0.0 only if you need the
API reachable from outside this machine (defaults to 127.0.0.1-only).
For backups containing a copy of .env (whole-machine clone), pass
--include-secrets --encrypt — the bundle gets passphrase-encrypted with
age (requires sudo apt install age).
Requirements: Docker (sudo apt install -y docker.io docker-compose on
Kali — the modern docker-compose apt package is Compose v2) and your user in
the docker group (sudo usermod -aG docker $USER && newgrp docker). The CLI
checks both at install time and offers to install Docker for you if it's
missing — answer Y when prompted.
On a connected machine:
make release-offline
# → dist/portraven-offline-linux-amd64.tar.gz (CLI + images.tar + compose)Copy the tarball to the air-gapped Kali box, then:
tar xzf portraven-offline-linux-amd64.tar.gz
cd portraven-offline
./portraven-cli install --offline images.tar
./portraven-cli upNo network calls during install; docker load reads images straight off the
tarball.
For people hacking on PortRaven itself — no Docker required for the inner loop.
cp .env.example .env
make localThe single binary serves the API on :8090 and persists to ./portraven.db
(SQLite). Suitable for fast dev iteration on a laptop.
For Postgres parity (matches what portraven-cli install deploys):
cp .env.example .env
make dev # starts postgres in docker, then runs backend + frontend on host- Backend: http://127.0.0.1:8090
- Frontend: http://127.0.0.1:5173
- Postgres:
127.0.0.1:5432(volumeportraven-pgdata)
The deploy/ directory is the original raw compose stack. If you want
control over every env var (e.g. for staging/prod CI, custom registry tags,
external Postgres), you can still:
cd deploy
cp .env.production.example .env
# edit .env: set PORTRAVEN_JWT_SECRET, PORTRAVEN_SEED_ADMIN_PASSWORD,
# PORTRAVEN_CRED_PASSPHRASE, POSTGRES_PASSWORD
cd ..
make prod-upportraven-cli was built specifically so most users never need this.
| Make target | What it does |
|---|---|
make cli |
Build the host CLI (backend/bin/portraven-cli) |
make release-offline |
Build the offline tarball (CLI + saved images + compose) |
make docker-build |
Build the multi-stage image (portraven:latest) |
make prod-up |
docker compose -f deploy/docker-compose.yml up -d --build (legacy) |
make prod-down |
Stop the legacy stack (keeps Postgres + loot volumes) |
make prod-logs |
Tail backend logs from the legacy stack |
The image is distroless (no shell, no package manager) and runs as the
non-root nonroot user. Two named volumes carry persistent state:
portraven-pgdata (DB) and portraven-loot (collector artifacts).
Both the backend and Vite are pinned to IPv4 (127.0.0.1) by default.
Node 20+ resolves localhost to ::1 (IPv6 loopback) before 127.0.0.1,
which silently breaks Vite's proxy when the Go backend listens on IPv4 only.
Pinning both sides to 127.0.0.1 avoids that class of bug entirely.
For server deployments that need to accept external connections, override
PORTRAVEN_HTTP_ADDR=0.0.0.0:8090 in .env.
backend/ Go 1.22+ service (chi, sqlc, dual SQLite/Postgres) + portraven-cli
frontend/ React 18 + Vite + TypeScript + shadcn/ui
docs/ MkDocs site (architecture, API, plugin authoring, user guide)
plugins-sdk/ Public Go module for third-party plugin authors
Full layout and architecture rules: see the spec §9 and §4.
| Doc | Audience |
|---|---|
| Architecture | Contributors |
| API reference | API consumers, frontend |
| Writing a plugin | Plugin authors |
| Plugin manifest spec | Plugin authors |
| User guide | End users (pentesters) |
Docs are built with MkDocs Material — make docs-serve to preview locally.
See CONTRIBUTING.md (added in a later step). Conventional Commits required; PRs squash-merge.
TBD.