Introduced: v8.0.0 (audit NL search). v8.1.0 + v8.2.0 add vulnerability triage and incident triage. Status: Off by default. Bring your own API key (BYOK) or run a local Ollama instance.
Docker Dash's AI features translate noisy data into ranked, explainable decisions — and never take actions on your behalf. Every call is audited. Every payload is redacted before it leaves the host. You can disable the entire feature category with one toggle and verify zero outbound calls in audit_log.
If that one-sentence-to-defend matches your operational stance, this doc walks you through enabling it.
1. Open Settings → AI tab (admin only)
2. Pick a provider:
- Anthropic Claude (recommended for cloud — fast, cheap, good)
- OpenAI GPT
- Ollama (recommended for privacy — runs on your hardware)
3. For cloud providers: paste your API key
For Ollama: paste the endpoint URL (default: http://localhost:11434)
4. Pick a model (recommended one is pre-selected)
5. Click "Test connection" → should turn green
6. Tick "Enable AI features" → Save
7. Try it: System → Audit → type "actions by admin in the last 24 hours" in the magic-wand search box
That's it. No account creation on our side. No telemetry. No data sent to us. Provider sees only the post-redaction prompt; we see only token counts in our own audit log.
- Recommended model:
claude-haiku-4-5-20251001($1 / $5 per Mtok) - Cost example: 100 NL audit searches/day at ~250 tokens each ≈ $1/month
- Latency: 0.5–2s per call
- Privacy: API inputs not used for training. 30-day default retention; zero-retention with enterprise terms.
- Get a key: https://console.anthropic.com/settings/keys
- Recommended model:
gpt-4o-mini($0.15 / $0.60 per Mtok) - Cost example: 100 NL audit searches/day ≈ $0.30/month
- Latency: 0.5–2s per call
- Privacy: API inputs not used for training (since 2023). 30-day retention.
- Get a key: https://platform.openai.com/api-keys
- Recommended model:
qwen2.5-coder:7b(≈ 4-5 GB on disk, ≈ 6 GB RAM at runtime) - Cost: $0 — your hardware does the work
- Latency: 1–10s on a Linux box with 8 GB RAM (CPU); sub-second on GPU
- Privacy: Nothing leaves your network. Best fit for sovereignty-critical deployments.
- Setup:
ollama.ai/download→ollama pull qwen2.5-coder:7b→ollama serve→ pastehttp://localhost:11434in Docker Dash Settings
If your host doesn't have GPU and you want chat-speed responses, pick a cloud provider. For batch use (audit search runs in 1-3s and you can tolerate that), Ollama is great.
- The query/data for that specific call (after redaction — see §4)
- Provider/model identifier (in our local audit log)
- Container logs / inspect content (this release — v8.0.0 only ships NL audit search; future features have explicit redaction policies per feature)
- Stored secrets / registry credentials / encryption keys
- Audit log row content (queries are NL strings; results stay local — we filter rows in Node, not via the LLM)
When enabled = 0 in ai_settings (the initial state after migration), the route handlers refuse to call the provider. The Settings page itself is the only AI surface — no other UI surface invokes AI.
Docker Dash ships zero API keys. You bring your own (or point at your own Ollama). Keys are encrypted at rest using the same AES-GCM helper that protects registry credentials.
Every AI call writes a row to audit_log with action = 'ai_call'. Details include:
provider(anthropic / openai / ollama)model(e.g.claude-haiku-4-5-20251001)inputTokens,outputTokensdurationMsredactions(per-pattern count of what got stripped)payloadHash(SHA-256 of the original prompt, truncated to 8 hex)ok: true | falseerror(truncated, on failure)
The payloadHash is the compliance gold. If a compliance officer ever asks "did you send X to OpenAI?", you hash X locally and compare:
echo -n "the question" | sha256sum | cut -c1-8
# Compare against payloadHash values in audit_logPrivacy-preserving evidence trail without storing the actual prompt.
SELECT
username,
COUNT(*) as calls,
SUM(CAST(json_extract(details, '$.inputTokens') AS INTEGER)) as input_tokens,
SUM(CAST(json_extract(details, '$.outputTokens') AS INTEGER)) as output_tokens
FROM audit_log
WHERE action = 'ai_call'
GROUP BY username;Or in the UI: System → Audit → search box: actions by alice with action ai_call.
Docker Dash applies a defense-in-depth redactor BEFORE any payload reaches the provider. Validated on a hand-built corpus (see plans/spikes-ai-features.md S4): 100% recall, 100% precision on 27 realistic test cases.
| Pattern | Catches |
|---|---|
auth-bearer |
Authorization: Bearer <token> |
connection-string-creds |
postgres://user:pass@host, redis://, etc. (13 schemes) |
env-assignment |
*PASSWORD*=val, *SECRET*=val, *TOKEN*=val, *API_KEY*=val, *ACCESS_KEY*=val, *PRIVATE_KEY*=val, *AUTH*=val (with prefix/suffix tolerance like STRIPE_SECRET_KEY) |
long-token |
High-entropy strings ≥ 32 chars (UUIDs labeled distinctly) |
ipv4 |
Dotted-quad IPs |
email |
Email addresses |
Settings → AI → "Custom redaction patterns" — one regex per line. For site-specific things (internal hostnames, project codenames, etc.). Built-in patterns are always active and can't be disabled.
- It's defense-in-depth, not a guarantee. The doc explicitly says so. The "what gets sent" preview lets you verify the post-redaction payload before any submit (Settings → AI → Privacy panel).
- It doesn't redact natural-language descriptions of secrets ("the password is hunter2" — the value isn't in env-style format).
- Invalid custom regex (catastrophic backtracking) aborts the AI call rather than sending unredacted. Privacy beats utility.
Where: System → Audit page → magic-wand search box at the top.
Examples:
- "show me everyone who deleted containers in the last 7 days"
- "who restarted the redis container yesterday"
- "all actions by alice this week"
- "failed registry pushes in the past hour"
- "any sandbox container created today"
How it works:
- Your query goes through the redactor.
- We send it to the configured provider with a strict JSON schema asking for: actor, action, resource, host, since, until, limit.
- The provider returns a structured filter (validated against the schema — invalid responses are rejected).
- We translate that filter to the existing audit query path. Never NL→SQL — the LLM only emits structured filter fields, never raw query text.
- The parsed filter renders as chips above the result table so you see what the LLM understood. Click "Clear" to reset.
Trust signals: the provider name + latency + match count display next to the chips. If the LLM can't translate your query (gibberish, off-topic), it returns an empty filter and you see all-recent rows — never a confidently wrong filter.
Will rank scan results by real exploitability using EPSS data + LLM reasoning. Roadmap, not yet shipped.
Container restart-loop detection → "Investigate" button on detail page → LLM-narrated diagnosis using inspect + logs + stats. Roadmap, not yet shipped.
| Failure | Behavior |
|---|---|
| Provider not configured | Search box is grayed out with "Enable AI in Settings" tooltip |
| Invalid API key | Toast: "AI provider rejected the API key. Re-enter in Settings → AI." Audit log records the failure. |
| Rate limit (429) | Toast with retry hint. Audit log records. |
| Timeout (15s default) | Toast. Operator can retry. |
| Malformed LLM response | Toast: "AI returned an unexpected response. Try rephrasing." Schema details NOT exposed to user. |
| LLM hallucinates filter | Schema validation drops invalid fields. Empty filter → empty result table → operator sees "no matches" implicitly. Never a confidently wrong filter. |
| Ollama unreachable | Connection error toast. |
| Custom redaction regex invalid | Save rejected with clear validation error before the bad pattern can fire. |
# All endpoints require admin auth. $TOKEN = Bearer token from POST /api/auth/login.
# Read settings (key returned masked)
curl -H "Authorization: Bearer $TOKEN" http://docker-dash:8101/api/ai/settings
# Update settings
curl -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"enabled":true,"provider":"ollama","model":"qwen2.5-coder:7b","endpointUrl":"http://localhost:11434"}' \
http://docker-dash:8101/api/ai/settings
# Test the configured provider's connectivity + auth
curl -X POST -H "Authorization: Bearer $TOKEN" http://docker-dash:8101/api/ai/test
# List supported providers + recommended models (static catalog)
curl -H "Authorization: Bearer $TOKEN" http://docker-dash:8101/api/ai/providers
# Run NL audit search (the v8.0.0 feature)
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"query":"who deleted containers last week"}' \
http://docker-dash:8101/api/audit/ai-searchFor audit NL search specifically, each call sends ~250 tokens of input (system prompt + query + today's date + 161-entry action enum) and gets back ~50 tokens of output (the JSON filter). Per-call cost:
| Provider/model | Per call | 100 calls/day |
|---|---|---|
| Claude Haiku 4.5 | $0.0005 | $1.50/mo |
| GPT-4o-mini | $0.0001 | $0.30/mo |
| Ollama (any model) | $0.00 | $0.00 |
Heavier features (vuln triage, incident triage) will burn more — but each will document its own cost profile when shipped.
- Always-on chat sidebar. "Ask Docker Dash anything" is the most-mocked AI pattern of 2025. Engineers want answers in context, not a chat that needs to re-learn their setup every time.
- Auto-remediation agent. "AI fixes restart-looping containers automatically." Replit-class risk. We stay read-only.
- AI-generated weekly summary emails. Padding nobody reads.
- NL → Compose generation in dashboard. Operators edit existing Compose; Docker Desktop's Gordon does generation for dev workflows.
- AI insights dashboard with predictive forecasting. Single-host data is too small for meaningful prediction; wrong forecasts erode trust in everything else.
If a future feature request feels like one of these, it'll get a polite no with the rationale on the issue.
Settings → AI → uncheck "Enable AI features" → Save. Done.
For complete teardown (e.g. you were testing and want to remove the API key from disk):
- Settings → AI → "Clear" the API key
- Save
The encrypted key is removed from ai_settings. No outbound calls possible until reconfigured.
For paranoid environments that want to prove AI is off:
SELECT * FROM ai_settings;
-- enabled = 0 + provider = NULL + api_key_encrypted = NULL → fully offOr in CI: DD_FORCE_AI_DISABLED=1 env var (planned for v8.1.0 if there's demand — file an issue if you need it now).
plans/deep-spec-ai-features.md— full architectural rationale (local artifact)plans/spikes-ai-features.md— pre-implementation validationSECURITY.md— encryption details for stored credentialsCHANGELOG.md— v8.0.0 release notes