log-guardian/project-docs/design/phase-1-plan.md
WayfinderAK 6f7549d439
All checks were successful
build-image / docker (push) Successful in 53s
Implement phase 1 foundations
2026-07-03 20:14:06 -08:00

9.8 KiB

Phase 1 Plan

Goal: make log monitoring useful in production without enabling dangerous automation.

Phase 1 targets a production Portainer deployment of Log Guardian. Loki will likely run on a separate server and use an object-storage backend, probably MinIO backed by NAS storage. Log Guardian must remain safe-by-default: authenticated UI, real alert delivery, incident cooldowns, Loki validation tooling, dry-run remediation evidence, and local-only AI analysis.

Decisions made

  • Deployment target: production Portainer.
  • Loki location: separate server from Log Guardian.
  • Loki storage direction: object storage via MinIO, with MinIO data on NAS-backed storage.
  • UI auth: single admin user using basic auth.
  • Health endpoint: /healthz remains unauthenticated.
  • First alert channel: self-hosted ntfy.
  • Additional alert channel types should be supported/configurable from UI, not ntfy-only.
  • Incident cooldown: per rule, default 1h.
  • AI: local-only Ollama is approved; no external/cloud AI providers.
  • Remediation: Phase 1 should implement permission modeling and dry-run evidence, not dangerous automatic actions.
  • Phase 1 completion requires Docker build and real alert delivery validation.

1. Production deployment architecture

Log Guardian

Run Log Guardian as a Portainer-managed service/container.

Required mounts/config:

  • Persistent local config/data file mount for LOG_GUARDIAN_DATA_PATH.
  • Environment configuration for Loki endpoint, auth, alert defaults, and optional Ollama endpoint.
  • Network path to the remote Loki server.
  • Optional network path to self-hosted ntfy, Gotify, SMTP relay, webhook targets, and Ollama.

Loki

Loki will run on a different server. Recommended production direction:

  • Loki single-binary or simple scalable deployment depending on expected volume.
  • Object storage backend: S3-compatible MinIO.
  • MinIO data stored on NAS-backed storage.
  • Retention configured explicitly.
  • Promtail or Grafana Alloy deployed on every Docker/Portainer host that needs logs collected.

Recommended initial storage sizing:

  • Start with 50 GB usable object storage for modest private infrastructure.
  • Use 14-day retention initially.
  • Monitor ingestion and object growth for 7 days before increasing retention.
  • Increase to 100-250 GB+ if services are noisy or retention must be longer.

Planning assumptions to validate:

  • NAS latency is acceptable for MinIO/Loki workload.
  • MinIO has backups/snapshots appropriate for desired retention.
  • Loki retention deletes old chunks/index data correctly.
  • Log Guardian can reach Loki over a private network/VPN only.

2. Loki ingestion, label discovery, and validation

Because actual labels are not known yet, Phase 1 must include label discovery and query testing.

Collection strategy

Use Promtail or Grafana Alloy on Docker/Portainer hosts. Target labels should include stable, low-cardinality dimensions such as:

  • host
  • container
  • service
  • stack
  • stream
  • compose_project or equivalent
  • compose_service or equivalent

Avoid high-cardinality labels, including request IDs, user IDs, IP addresses, paths, error messages, or raw log content.

Log Guardian Loki diagnostics

Add authenticated UI/API support for:

  • Loki readiness/status check.
  • List labels from /loki/api/v1/labels.
  • List values for a selected label from /loki/api/v1/label/{name}/values.
  • Test a LogQL query before saving a rule.
  • Show count and sanitized sample lines for a test query.

Implementation notes:

  • Limit query time range and result count.
  • Do not log raw sample payloads by default.
  • Redact obvious secrets from displayed query samples where practical.
  • Handle Loki tenant ID and basic auth from existing Loki config.

3. UI authentication

Add single-admin basic auth.

Configuration:

  • LOG_GUARDIAN_AUTH_USERNAME
  • LOG_GUARDIAN_AUTH_PASSWORD

Rules:

  • /healthz is unauthenticated.
  • All other UI/API routes require auth.
  • Use constant-time comparison for credentials.
  • Do not log usernames/passwords or auth headers.
  • If credentials are unset, fail closed in production or clearly mark auth as disabled only for local development. Prefer fail closed for Portainer deployment.

4. Alert channels

Alert channels must be configurable from the UI and stored in local configuration. Secrets need careful handling.

Required first channel: self-hosted ntfy

Support fields:

  • Name
  • Enabled
  • Server URL
  • Topic
  • Optional bearer token or token file reference
  • Priority
  • Tags

Validation:

  • Send a test notification from the UI.
  • Record delivery result without logging token values.

Additional Phase 1 channel types

Implement the data model and UI so multiple channel types are possible. Preferred Phase 1 support order:

  1. ntfy - implement real delivery first.
  2. gotify - real delivery if time allows; token-based API is straightforward.
  3. generic_webhook - useful but must avoid leaking secrets; support explicit headers carefully.
  4. smtp - useful, but can be deferred if it complicates TLS/auth validation.

Minimum acceptable Phase 1 scope:

  • UI can create/edit/delete alert channels.
  • UI can attach channels to rules.
  • ntfy real delivery works.
  • Other channel types may be present as disabled/scaffolded if not implemented, but the UI should clearly show unsupported status.

Secret handling:

  • Do not print secrets in logs.
  • Do not render stored secret values back into forms; show only configured/not configured.
  • Prefer environment variable or mounted file references for sensitive channel tokens when possible.
  • If secrets are stored in local JSON, the file must be written with 0600 permissions and documented as sensitive.

5. Rule evaluation and incident cooldown

Add per-rule cooldown.

Rule field:

"cooldown": "1h"

Default behavior:

  • If unset, cooldown is 1h.
  • If a rule fires outside cooldown:
    • create incident;
    • send configured alert channels;
    • record dry-run remediation evidence if actions are configured.
  • If a rule fires during cooldown:
    • update rule last checked/matched/count fields;
    • do not create a duplicate incident;
    • do not send another alert;
    • increment or record suppressed count if implemented.

6. Remediation/action model

Phase 1 should not execute destructive remediation. Implement guardrails and dry-run evidence.

Recommended Phase 1 action types:

  • generic_webhook: dry-run by default; real execution can be deferred or restricted.
  • portainer_restart: dry-run only in Phase 1.
  • allowlisted_command: dry-run only in Phase 1; command IDs only, never arbitrary shell from UI/AI.
  • record_recommendation: safe action that stores an advisory recommendation on the incident.

Guardrails:

  • Global dry-run defaults true.
  • Per-rule action must be enabled.
  • Per-action dry-run should be explicit or inherited from global dry-run.
  • AI may recommend actions but cannot execute them.
  • No arbitrary command execution.
  • No Portainer write API calls in Phase 1 unless separately approved.

Validation evidence:

  • At least one rule with a configured dry-run action.
  • Incident shows what would have happened.
  • Logs do not expose secrets or raw full log payloads.

7. Local-only AI analysis

Local-only Ollama is approved for Phase 1. External/cloud AI providers are not approved.

Configuration:

  • LOG_GUARDIAN_ANALYSIS_PROVIDER=none|ollama
  • LOG_GUARDIAN_OLLAMA_URL=http://ollama:11434
  • LOG_GUARDIAN_OLLAMA_MODEL=<model>

Default:

  • LOG_GUARDIAN_ANALYSIS_PROVIDER=none

Rules:

  • AI analysis remains opt-in per rule.
  • AI findings are advisory only.
  • Limit number of log lines sent to Ollama.
  • Redact obvious secrets before prompt construction.
  • Do not log prompts or raw log payloads by default.
  • Store only concise summaries/recommendations in incidents.

Prompt/redaction design must be documented before enabling Ollama in production.

8. UI scope

Add UI support for:

  • Login-protected dashboard.
  • Rule create/edit with cooldown and alert channel selection.
  • Alert channel create/edit/test.
  • Loki status/label discovery/query test.
  • Incident list showing alert delivery state and remediation dry-run evidence where available.

Keep the UI served by Go. Do not add a server-side JavaScript runtime.

9. Tests and validation

Required implementation tests:

  • Auth middleware unit tests.
  • Store tests for alert channels, cooldown fields, and secret-preserving updates.
  • Loki client tests using httptest fixtures for labels, label values, and query range.
  • Alert dispatcher tests for ntfy using httptest.
  • Rule engine tests for cooldown suppression.
  • Remediation dry-run tests.
  • Optional Ollama provider tests using httptest only; no live AI dependency in unit tests.

Required validation before Phase 1 completion:

gofmt -w cmd internal
go test ./...
make validate-structure
make docker-build

Additional required evidence:

  • Loki connectivity/query validation against the remote Loki server.
  • Label discovery output documented without secrets.
  • Self-hosted ntfy test alert received.
  • A rule-generated ntfy alert received.
  • Remediation dry-run evidence captured.
  • Security/privacy review covering logs, prompts, secrets, alert tokens, and action permissions.

10. Required Phase 1 artifacts

Create/update these before declaring Phase 1 complete:

  • project-docs/status/phase-1-summary.md
  • project-docs/status/phase-1-test-results.md
  • project-docs/status/phase-1-open-issues.md

11. Open planning items

  • Final Loki topology: single-binary vs simple scalable.
  • Final MinIO/NAS capacity and retention target after observing ingestion.
  • Whether Gotify, generic webhook, or SMTP are implemented fully in Phase 1 or scaffolded after ntfy.
  • Whether alert channel secrets are stored directly in local JSON or referenced via env/file paths.
  • Exact Ollama model to use once Ollama is stable.
  • Whether Log Guardian reaches Loki/ntfy/Ollama over LAN, VPN, or Docker overlay network.