Skip to main content

Licensing

NullReport unlocks paid features with a license key you set as an environment variable. There's no in-app license screen; the key is read at startup and verified against the license server. This page covers how that works, what each tier includes, and how to manage it.

How it works

  1. Pick a tier and pay on the NullReport website.
  2. You receive a license key by email and in the customer portal.
  3. Set it as LICENSE_KEY in your .env or compose file and restart.
  4. Your tier is detected at startup and re-checked in the background.

Between checks, NullReport verifies your cached, signed token locally, so it keeps working offline within a 7-day grace period.

Tiers

Free
Pro
TeamMost popular
Price
$0
$39/mo
$99/mo + $30/seat
Users (seats)
1
1
3 (+ extra seats)
Reports
Unlimited
Unlimited
Unlimited
Finding-template library
DOCX export
Custom DOCX templates
1
Unlimited
Unlimited
AI drafting & polish
Roles (Admin / Editor / Viewer)
Comments & activity feed
Real-time collaboration
  • Free: solo penetration testing with unlimited reports, findings, and DOCX export. 1 user, 1 report template.
  • Pro: adds AI drafting and polishing (Ollama, OpenAI, Claude, or Gemini). Still single-user.
  • Team: multi-user with Admin, Editor, and Viewer roles, report assignment, comments, an activity feed, and real-time field locking. 3 seats included; add more at $30/seat.

Support is community and GitHub Issues on Free; Pro and Team add email support.

Setting your license key

There is no license field inside the app. The key is an environment variable read at startup.

.env
LICENSE_KEY=your-license-key-here
docker compose up -d

On startup NullReport activates the key and detects your tier. Leaving LICENSE_KEY empty runs the free tier.

The image tier and the license tier must match

Your tier is also baked into the Docker image at build time (the TIER arg). A Team license on a free image won't unlock anything; you'll just see an "upgrade your image" banner. Build or pull the matching image (see Getting Started).

What a license token contains

When you activate, the server returns an RS256-signed JWT holding:

  • Your tier (Free, Pro, or Team)
  • Allowed seats
  • The instance ID it's bound to
  • An expiry (30 days from issue)

NullReport verifies the signature locally against an embedded public key. The token is machine-bound, valid only on the install it was issued for.

Auto-refresh

Tokens last 30 days and stay current on their own. NullReport activates on every startup, and a background timer re-activates on a fixed ~25-day interval. As long as your subscription is active, a fresh token is cached automatically. You'll never notice it unless something goes wrong.

Grace period and downgrade

What happens when a check can't confirm your tier depends on why:

SituationWhat happens
Server unreachable (network error / 5xx)7-day grace: your cached, still-valid token keeps the paid tier. After 7 days without a successful check, you fall back to Free.
Server rejects the key (cancelled, revoked, suspended, wrong machine)Immediate downgrade to Free, no grace.
Your data is never deleted

Downgrading only locks paid features. Extra users are locked out (not removed), templates beyond the free limit are hidden (not deleted), and reports, findings, and DOCX export all keep working. You can always export.

Upgrading and downgrading

Because the tier is built into the image, upgrading means switching to the new-tier image and supplying the matching key:

docker-compose.yml
# from
image: ghcr.io/izzy0101010101/nullreport-backend:free
# to
image: ghcr.io/izzy0101010101/nullreport-backend:pro
# update LICENSE_KEY in .env, then
docker compose pull && docker compose up -d

Do the same for the nullreport-frontend image, or rebuild from source with TIER=pro docker compose up -d --build. All data is preserved.

Offline and air-gapped installs

NullReport verifies the cached token locally, so it runs offline within the 7-day grace period. It still reaches the server on every startup and on the periodic refresh. If it can't reach the server for more than 7 days, paid features fall back to Free until the next successful check. For fully air-gapped environments, contact us about extended key validity.

FAQ

Can I use one license on multiple machines?

No. Each key is machine-bound and activates one install at a time. Team's seat count is about how many users that one install supports, rather than how many machines. To move machines, deactivate first (below).

What if my server can't reach the license server?

Your cached, still-valid token keeps the paid tier for a 7-day grace period, then re-activates automatically once you're back online. Past 7 days unreachable, you fall back to Free until the next successful check.

Can I transfer my license to a new server?

Licenses are machine-bound, so you can't just copy files. The key lives in the LICENSE_KEY environment variable rather than in ./data, and a new machine or wiped data volume gets a new instance ID the token won't match. Click Deactivate Machine in the license portal, then bring NullReport up on the new machine with the same LICENSE_KEY and let it re-activate.

Lost your key, or need billing?

Open your customer portal via the Lemon Squeezy magic link emailed to you to view or re-copy your key and manage billing (Lemon Squeezy is our merchant of record).

Do you collect any usage data?

No telemetry, no usage tracking, and no report data sent anywhere. The only outbound calls are to the license server to activate and refresh your key.