Ops-dashboard/README.md
Scrum4Me Agent 92d450609c feat(auth): shared-secret auth web-app → ops-agent
- ops-agent/src/auth.ts: constant-time compare via timingSafeEqual to prevent timing attacks; store secret as Buffer
- ops-agent/src/index.ts + ops-agent.service: bind on 127.0.0.1:3099 (was 4242, per plan)
- app/api/agent/[...path]/route.ts: Next.js proxy route that verifies ops_session cookie then forwards requests to agent with Authorization: Bearer <secret>
- .env.example + deploy/ops-dashboard.env.example: add OPS_AGENT_SECRET and OPS_AGENT_URL
- README.md: rotation procedure for the shared secret

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 17:22:37 +02:00

1.2 KiB

Ops Dashboard

Single-user ops dashboard voor jp-visser.nl.

See docs/runbooks/ for setup, deployment, and operational procedures.

Ops-agent auth

The web-app communicates with the ops-agent via a shared secret stored in /etc/ops-agent/secret (mode 0640, owner root:ops-agent).

  • The ops-agent reads the secret at startup via OPS_AGENT_SECRET_PATH.
  • Every request from the web-app carries Authorization: Bearer <secret>.
  • The agent validates using a constant-time comparison to prevent timing attacks.
  • The web-app reads the secret value from the OPS_AGENT_SECRET environment variable.

Secret rotation procedure

  1. Generate a new secret on the server:
    openssl rand -hex 32 | sudo tee /etc/ops-agent/secret
    sudo chown root:ops-agent /etc/ops-agent/secret
    sudo chmod 0640 /etc/ops-agent/secret
    
  2. Update OPS_AGENT_SECRET in the web-app's environment file (/srv/ops/ops-dashboard.env) with the new value.
  3. Restart both services:
    sudo systemctl restart ops-agent
    sudo docker compose -f /srv/ops/docker-compose.ops-dashboard.yml restart ops-dashboard
    
  4. Verify the dashboard is operational and that systemctl status ops-agent shows the service running without errors.