Getting Started
NullReport is a self-hosted, AI-assisted penetration-test report generator. You write your sections, track structured findings with CVSS, and export a polished, branded DOCX, all from one Docker stack on your own infrastructure. There's no cloud and no multi-tenancy, so your data stays on your machine.
Clone the repo, set two secrets, and run docker compose up -d --build. Jump to
Install and you'll be logged in within five minutes.
Choose your tier
The tier is baked into the Docker image at build time (a TIER build argument). A Pro or
Team license on a free image won't unlock anything, because the image and the license have to
match. There's more on that in Licensing.
Need a custom seat count? Get in touch.
Prerequisites
- Docker and Docker Compose (Docker Desktop on macOS/Windows includes both).
- Two secrets you'll generate below: a
JWT_SECRETand anENCRYPTION_KEY. - Nothing else. Postgres runs as a container, so you don't install a database yourself.
Install
- Build from source
- Prebuilt images
# 1. Clone
git clone https://github.com/izzy0101010101/nullreport.git
cd nullreport
# 2. Create your .env from the example
cp .env.docker.example .env
# 3. Generate the two required secrets
echo "JWT_SECRET=$(openssl rand -hex 32)" >> .env
echo "ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env
# 4. Pick a tier (free | pro | team) and bring it up.
# TIER selects which image is built.
TIER=free docker compose up -d --build
Then open http://localhost:3000.
Prefer not to build? Use the production compose file, which pulls published images from GHCR instead of building locally:
git clone https://github.com/izzy0101010101/nullreport.git
cd nullreport
cp .env.docker.example .env
echo "JWT_SECRET=$(openssl rand -hex 32)" >> .env
echo "ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env
# TIER picks the image tag that gets pulled
TIER=free docker compose -f docker-compose.prod.yml up -d
This pulls ghcr.io/izzy0101010101/nullreport-backend:free and the matching frontend image.
Swap free for pro or team to run a paid build.
JWT_SECRET signs login sessions and ENCRYPTION_KEY encrypts stored AI API keys with
AES-256-GCM. ENCRYPTION_KEY must be exactly 64 hex characters (32 bytes), which openssl rand -hex 32 produces. The backend refuses to start with a malformed key. Use unique values per
install and never commit them.
What happens on first boot
The database schema is created automatically, so there's nothing to migrate by hand.
First login
- On first boot the backend creates the
adminaccount with a randomly generated password and prints it to the logs once. Grab it with:(To pin a known password instead, setdocker compose logs backend | grep -A1 "First run detected"ADMIN_INITIAL_PASSWORDin your.envbefore the first boot.) - Open http://localhost:3000 and log in:
- Username:
admin - Password: the value from the logs (or your
ADMIN_INITIAL_PASSWORD)
- Username:
- You're immediately required to set a new password (minimum 6 characters). This only happens once.
- You land on the Reports dashboard, already populated with a demo report so you have something to explore.
The login form, then the "change your password" screen shown on first sign-in.
The first-run password is shown in the logs only once. Save it somewhere safe, complete the forced change on first login, and don't expose the app to the internet without a reverse proxy and TLS in front of it.
Activate a paid tier
Licensing is driven by the LICENSE_KEY environment variable. There's no in-app field for it.
After purchasing, you'll receive a license key:
-
Add it to your
.env:LICENSE_KEY=NR-PRO-xxxxxxxx # the key from your purchase email / portal -
Make sure your image tier matches the license (build or pull the
proorteamimage; see Install). -
Restart with
docker compose up -d.
On startup the backend activates the key against the license server, caches a signed token, and
unlocks the matching tier. Leaving LICENSE_KEY empty runs the free tier. Full details,
including the offline grace period and machine binding, live in Licensing.
What ships out of the box
First boot seeds a working starting point:
- A demo report, "Example: Acme Corp Web App Pentest", with sections and findings so you can see a complete report immediately.
- A DOCX export template, the "Templating Showcase Template", ready to export against.
- One example finding template, SQL Injection, to show the format. Build your own library from there.
Quick walkthrough
The fastest path from zero to a finished report:
- 1. Create
- 2. Write
- 3. Findings
- 4. Export
From the Reports dashboard, click New Report, give it a title and client, pick the seeded report template, and click Create. See Reports.
On the Content tab, click a section in the sidebar and write in the rich-text editor. Add new sections by typing a name in Add Section. See Sections.
On the Findings tab, click Add Finding and start from the template browser or from scratch. Set severity, run the CVSS calculator, and fill in the fields. See Findings.
Click Export, choose your template, and download the DOCX. Empty fields trigger a warning you can dismiss. See Exporting.
On Pro and Team, you can point the AI features at a local Ollama model instead of a cloud
key. The repo ships a docker-compose.ollama.yml overlay that bundles Ollama and wires it up:
TIER=pro docker compose -f docker-compose.yml -f docker-compose.ollama.yml up -d --build
Data, backups, and updates
Your data lives in two Docker volumes, and you should back up both:
| Volume | Holds |
|---|---|
db-data | The Postgres database (reports, findings, users, templates metadata) |
app-data (/data) | License cache, the machine instance ID, uploaded images, and DOCX template files |
To update:
git pull
docker compose up -d --build # or `--pull always` for prebuilt images
Your volumes are preserved and the schema is reconciled automatically on startup.
docker compose down -v deletes app-data, including the machine instance ID your license is
bound to. After that, re-activation fails until you click Deactivate Machine in the license
portal. See Licensing.
What's next
- Reports for the dashboard and the report editor
- Sections for writing content in the rich-text editor
- Findings for severity, CVSS, and custom fields
- Finding Templates for your reusable vulnerability library
- Report Templates and Template Syntax for your own DOCX exports
- Users & Roles for team management (Team)
- Settings, Search & Navigation, Licensing, and Exporting