Speaking up takes courage. Staying silent shouldn't be the safer option.
Live demo · Documentation · Changelog
A self-hosted internal reporting channel that meets the German HinSchG and EU Directive 2019/1937: the reporter leaves no trace — no IP address, no account, no exact time.
Any company with 50 or more employees, and every public authority, must offer one. Free, open source, no vendor lock-in.
git clone https://github.com/openwhistle/OpenWhistle.git && cd OpenWhistle
cp .env.example .env # SECRET_KEY, ENCRYPTION_KEY: openssl rand -hex 32 each
docker compose up -d
docker compose logs app | grep "Setup token" # then open http://localhost:4009/setupPlain HTTP from another device needs SECURE_COOKIES=false; keep the default behind HTTPS.
Production setup, every setting, reverse proxy: openwhistle.net/en/docs.
Every one of them is documented on openwhistle.net/en/docs.
- No trace — no IP address in any log; times the reporter causes are stored as the day only
- Proxy warning — a reporter whose request reached the app with an address header is told the proxy may log it
- Case number + UUID4 PIN — no account, no email; a correct pair always opens the case
- Anonymous or confidential — a confidential name is encrypted, shown to the case handler only on audited request
- Submission wizard — guided steps, Redis-backed draft encrypted with a key only in the reporter's cookie
- Two-way messages (HinSchG § 17) and file attachments with GPS, EXIF and author metadata stripped
- Optional virus scan — ClamAV, fail-closed
- Tor onion address —
ONION_LOCATIONadds theOnion-Locationheader and a note for monitored networks
- HinSchG deadlines — 7-day acknowledgement and 3-month feedback, tracked and reminded
- Status workflow —
received → in_review → pending_feedback → closed, validated server-side - Assignment, internal notes, case linking, search by number or content, custom categories, locations
- PDF export with the SLA section; dashboard statistics
- Slack, Teams and email notices — batched; webhooks carry counts only, e-mail the case numbers, never content
- Telephone-channel guide — HinSchG § 16 Abs. 3 checklist
- Mandatory TOTP for every admin; secrets stored encrypted
- Roles —
SUPERADMIN,ADMIN,CASE_MANAGER, object-level authorization on every report - Database, LDAP / Active Directory or OIDC login — PKCE, verified ID token
- Account recovery — own password page, authenticator reset, host script, password-spraying alarm
- 4-eyes deletion, audit log with CSV export, data retention (default 3 years), hard deletion
- Encryption at rest — per-report envelope encryption, separate
ENCRYPTION_KEYwith rotation - Hardened HTTP — nonce-based CSP, security headers, absolute session lifetime, TLS by default
- Hardened containers — read-only root, no capabilities, base images pinned by digest
- Web setup wizard with one-time setup token
- Multi-tenancy — isolated organisations, per-organisation reporting link
- S3-compatible attachment storage, structured JSON logs,
/healthfor Kubernetes probes - Helm chart, Ansible role, multi-arch images on GHCR, Docker Hub and Quay.io
- Update check and install count — both opt-in; the update check sends nothing about the instance, the count a random ID and the version; while the count is off, the dashboard asks once per update
- Five languages — English, German, French, Spanish, Brazilian Portuguese; WCAG 2.1 AA; light and dark
- No external calls — self-hosted fonts, no CDN, no tracking (GDPR)
- "Signal" design system —
DESIGN.md
| Registry | Image |
|---|---|
| GitHub Container Registry | ghcr.io/openwhistle/openwhistle |
| Docker Hub | kermit1337/openwhistle |
| Quay.io | quay.io/jp1337/openwhistle |
Multi-arch (amd64, arm64). GHCR images are signed with Cosign; verify them.
Every image is scanned with grype before it is tagged: any fixable
vulnerability fails the build. The reviewed exceptions are in .grype.yaml.
demo.openwhistle.net — user demo, password demo, TOTP 000000. Resets every 6 hours.
Designed for the HinSchG, EU Directive 2019/1937 and the GDPR. The duties, one by one: compliance pages. OpenWhistle is a tool; the operator stays responsible for the deployment.
Setup and review checklist: CONTRIBUTING.md. Documentation changes go to openwhistle/website. A vulnerability: not a public issue — see SECURITY.md.
GPL-3.0 — see LICENSE. Developed in free time; sponsor it if it helps.