Skip to content

AKKO Cockpit

Overview

The AKKO Cockpit is the service discovery portal and operational dashboard for the platform. Built with nginx, HTML, and vanilla JavaScript, it provides a single-pane-of-glass view of all platform services with real-time health checks, quick-access links, and key performance indicators.

Architecture

  Browser ──→ Traefik (:443)
          Cockpit (nginx :80)
           ├── index.html      (service cards, DevHub)
           ├── app.js          (health polling, dynamic URLs)
           ├── style.css       (AKKO dark theme)
           └── nginx.conf      (health proxy routes)
                  ▼  /health/* reverse proxy
          ┌───────┼───────┐
          ▼       ▼       ▼
       Trino   Airflow  Polaris  ... (all services)

The cockpit nginx server acts as a health-check proxy, forwarding /health/<service> requests to each service's internal health endpoint. This avoids CORS issues and keeps health URLs consistent for the frontend.

Ports

Port Purpose Exposed
80 HTTP — serves the portal UI and proxies health checks Yes (via Traefik ingress)

Access the cockpit at https://akko.local (k3d) or the configured ingress hostname.

Key Features

  • Service cards — each platform service has a card with name, version, health status indicator (green/red), and direct link
  • Health proxy — nginx location /health/* blocks proxy to each service's native health endpoint, normalizing responses for the frontend
  • Dark theme — follows the AKKO Design System (--bg-primary: #0a0a14, --accent: #6c63ff, font: Inter)
  • DevHub section — quick links to JupyterHub, Superset, Airflow, MLflow, Dashboards, and documentation
  • Version display — reads versions.json (generated by scripts/generate-versions.sh) to show pinned versions for every service

8-Page Portal (Sprint 14)

The cockpit is structured into eight dedicated pages:

Page Purpose Source
Home Service cards with health checks and quick links /
DevHub Developer shortcuts (JupyterHub, Airflow, Superset, MLflow, dbt docs) /devhub/
AI AI SQL UDF playground, LiteLLM gateway info, Ollama/vLLM status /ai/
Governance OpenMetadata catalog, OPA policies, RBAC dashboard /governance/
Architecture Interactive architecture diagram (Mermaid) /architecture/
Logs logs layer log viewer (LogQL, live tail, filtering by pod/namespace) /logs/
Monitoring Prometheus metrics (CPU, memory, request rates, HPA) /monitoring/
Alerts AlertManager active/silenced alerts with severity, receiver, and annotations /alerts/

Logs, Monitoring, and Alerts reverse-proxy through the cockpit nginx to logs layer, Prometheus, and AlertManager internal services — no external DNS/TLS required.

Configuration

nginx.conf

The cockpit's nginx configuration defines health proxy routes for each service:

branding/cockpit/nginx.conf
location /health/trino {
    proxy_pass http://akko-trino:8080/v1/info/state;
}

location /health/airflow {
    proxy_pass http://akko-airflow-webserver:8080/health;
}

location /health/polaris {
    proxy_pass http://akko-polaris:8182/q/health;
}

Kubernetes ConfigMap

In Helm deployments, the nginx config is mounted via a ConfigMap from the akko-cockpit sub-chart. The Docker-era branding/cockpit/nginx.conf serves as the source of truth and is copied into helm/akko/charts/akko-cockpit/files/.

app.js

The JavaScript frontend polls /health/* endpoints every 30 seconds and updates the status indicator on each service card. Service URLs are dynamically built based on the current hostname pattern (uses *.akko.local domains, configurable via global.domain in Helm values).

Helm Chart

The cockpit is deployed via the akko-cockpit custom sub-chart:

helm/akko/charts/akko-cockpit/
├── Chart.yaml
├── values.yaml
├── files/
│   ├── index.html
│   ├── app.js
│   ├── style.css
│   └── nginx.conf
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    ├── configmap.yaml      # mounts files/ via .Files.Get
    └── ingress.yaml

Key Values

values.yaml
akko-cockpit:
  image:
    repository: akko-cockpit
    tag: "2026.03"
  ingress:
    enabled: true
    host: "akko.local"

Static files via .Files.Get

All HTML, CSS, JS, and nginx config files must be read via .Files.Get from the files/ directory. Never pass static content through .Values — it results in 0-byte files.

Troubleshooting

Common Issues

  • Health checks all red: Verify that service DNS names resolve from inside the cockpit pod. Run kubectl exec deploy/akko-cockpit -- nslookup akko-trino to check. A common cause is deploying the cockpit before other services are ready.
  • Blank page / no cards: Check that the ConfigMap is correctly mounted. Run kubectl exec deploy/akko-cockpit -- cat /usr/share/nginx/html/index.html to verify the file is not empty (0-byte .Files.Get issue).
  • OAuth2 redirect loop: The cockpit is protected by oauth2-proxy via Traefik forward-auth middleware. Ensure the Keycloak client akko-oauth2-proxy has the correct redirect URI (https://akko.local/oauth2/callback).