The problem
Small businesses and MSMEs are digitizing through websites, but they rarely have the budget for professional penetration testing. Meanwhile, the industry-standard tools (Nmap, Nuclei, xray, XSStrike, sqlmap, ffuf) are free but command-line heavy, each produces reports in a different format, and running them against your own site without proper isolation is risky. The predictable outcome: website owners skip security testing entirely.

HydraSec is my answer: a self-hosted web application that consolidates all six tools into one interface. You point it at a website you own, and it runs the scan inside an isolated ephemeral container, streams the live CLI output straight to your browser through xterm.js, normalizes every finding into a single database schema, and adds your scan to a public leaderboard. Total cost: Rp0, running entirely on your own machine.

Architecture

arch

The stack is nine containers: an Nginx gateway, a React frontend, a Node.js API, PostgreSQL, Redis (BullMQ), a background worker, MailPit for OTP email delivery, plus Prometheus and cAdvisor for telemetry. The design principle is strict separation: a dedicated internal network for app services and a sandbox network for the scanning tools, so a scanner can never reach the database. Tool containers spawn on demand as non-root users with all capabilities dropped, memory caps, PID limits, and a per-tool timeout, then destroy themselves when the scan ends.

The Docker details that mattered
The frontend uses a multi-stage build, which is the cheapest win in the whole project:

Dockerfile
FROM node:20-alpine AS build
COPY package.json package-lock.json* ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html

Only the final stage ships, so the image is 74 MB instead of 400+ MB of Node.js and node_modules. Every base image is pinned to a specific version (no latest), and the tool sources are pinned to exact commit hashes.

The orchestration rule is equally simple: the API never spawns containers. Jobs go into a Redis queue (BullMQ) and the worker runs at most two tools at a time:
docker-compose.yml
background-worker:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- tooldata:/data
environment:
WORKER_CONCURRENCY: 2
networks: [internal, sandbox]

Ten simultaneous scans queue safely instead of OOM-ing the host. Security was treated as a chain: parameterized SQL everywhere, OTP codes stored as SHA-256 hashes (there are no passwords at all), an SSRF guard that resolves DNS and rejects private ranges, and strict input whitelists before anything reaches a CLI.

Run it locally
bash
git clone https://github.com/Ikhsaaan334/hydrasec && cd hydrasec
bash setup.sh

Sign in with an email and a one-time code, pick a unique username, choose a tool, and watch the scan stream live into your terminal. When it finishes, every finding lands in one normalized table you can export as JSON.

1
2
3
4
5
6
7
8
9

What I learned

  1. Multi-stage builds are the cheapest performance win in containerization: one extra FROM cut my frontend image by 6x.
  2. cgroups make ephemeral sandboxes practical: memory caps and PID limits per tool container are what let two aggressive scanners run side by side safely.
  3. Test before you ship, always. A 2024 binary against 2026 template formats crashed instantly; the bug only surfaced when I actually ran the scan instead of trusting the build.
  4. Security is a chain: one latest tag or one unpinned dependency weakens an otherwise hardened setup.
  5. AI-assisted development needs a human in the loop: I used an AI coding assistant heavily for scaffolding, but every fix, test, and architectural call went through my own hands (full declaration in the repo README).

Links
Repository: https://github.com/Ikhsaaan334/hydrasec/
Demo video: https://youtu.be/---Ny7KHdEk