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 byscripts/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:
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¶
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-trinoto 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.htmlto verify the file is not empty (0-byte.Files.Getissue). - OAuth2 redirect loop: The cockpit is protected by
oauth2-proxyvia Traefik forward-auth middleware. Ensure the Keycloak clientakko-oauth2-proxyhas the correct redirect URI (https://akko.local/oauth2/callback).