An open-source diagnostic toolkit for troubleshooting existing Rocket.Chat deployments.
Velreon helps administrators and support teams diagnose common Rocket.Chat deployment issues using read-only checks and deterministic diagnostic rules.
It connects to an existing deployment, collects a bounded set of evidence, evaluates that evidence, and produces clear diagnostic results and reports.
Velreon is an independent community project and is not an official Rocket.Chat product.
Diagnose first. Explain second. Collect evidence throughout.
Every diagnostic check produces one of four verdicts, and UNKNOWN is a
first-class, legitimate outcome — not an error to be hidden:
- PASS — the check ran and the evidence matches the expected-healthy pattern.
- WARN — the check ran and found a known risk factor, not itself a failure.
- FAIL — the check ran and the evidence matches a known-broken pattern.
- UNKNOWN — the check could not run, or the available evidence is insufficient to reach a verdict. This is never hidden or inferred around.
- Connects, read-only, to a Rocket.Chat deployment the administrator already runs and controls.
- Collects a bounded, declared set of evidence (see
docs/evidence-contract.md). - Evaluates that evidence against versioned, auditable rules and reports PASS/WARN/FAIL/UNKNOWN per check, separating observed evidence from interpretation from recommendation.
- Optionally packages a redacted, previewable, local support bundle — only on explicit request; nothing is transmitted automatically.
It does not provision Rocket.Chat or MongoDB, manage Docker/Kubernetes
lifecycle, reproduce customer issues, create disposable environments, run
destructive commands, modify configuration automatically, collect private
messages/passwords/tokens/private keys, send data anywhere by default, or
behave as an AI chatbot. See
docs/security-boundary.md for the full,
explicit boundary — including which guarantees are Velreon's own versus
which depend on credentials and environment the administrator controls.
| Command | Purpose | Network | Changes anything |
|---|---|---|---|
velreon check |
Collect evidence + evaluate rules, print a human-readable result per rule | target only | no |
velreon collect |
Collect evidence only — no rule evaluation, no PASS/WARN/FAIL/UNKNOWN verdict — and render it as versioned JSON | target only | writes a local file only if --output/-o is given |
velreon report |
Collect evidence + evaluate rules, render the versioned JSON report | target only | writes a local file only if --output/-o is given |
velreon bundle |
Collect evidence + evaluate rules, preview, then (on confirmation) build a redacted local support archive | target only | writes one local file, only after confirmation |
velreon rules list |
List loaded diagnostic rules | none | no |
velreon version |
Print binary + rule-pack version | none | no |
All four data-producing commands share one orchestration path
(internal/cli/diagnose.go): connector → collector → evidence → redaction,
plus rule evaluation for check/report/bundle. What differs is only what
each one does with the result:
collectgathers evidence and stops there — useful for inspecting exactly what a collector can see, independent of any diagnostic verdict.checkevaluates that evidence against the rule pack and prints a PASS/WARN/FAIL/UNKNOWN result per rule.reportdoes the same evaluation and renders it as the versioned JSON report instead of terminal text.bundletakes that report plus the evidence it came from and packages both into a redacted, shareable archive.
check/collect/report/bundle all run the same rule pack by default
(every shipped rule) and share the same selection/output flags:
| Flag | Applies to | Meaning |
|---|---|---|
--rule <id> (repeatable) |
check, collect, report, bundle | run only this rule ID |
--category <name> (repeatable) |
check, collect, report, bundle | run only rules in this category |
--oplog-warn-hours <n> |
check, collect, report, bundle | override the MongoDB oplog-window WARN threshold (default 24) — has no effect on collect, which never evaluates rules, but is accepted for flag consistency |
--output / -o <path> |
collect, report, bundle | write to this path instead of stdout / instead of the default bundle filename |
--yes |
bundle | skip the interactive confirmation prompt (for CI) |
--force |
bundle | allow overwriting an existing file at --output |
--keep-hostnames |
bundle | retain network identifiers (hostnames/IPs) in the bundle instead of redacting them |
Every diagnostic's target/credentials are read once from environment variables — never a CLI flag, so nothing sensitive ends up in shell history or a process listing:
| Variable | Used by |
|---|---|
VELREON_MONGO_URI |
MongoDB (replica-set health, migration state) |
VELREON_RC_URL |
Rocket.Chat's own base URL (REST settings, reverse-proxy probe, and — unless VELREON_TLS_HOST overrides it — the TLS probe's host) |
VELREON_RC_USER_ID / VELREON_RC_AUTH_TOKEN |
Rocket.Chat REST API credentials (Personal Access Token) |
VELREON_TLS_HOST |
optional explicit host:port for the TLS probe |
VELREON_LDAP_URI, VELREON_LDAP_BIND_DN, VELREON_LDAP_PASSWORD, VELREON_LDAP_BASE_DN, VELREON_LDAP_FILTER |
LDAP bind sanity check |
Only the categories the selected rules actually need are collected — e.g.
--rule mongodb-replicaset-health never touches the REST API or LDAP.
Anything not configured this run reports UNKNOWN with a stated reason;
nothing is ever guessed.
# Run every shipped diagnostic and print a human-readable result per rule
velreon check
# Run only the MongoDB diagnostic
velreon check --rule mongodb-replicaset-health
# Collect every category's evidence (no diagnostic verdict) as JSON
velreon collect
# Collect only MongoDB evidence
velreon collect --category mongodb
# Collect only TLS evidence
velreon collect --category tls
# Collect evidence to a file instead of stdout
velreon collect --output evidence.json
# Render the full versioned JSON report to stdout
velreon report
# Render it to a file instead
velreon report --output report.json
# Preview, then (after confirming) build a redacted support bundle
velreon bundle --output velreon-bundle.zip
# Same, without the interactive prompt — for CI/non-interactive use
velreon bundle --output velreon-bundle.zip --yesgo build -o bin/velreon ./cmd/velreon
./bin/velreon versiongo test ./...No test in this repository spins up a live Rocket.Chat or MongoDB instance —
see testdata/README.md.
cmd/velreon/ CLI entrypoint
internal/cli/ (done) command dispatch, diagnostics orchestration (connector -> collector ->
evidence -> rule engine -> report/bundle), check/collect/report/bundle commands
internal/connector/ (done) RC REST client, read-only Mongo client, proxy/TLS probes, LDAP
internal/collectors/(done) all 8 categories — collection only, no diagnostic decisions
internal/evidence/ (done) typed, allowlisted, sensitivity-tagged evidence structs
internal/redaction/ (done) schema-driven redaction engine + secondary pattern pass
internal/rules/ (done) YAML rule loader, validator, and step-execution engine
internal/findings/ (done) Finding type
internal/report/ (done) versioned JSON report generator
internal/bundle/ (done) manifest + redacted evidence + report, packaged as a ZIP archive
rules/ (done, all 8 rules) shipped rule packs — YAML data, plus embed.go,
the one Go file here (compile-time embedding)
testdata/ empty by design — see testdata/README.md for why
docs/ design and security documentation, plus rule-authoring.md
- Phase 1 (done): project skeleton, CLI stubs, version handling, CI.
- Phase 2 (done): evidence & redaction contract —
docs/evidence-contract.mdanddocs/security-boundary.md, the typed and allowlisted evidence structs (internal/evidence), and the schema-driven redaction engine with a secondary pattern-based pass (internal/redaction) — all implemented and covered by adversarial tests. No collector or live connectivity yet. - Phase 3 (done): target connector — a read-only
RESTConnector(Info,Setting, allowlisted setting IDs only) and an optional read-onlyMongoConnector(Ping,ReplSetStatus,BuildInfo,OplogWindow), both ininternal/connector, plus fake in-memory implementations of both ininternal/connector/connectortestfor Phase 4+ collector tests. - Phase 4 (done): first full vertical slice —
internal/collectors/mongodb.gocollectsMongoDBEvidencevia the Phase 3 connector.velreon checkran it end to end against a hand-written Go evaluation function (since replaced, see Phase 5). The connection string is read once fromVELREON_MONGO_URI, never a CLI flag, never persisted or logged. - Phase 5 (done): rule engine generalization —
internal/rulesloads, strictly validates (fail closed), and executes declarative YAML rules against evidence already in anevidence.Store, withrequires_passstep dependencies, a small fixed assertion language (equals,not_empty,any_equals,gte), and version/deployment applicability (NOT APPLICABLEvs. a real, countedUNKNOWNkept distinct). The Phase 4 hand-writtenEvaluateReplicaSetHealthis gone, replaced byrules/mongodb-replicaset-health.yaml— proven behaviorally equivalent byinternal/rules/mongodb_rule_test.go, which runs the actual shipped, embedded rule pack. Seedocs/rule-authoring.mdfor the schema. - Phase 6 (done): the remaining 6 collectors and rules — proxy,
TLS, SMTP, OAuth, SAML, LDAP, and upgrade/migration (8 rules total; OAuth
and SAML stayed separate evidence types and rule files as planned). Three
new connectors (
ProxyConnector,TLSConnector,LDAPConnector) and one newMongoConnectormethod (MigrationState) were added, each verified against Rocket.Chat source/docs before implementation rather than guessed — seedocs/rule-authoring.mdanddocs/evidence-contract.mdfor what was confirmed versus deliberately leftUNKNOWN. The engine gained one new assertion operator (days_until_gte, for certificate expiry).checkstill wired only the MongoDB rule into its default run at the end of this phase; wiring the rest into the CLI was deferred to Phase 9 rather than expanding Phase 6's scope into a CLI redesign. - Phase 7 (done): report generator (
internal/report) — a deterministic, versioned JSON report consuming already-produced findings/evidence, with no connector/rule-engine access of its own; every rendered string passes through the existingredaction.Sanitizefail-safe. - Phase 8 (done): bundle generator (
internal/bundle) — packages a report plus Bundle-target-redacted evidence into a ZIP archive (manifest.json,report.json,evidence/*.json), with path-traversal/ duplicate/absolute-path-safe archive handling on both write and read. - Phase 9 (done): CLI integration —
internal/cli/diagnose.gois the one orchestration pathcheck/report/bundleall share: load the rule pack, select the requested rules (--rule/--category), collect exactly the evidence those rules declare they need (Rule.RequiresEvidence), evaluate with the existing rule engine, and hand the results toreport.Generate/bundle.Generate.bundleadds a mandatory preview-and-confirm step (--yesto skip it for CI,--forceto allow overwriting an existing output file). No diagnostic, evidence- shape, or redaction logic was added tointernal/cliitself. - Phase 10 (this state): standalone evidence collection —
velreon collectnow uses the samerunDiagnosticsorchestration path as check/report/bundle, but only renders what's already in theevidence.Store(each category's typed struct, already Local-redacted) as versioned JSON — it never callsrules.Evaluate's result for anything, so it can never carry a PASS/WARN/FAIL/UNKNOWN verdict. An unavailable category is always listed explicitly, with its stated reason, never silently omitted. - Phase 11–12: documentation, name validation, release preparation, and the v0.1.0 release are complete.
Velreon is the name of this open-source Rocket.Chat deployment diagnostics tool. It is an independent community project and is not an official Rocket.Chat product. The project was released as v0.1.0; nothing in the codebase's architecture, package layout, or file formats depends on the project name.
MIT — see LICENSE. Velreon is an independent community project;
it is not affiliated with or endorsed by Rocket.Chat Technologies Corp., and
this license applies to Velreon's own source code only, not to Rocket.Chat
itself.