CyberCLI

Operator wiki

How to actually
use CyberCLI.

Self-contained recipes for the things real operators do. Each one tells you what you'll end up with, walks the dashboard or CLI steps, and flags the easy-to-miss bit. Cmd-F your task.

Jump to

Install CyberCLI on a fresh host

~2 min

For: First-time operator

One-line install. Works on Ubuntu 22.04+, Debian 11+, RHEL/Rocky 9+, macOS 13+. The script verifies a Cosign-signed SHA256SUMS before extracting any binary.

curl -sSfL https://cybercli.com/install.sh | bash

After install:

  1. Run `cybercli init` once to scaffold the config dir at ~/.cybercli (vault, keys, defaults).
  2. Run `cybercli dashboard` to start the local SOC at http://localhost:8088. The first page asks you to set an admin token.
  3. Open the dashboard in your browser. Everything else can happen from there.
Note

The install script is idempotent. Re-run it to upgrade in place — your vault, license, and connectors all survive.

Onboard Wazuh (existing deployment)

~3 min

For: Operator with a running Wazuh 4.x manager + indexer

Wazuh is the OSS XDR keystone — alerts, agent inventory, write-back rule deployment. CyberCLI talks to the Manager API on :55000 and the Indexer (OpenSearch) on :9200. Both are required because Wazuh 4.x stores alerts on the indexer, not the manager.

  1. Open the dashboard → Connectors → click `+ Onboard connector`.
  2. Pick Wazuh from the wizard. The form asks for two paths (Manager API + Indexer), each a step.
  3. Manager API step: paste your manager base URL (e.g. `https://wazuh.example:55000`), API username, and password. Wazuh's JWT bootstrap runs against `/security/user/authenticate`; the wizard verifies a real `GET /agents` before vault write.
  4. Indexer step: paste your indexer URL (`https://wazuh.example:9200`) + admin user + password. The wizard verifies `≥1 alert document` lands within the lookback window — that's the live-receipt proof, never inferred from process-up.
  5. Click Submit. On success the wizard shows the next-step CTA: `Enrol syslog now →` (Wazuh forwards manager-level events over TCP 6514).
Note

Self-signed TLS? Toggle `Verify TLS` off in the optional step. Runtime, smoke, and the verification probe all read the same vault key, so the setting can't drift across surfaces.

Install Wazuh on this host (greenfield)

~10 min

For: Operator on a fresh Ubuntu/Debian/RHEL host

No existing Wazuh? CyberCLI's dashboard wraps the official Wazuh quickstart with a resource-budget gate, system-impact disclosure, and auto-vaulting of the generated admin credential.

  1. Dashboard → Connectors → `+ Install Wazuh`.
  2. Pre-flight panel shows OS, root/NOPASSWD-sudo status, existing-install detection, and a resource-budget verdict (green/yellow/red). RED refuses without a force-overcommit override.
  3. Set the `Manager host` field (defaults to your host's primary IP — keep it for single-host deploys, or change to a tailnet hostname for split deploys).
  4. Click `Install (~10 min)`. A live progress panel streams the installer output line by line.
  5. On completion: credentials auto-land in the CyberCLI vault. The Wazuh connector becomes live on its next 30s poll.
Note

What this actually does: adds the apt/dnf repo, installs wazuh-manager + wazuh-indexer + wazuh-dashboard, opens ports 443/1514/1515/9200/55000, enables 3 systemd units, and parses the admin password out of the installer output.

Onboard Unifi (UDM / UCK / Network Application)

~5 min

For: Operator with an existing Unifi controller

Unifi has two ingest paths: the local Network Integration API (inventory + control actions) and Remote Syslog (firewall/DPI/IPS/association events). You'll wire both.

  1. Generate an API key in your controller: Settings → Control Plane → Integrations → Create API Key. Scopes: read events, read clients, write block, write deauth.
  2. Find your Site UUID (NOT the display slug): Settings → Sites. The UUID is what the API accepts.
  3. Dashboard → Connectors → `+ Onboard connector` → Unifi.
  4. Paste: controller URL (`https://10.0.0.1`), API token, Site UUID, verify_tls (default true; flip to false ONLY for self-signed UDM/UCK).
  5. Submit. The wizard probes `GET /sites` — non-zero sites visible confirms the token has scope.
  6. On success: click `Enrol syslog now →`. Pick `unifi` and paste the UDM's LAN IP. Then in the controller UI: Settings → System → Remote Syslog → Host: this CyberCLI host, Port 514.
Note

Cloud `api.ui.com` keys do NOT work here — the Integration API is local to your controller. Always use the device IP.

Onboard pfSense (or OPNsense — same pack)

~3 min

For: Operator with a pfSense or OPNsense firewall

pfSense is syslog-only — there's no API path to wire. OPNsense is byte-identical at the filterlog wire format; CyberCLI accepts `opnsense` as an alias that resolves to the pfSense pack.

  1. Dashboard → Connectors → `+ Enrol syslog` (not Onboard — pfSense has no API step).
  2. Pick `pfsense` (or `opnsense`) and paste the firewall's LAN IP.
  3. Submit. The dashboard shells out to `cybercli setup add-syslog-source --connector pfsense --source-ip <ip>`, writes a Vector conf.d, validates it, hot-reloads (no dropped events), and records a SourceRegistry binding.
  4. In pfSense UI: Status → System Logs → Settings → Remote Logging. Enable, set the remote server to your CyberCLI host:514, check `Firewall events`. Save.
  5. Wait ~30 seconds. The wizard's `/connectors` row turns green when the first event arrives.

Onboard Microsoft 365 / Entra ID

~5 min

For: Pro tier operator with M365 tenant admin rights

M365 pulls sign-in events, directory audits, and Defender/Sentinel alerts via Microsoft Graph using OAuth2 client credentials. Requires an Azure AD app registration with three admin-consented application permissions.

  1. In Azure Portal → Microsoft Entra ID → App registrations → New registration. Name it `CyberCLI`. Pick `Accounts in this organizational directory only`. Skip the redirect URI.
  2. On the new app's Overview: copy the Application (client) ID and Directory (tenant) ID. Both are GUIDs.
  3. API permissions → Add → Microsoft Graph → Application permissions → check `AuditLog.Read.All`, `Directory.Read.All`, `SecurityAlert.Read.All`. Then click `Grant admin consent for <tenant>`.
  4. Certificates & secrets → New client secret → 24-month expiry. Copy the VALUE (not the Secret ID — common mistake).
  5. Dashboard → Connectors → `+ Onboard connector` → Microsoft 365.
  6. Paste tenant ID, client ID, client secret. Wizard probes `GET /v1.0/organization` — successful tenant fetch confirms the registration is consented.
Note

Common errors: AADSTS7000215 means you pasted the Secret ID instead of the Value. AADSTS70011 means admin consent wasn't granted. The wizard surfaces these with operator-friendly hints.

Send CYCON 1/2 alerts to Slack

~3 min

For: Operator with a Slack workspace

CyberCLI routes alerts to channels by CYCON level. Slack is the default homelab + small-team channel. The pattern: create an incoming webhook → store its URL in the vault → wire a destination → enable it for CYCON 1+2.

  1. In Slack: api.slack.com/apps → Create New App → From scratch → pick a workspace.
  2. Incoming Webhooks → Activate → Add New Webhook → pick the channel. Copy the webhook URL.
  3. On the CyberCLI host: `cybercli vault put slack_ops` → paste the webhook URL when prompted. The vault encrypts and stores under the `slack_ops` key.
  4. Dashboard → Notifications → `+ Add channel` → Slack.
  5. ID: `slack-ops`. Label: `Ops channel`. Webhook URL (vault ref): `vault:slack_ops`. Submit.
  6. Routing → CYCON 1 (CRITICAL) → toggle Slack on. CYCON 2 (ENGAGED) → toggle on. Lower levels stay off unless you want pager fatigue.
  7. Test send: from the Notifications row, click `Test`. A test message should land in your Slack channel within a second.
Note

Always use `vault:<key>` references in channel configs — raw secrets pasted inline are masked as `[redacted]` in the GET response (and audit-row diffs), but the vault ref pattern keeps secrets out of the destination store entirely.

Page on-call via PagerDuty for CYCON 1

~3 min

For: Pro+ tier operator with a PagerDuty service

PagerDuty is the Pro-tier paging channel. CYCON 1 fires a Trigger event; the on-call human acks in PagerDuty, which round-trips back via the native-ack webhook to stop our repeat loop.

  1. In PagerDuty: Services → your service → Integrations → Add → Events API v2. Copy the integration key.
  2. On the host: `cybercli vault put pagerduty_routing` → paste the key.
  3. Dashboard → Notifications → `+ Add channel` → PagerDuty. Events API v2 routing key (vault ref): `vault:pagerduty_routing`. Submit.
  4. Routing → CYCON 1 → toggle PagerDuty on. (Optional: turn Slack OFF for CYCON 1 so only the pager fires — phone + Slack double-paging is noisy.)
  5. In PagerDuty: Services → your service → Integrations → Add → Webhook v3. URL: `https://<your-cybercli-host>/v1/delivery/ack/native/pagerduty`. This lets the on-call ack on their phone and stop our 5-minute repeat loop too.

Silence notifications during a maintenance window

~1 min

For: Any operator about to do something noisy

Maintenance windows suppress notification delivery without silencing detection. Audit chain still gets every signal; the channels just don't ring. Use this before patching firewalls, rebooting hosts, or running a vuln scan.

  1. Dashboard → Notifications → Maintenance windows → `+ New window`.
  2. Pick start + end. Reason is required — surfaces in the post-incident audit log.
  3. Save. Every notification that would fire during the window gets a `NOTIFICATION_MAINTENANCE_SUPPRESSED` audit row instead of going out.
  4. Window auto-ends. Notifications resume on the next signal.

Something's wrong — run the doctor

~30 sec

For: Anyone whose dashboard is showing a red light

`cybercli doctor` is the structured self-test. It walks every wire (vault, license, connectors, syslog substrate, AI lanes, audit chain, delivery channels) and reports each as ✓ / ⚠ / ✗ with a concrete fix line.

cybercli doctor

What it checks:

  1. Vault: master key resolvable, vault.json present + chmod 600.
  2. License: present, signature valid, kid matches engine's trusted pubkey, expiry not in past.
  3. Connectors: each adopted instance — vault credentials present, last poll success, path health current.
  4. Syslog substrate: Vector running, conf.d files all validate, enrolled sources reachable on the wire.
  5. AI lanes: configured lane providers respond (frontier ping or local ollama up).
  6. Audit chain: hash chain unbroken from genesis to head.
  7. Delivery: every destination test_send succeeds (sandboxed — no real send).
Note

Doctor runs every connector probe live; expect ~5-15 seconds of work. The dashboard's `/doctor` page shows the same content + live re-run button.

Upgrade to a new CyberCLI version

~1 min

For: Anyone running a non-current version

Re-running the install script is the upgrade path. The binary, the connectors, and the dashboard refresh in place; the config dir, vault, license, and connector state survive.

curl -sSfL https://cybercli.com/install.sh | bash

Then restart the dashboard:

systemctl restart cybercli-dashboard  # or: pkill -HUP cybercli
Note

Migration safety: every D1 / SQLite migration is forward-only, idempotent on re-run, and atomic at apply time. Failed migrations are non-destructive (the partial state is rolled back before the new schema becomes effective).

Recipe you need isn't here

Tell us what to write next.

The recipes above cover the v1 ship surface. New recipe requests, harder edge cases, or feedback on what's confusing — drop a line.