Move the server to car.k8s.stinnesbeck.com

The server's host is car.k8s.stinnesbeck.com, not car.stinnesbeck.com:
IngressRoute, PUBLIC_URL (so the pairing QR code points there), the
app's pre-filled server URL and hint, and the docs. Grafana's
placeholder host follows to car-grafana.k8s.stinnesbeck.com, so one
*.k8s.stinnesbeck.com default certificate covers both. App 2.4.1 for the
new default; the server image is unchanged (its URL comes from the
manifest).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
2026-10-17 18:08:35 +02:00
co-authored by Claude Opus 5.5
parent 59ee2cae3b
commit 315586f94c
10 changed files with 19 additions and 19 deletions
+4 -4
View File
@@ -7,17 +7,17 @@ what has been changed, and what is still to do.
- Upstream: https://github.com/fatihdonmezdev/FatihsMG4 (itself a fork of malys / EVABRPUploader
and Leon Kernan / ABRP_Uploader). Credited in the app's About dialog.
## Architecture: car server at car.stinnesbeck.com
## Architecture: car server at car.k8s.stinnesbeck.com
The car sends everything to our own server. The server stores it in InfluxDB 2 and forwards live
telemetry to ABRP, so the ABRP token lives only on the server, never in the APK. Grafana reads
InfluxDB directly for the dashboards.
```
car ──live telemetry───▶ car.stinnesbeck.com (Go) ──▶ ABRP api.iternio.com/1/tlm/send
car ──live telemetry───▶ car.k8s.stinnesbeck.com (Go) ──▶ ABRP api.iternio.com/1/tlm/send
──daily chunks─────▶ │
──charging sessions▶ ▼
InfluxDB 2 ◀── Grafana (car-grafana.stinnesbeck.com)
InfluxDB 2 ◀── Grafana (car-grafana.k8s.stinnesbeck.com)
```
- **Server:** `server/`, Go 1.26, API only — see `server/README.md` for endpoints, configuration
@@ -42,7 +42,7 @@ car ──live telemetry───▶ car.stinnesbeck.com (Go) ──▶ ABRP ap
- [x] Image `mg4-server:2.1.0` (with pairing) pushed to git.stinnesbeck.com (public; pinned by
digest `sha256:e5f6e2d2…` in `k8s/kustomization.yaml`).
- [ ] Check in `k8s/ingress.yaml`: the Traefik ingress class (placeholder `traefik-external`) and
Grafana's host (placeholder `car-grafana.stinnesbeck.com`).
Grafana's host (placeholder `car-grafana.k8s.stinnesbeck.com`).
- [ ] First pairing and drive with 2.4.0: telemetry arrives in InfluxDB, Grafana and ABRP.
## To do
+2 -2
View File
@@ -34,8 +34,8 @@ android {
applicationId "com.stinnesbeck.nilsmg4"
minSdk 27
targetSdk 36
versionCode 58
versionName "2.4.0"
versionCode 59
versionName "2.4.1"
// Nothing about the server ships in the APK: its URL and ingest token are entered in
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
@@ -7,7 +7,7 @@ package com.evsuite.abrp;
*
* <pre>
* # Nils' MG4 config
* server_url = https://car.stinnesbeck.com
* server_url = https://car.k8s.stinnesbeck.com
* token = 0123abcd... (the server's INGEST_TOKEN)
* installation_id = 6f1a2b3c-4d5e-4f60-8a9b-0c1d2e3f4a5b
* interval_sec = 60
@@ -28,7 +28,7 @@ final class ServerConfig {
Pattern.CASE_INSENSITIVE);
/** Pre-filled so pairing needs no typing in the car; can still be changed. */
static final String DEFAULT_URL = "https://car.stinnesbeck.com";
static final String DEFAULT_URL = "https://car.k8s.stinnesbeck.com";
/** The server refuses shorter ingest tokens outright. */
static final int MIN_TOKEN_LENGTH = 24;
+1 -1
View File
@@ -49,7 +49,7 @@
<!-- Server page -->
<string name="server_card_title">Car server</string>
<string name="hint_server_url">Server URL</string>
<string name="helper_server_url">For example https://car.stinnesbeck.com</string>
<string name="helper_server_url">For example https://car.k8s.stinnesbeck.com</string>
<string name="hint_server_token">Ingest token</string>
<string name="helper_server_token">The server\'s INGEST_TOKEN, at least 24 characters</string>
<string name="hint_installation_id">Installation ID</string>
+3 -3
View File
@@ -1,4 +1,4 @@
# Kubernetes manifests — car.stinnesbeck.com
# 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.
@@ -10,7 +10,7 @@ is applied automatically. Apply them yourself.
| `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 `IngressRoute`s for car.stinnesbeck.com and Grafana, TLS from Traefik's default certificate |
| `ingress.yaml` | Traefik `IngressRoute`s for car.k8s.stinnesbeck.com and Grafana, TLS from Traefik's default certificate |
| `secrets.example.yaml` | **Template** for the Secrets; placeholders only, not in `kustomization.yaml` |
| `secrets.yaml` | Your filled-in copy — **gitignored**, never committed |
| `kustomization.yaml` | Everything except the Secrets; pins the server image, generates the Grafana ConfigMaps |
@@ -18,7 +18,7 @@ is applied automatically. Apply them yourself.
## Before the first apply
1. **Check `ingress.yaml`:** the ingress class (placeholder `traefik-external` for the public
Traefik) and Grafana's host (placeholder `car-grafana.stinnesbeck.com`). Both hosts must be
Traefik) and Grafana's host (placeholder `car-grafana.k8s.stinnesbeck.com`). Both hosts must be
covered by Traefik's default certificate.
2. **Create the Secrets.** `cp k8s/secrets.example.yaml k8s/secrets.yaml` (gitignored), replace
every `CHANGE-ME` there (`openssl rand -hex 32`): `influxdb-auth`, `mg4-server` (ingest token,
+1 -1
View File
@@ -52,7 +52,7 @@ spec:
containerPort: 3000
env:
- name: GF_SERVER_ROOT_URL
value: https://car-grafana.stinnesbeck.com
value: https://car-grafana.k8s.stinnesbeck.com
- name: GF_SECURITY_ADMIN_USER
value: admin
- name: GF_SECURITY_ADMIN_PASSWORD
+2 -2
View File
@@ -14,7 +14,7 @@ spec:
- websecure
routes:
- kind: Rule
match: Host(`car.stinnesbeck.com`)
match: Host(`car.k8s.stinnesbeck.com`)
services:
- kind: Service
name: mg4-server
@@ -35,7 +35,7 @@ spec:
routes:
- kind: Rule
# CHECK: placeholder host. It must be covered by Traefik's default certificate.
match: Host(`car-grafana.stinnesbeck.com`)
match: Host(`car-grafana.k8s.stinnesbeck.com`)
services:
- kind: Service
name: grafana
+1 -1
View File
@@ -42,7 +42,7 @@ spec:
value: mg4
# Where a phone reaches the server; the pairing QR code points here.
- name: PUBLIC_URL
value: https://car.stinnesbeck.com
value: https://car.k8s.stinnesbeck.com
- name: INFLUX_TOKEN
valueFrom:
secretKeyRef:
+3 -3
View File
@@ -1,6 +1,6 @@
# Nils' MG4 — car server
A small Go service at car.stinnesbeck.com: the API the car writes to, and the ABRP
A small Go service at car.k8s.stinnesbeck.com: the API the car writes to, and the ABRP
forwarder. Data lives in InfluxDB 2; Grafana reads it from there for the dashboards
(`../k8s/grafana/`).
@@ -61,8 +61,8 @@ the same bucket), and the device is persisted before the car can collect the tok
restart never loses a paired car. Manage cars with the approval password:
```sh
curl -H "Authorization: Bearer $APPROVAL_PASSWORD" https://car.stinnesbeck.com/v1/devices
curl -X POST -H "Authorization: Bearer $APPROVAL_PASSWORD" https://car.stinnesbeck.com/v1/devices/<id>/revoke
curl -H "Authorization: Bearer $APPROVAL_PASSWORD" https://car.k8s.stinnesbeck.com/v1/devices
curl -X POST -H "Authorization: Bearer $APPROVAL_PASSWORD" https://car.k8s.stinnesbeck.com/v1/devices/<id>/revoke
```
## Storage