Files
mg4/k8s
nilsandClaude Opus 5.5 d711e0cfda App 2.12.0, server 2.5.0: enter settings on the phone
The ABRP credentials are long to type on the car. "Enter on phone"
(Live data tab, and Settings next to the charging price) shows a QR
code; it opens a form on the server where the phone sends the ABRP API
key and user token, charging price and usable capacity, confirmed with
the approval password. The car polls with its own token and collects
the values once, then saves them through the same checks as the fields
on screen.

Same device-flow shape as pairing. The server keeps the values in memory
only, at most ten minutes, hands them out once with no-store, and never
logs them or puts them back into the page; a paired token only reaches
its own installation's request. Pairing's QR dialog is now shared
(PhoneQrDialog), and the phone pages share one stylesheet.

The config file also takes charging_price and usable_kwh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 12:59:03 +02:00
..

Kubernetes manifests — car.k8s.stinnesbeck.com

Plain manifests for the car server, InfluxDB 2 and Grafana. They are only files: nothing here is applied automatically. Apply them yourself.

File What
namespace.yaml Namespace mg4
influxdb.yaml InfluxDB 2.7.12 StatefulSet (10Gi PVC, default storage class), cluster-internal Service, NetworkPolicy admitting only the server and Grafana
server.yaml Go server Deployment (1 replica, non-root, read-only root filesystem) and Service
grafana.yaml Grafana 13.2.3 Deployment (1Gi PVC), Service; datasource and dashboards provisioned
grafana/ The provisioned InfluxDB datasource and the MG4 dashboards (Live, Consumption, Charging)
ingress.yaml Traefik IngressRoutes for car.k8s.stinnesbeck.com and Grafana, TLS from Traefik's default certificate
secrets/secrets.example.yaml Template for the Secrets; placeholders only, not in kustomization.yaml
secrets/secrets.yaml Your filled-in copy — gitignored, never committed
kustomization.yaml Everything except the Secrets; generates the Grafana ConfigMaps

Before the first apply

  1. Check ingress.yaml: Grafana's host (placeholder car-grafana.k8s.stinnesbeck.com). Both routes use the traefik-internal class, and both hosts must be covered by Traefik's default certificate.
  2. Create the Secrets. cp k8s/secrets/secrets.example.yaml k8s/secrets/secrets.yaml (gitignored), replace every CHANGE-ME there (openssl rand -hex 32): influxdb-auth, mg4-server (ingest token, approval password for pairing), grafana-admin and grafana-influx (see below). Keep the template itself on placeholders only.
  3. Registry access. The mg4-server package on git.stinnesbeck.com is public, so no pull secret is needed. If you make it private, add an imagePullSecrets entry to server.yaml.

Apply

kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/secrets/secrets.yaml
kubectl apply -k k8s/

Use -k, not -f k8s/: plain -f applies the files without kustomize, so the Grafana ConfigMaps (datasource and dashboards) are never created and Grafana does not start.

Grafana's InfluxDB token

Grafana reads InfluxDB with a token that can only read the mg4 bucket, from the grafana-influx Secret. InfluxDB has to create that token, so it is a step of its own:

  1. With InfluxDB running, create the token. The influx CLI in the pod is already signed in as admin:

    kubectl -n mg4 exec influxdb-0 -- sh -c \
      'influx auth create --org mg4 --description grafana-read-only --json \
         --read-bucket "$(influx bucket find --name mg4 --hide-headers | cut -f1)"'
    
  2. Copy the "token" value from the output into grafana-influx → token in k8s/secrets/secrets.yaml, apply that file, and restart Grafana: kubectl -n mg4 rollout restart deployment/grafana.

Until the Secret exists, Grafana does not start (the container waits for the missing Secret). On a fresh install, apply everything once without Grafana working, create the token, then apply the Secret.

Notes

  • InfluxDB's setup mode runs only on an empty volume. Changing admin-token in the Secret later does not change the token inside InfluxDB.
  • The server uses the InfluxDB admin token; a token scoped to read/write on the mg4 bucket can replace it later. Grafana has its own read-only token (below).
  • The dashboards are read-only in Grafana's UI. Change the JSON in grafana/dashboards/; the ConfigMap name changes with its content, which rolls Grafana.
  • The server image is pinned by digest in server.yaml. To upgrade, push a new tag and put its digest there (skopeo inspect docker://git.stinnesbeck.com/nils/mg4-server:<tag>).