Infrastructure Directory & Disaster Recovery Runbook
High-availability, dual-homed redundancy specification for the frame-embedded E-Bike GPS Tracker & Smart Alarm. Features sub-second automatic MQTT failover, idempotent telemetry deduplication across distributed Postgres instances, remote Grafana Cloud log shipping, and automated keepalive jobs.
π 01. Service Directory & Access Hub
24/7 Always Free e2-micro VM in Iowa (us-central1-a) running Docker Compose with Node.js Aedes/Express and local Postgres.
34.134.11.1811883 (TCP)3000 (HTTP)antigravity@34.134.11.181Serverless MQTT broker in Frankfurt (eu-central-1) providing TLS 1.3 edge connectivity and REST downlink dispatch.
ne9190a6...emqxsl.com8883 (MQTTS)8443 (/api/v5)trackeradminCloud Postgres in Ireland (eu-west-1) with PostgREST API and sequence deduplication (uq_bike_seq) + keepalive cron.
zseccsirfivtsehriixmuq_bike_seq0 0 */3 * * (Actions)Centralized telemetry ingestion via Prometheus Remote Write and Loki Log Ingestion with live public health dashboards.
calmlattice2831.grafana.net35555301773440Source control, PlatformIO firmware compilation, Docker build workflows, and automated database ping jobs.
Kimishiba/eBike-GPS-TrackerKimishiba/eBike-GPS-Tracker-Serversupabase-keepalive.ymlπΊοΈ 02. Architecture & Data Flow Topology
graph TD
subgraph EDGE["π² IoT Edge Layer (ESP32-WROOM-32E)"]
ESP["ESP32 Cellular Tracker
Monotonic 64-bit Sequence Counter
RTC + NVS Watermark"]
end
subgraph ROUTE_A["π’ Route A: Primary Compute (Always Free $0/mo)"]
GCP["GCP e2-micro VM (34.134.11.181)
Docker Compose Stack (Iowa)"]
APP["ebike-tracker (Node 22)
Aedes Broker (:1883) + Express (:3000)"]
LOCAL_DB["ebike-db (postgres:16-alpine)
Credentials & Command Queue"]
GCP --> APP
APP --> LOCAL_DB
end
subgraph ROUTE_B["π‘ Route B: Secondary Cloud Failover ($0/mo)"]
EMQX["EMQX Cloud Serverless
ne9190a6.ala.eu-central-1.emqxsl.com:8883 (TLS 1.3)
REST Downlink Dispatcher (:8443)"]
SUPA["Supabase PostgreSQL
Project: zseccsirfivtsehriixm (Ireland)
Idempotent Deduplication (UNIQUE seq_num)"]
CRON["GitHub Actions Keep-Alive Cron
Runs every 3 days (0 0 */3 * *)"]
EMQX --> SUPA
CRON --> SUPA
end
subgraph OBS["π Centralized Observability ($0/mo)"]
GRAFANA["Grafana Cloud (calmlattice2831)
Prometheus Remote Write + Loki Log Ingestion"]
end
ESP -->|Default Primary Route: TCP 1883| GCP
ESP -.->|Failover on Drop: TLS 8883| EMQX
APP -->|Dual Downlink Dispatch| EMQX
APP -->|Push Metrics & Logs| GRAFANA
classDef primary fill:#ffffff,stroke:#1e1e1e,stroke-width:3px,color:#1e1e1e;
classDef secondary fill:#ffffff,stroke:#1e1e1e,stroke-width:3px,color:#1e1e1e;
classDef obs fill:#ffffff,stroke:#1e1e1e,stroke-width:3px,color:#1e1e1e;
classDef edge fill:#ffffff,stroke:#1e1e1e,stroke-width:3px,color:#1e1e1e;
class GCP,APP,LOCAL_DB primary;
class EMQX,SUPA,CRON secondary;
class GRAFANA obs;
class ESP edge;
πΉοΈ 03. Interactive Failover & Downlink Simulator
π¨ 04. Incident Response & Disaster Recovery Runbooks
The ESP32 firmware detects 3 dropped TCP ACK packets and automatically fails over to EMQX Cloud Serverless (TLS 8883) in ~334ms. Telemetry flows to Supabase without data loss.
Open Google Cloud Console and click "Start / Resume" if instance is stopped.
ssh antigravity@34.134.11.181 "cd ~/ebike-server && sudo docker compose restart"
Open Supabase Dashboard and click "Restore Project" (~60 seconds).
Run supabase-keepalive.yml to verify HTTP 200 response.
π 05. Automated Alerting Rules (Grafana Cloud)
Triggers when GCP Node.js HTTP traffic drops to zero AND no MQTT clients are connected for > 3 minutes.
sum(rate(http_request_duration_seconds_count[5m])) == 0 and sum(mqtt_connected_clients) == 0
Triggers immediately when the ADXL345 accelerometer detects unauthorized movement while armed.
increase(system_errors_total{type="alarm"}[1m]) > 0