In my first two posts in this series, I made the case for why the IoT industry needs to embrace the architectural principles that OSGi pioneered 25 years ago, and why edge AI model lifecycle management is the hardest problem nobody's solving well yet. The feedback was clear: "Show us how. With real technology. For a real use case."

So let's do exactly that.

In this post, I'm going to walk through a concrete architecture for a connected EV charging network with 10,000+ stations — built entirely on open-source components, designed from the ground up to comply with the EU Cyber Resilience Act (CRA), and ready to scale. The two cornerstones: Eclipse Kanto as the modular edge software stack running on every charging station, and Eclipse hawkBit as the backend for managing software updates across the entire fleet.

EV charging is the perfect proving ground for everything I've been advocating. It combines every hard IoT problem simultaneously: safety-critical power delivery, payment processing with PCI DSS requirements, real-time grid interaction, geographically distributed fleets in public spaces, regulatory pressure from the CRA and NIS2, and a product lifetime of 10-15 years during which the software must evolve continuously. If your architecture works here, it works anywhere.

The scenario: 10,000 charging stations across Europe

Let's define the scenario concretely. A Charge Point Operator (CPO) deploys and manages a network of 10,000+ AC and DC charging stations across multiple European countries. The fleet is heterogeneous:

Hardware diversity. The fleet includes AC wall boxes (11-22 kW) at apartment complexes and workplaces, AC/DC fast chargers (50-150 kW) at retail locations, and DC high-power chargers (150-350 kW) at highway corridors. Each hardware variant runs a different compute module — from ARM Cortex-A based controllers on the simpler wall boxes to x86-based industrial PCs on the high-power stations. Some stations have been deployed for five years and run older firmware; new stations ship with the latest software.

Protocol landscape. Stations communicate with the backend via OCPP (Open Charge Point Protocol) — but the fleet spans OCPP 1.6-J on legacy stations, OCPP 2.0.1 on mid-generation hardware, and OCPP 2.1 on the newest deployments. Vehicle-to-charger communication uses ISO 15118 for Plug & Charge functionality. Payment is handled via contactless terminals or app-based flows. Energy management integrates with local grid operators via OpenADR or proprietary APIs.

Operational reality. Stations are deployed in public and semi-public locations across multiple countries, each with different grid codes, energy regulations, and local requirements. They must achieve 97%+ uptime (as mandated by the U.S. NEVI program and emerging European standards). They handle sensitive data — payment credentials, personal identifiers, vehicle contract certificates. And they are physically accessible to the public, making them targets for both cyber and physical tampering.

This is a scenario where getting the architecture wrong doesn't just cause inconvenience — it causes safety incidents, financial fraud, grid instability, and regulatory penalties.

Why the CRA changes everything for EV charging

EV charging stations are textbook examples of "products with digital elements" under the EU Cyber Resilience Act. They contain software, they connect to networks, they process data, and they interact with critical infrastructure (the power grid). The CRA imposes obligations that fundamentally reshape how CPOs and charger manufacturers must think about their software architecture.

Security-by-design, not security-as-afterthought. The CRA mandates that products be designed and developed with appropriate cybersecurity measures from the outset. For a charging station, this means every software component — from the OCPP stack to the payment module to the energy management logic — must be hardened by design, not patched after deployment.

Vulnerability handling for the entire product lifetime. Manufacturers must identify and document vulnerabilities, provide security updates without delay, and maintain these capabilities for a minimum of five years (or the expected product lifetime, whichever is longer). For a charging station with a 10-15 year operational life, this is a decade-plus commitment to continuous software maintenance.

Software Bill of Materials (SBOM). The CRA requires documentation of all software components, including open-source dependencies. You must know — and be able to demonstrate to regulators — exactly what software is running on every device in your fleet, at any point in time.

Secure update mechanisms. Updates must be delivered securely, with cryptographic verification, and without exposing the device to new vulnerabilities during the update process. For a geographically distributed fleet where physical access is expensive and stations must maintain availability, this means robust, reliable OTA (over-the-air) update infrastructure.

Incident reporting. Actively exploited vulnerabilities must be reported to ENISA within 24 hours. This requires continuous monitoring and the ability to rapidly assess which devices in your fleet are affected by a newly discovered vulnerability — which in turn requires knowing exactly what software each device is running.

The CRA's penalties — up to €15 million or 2.5% of global revenue — make non-compliance an existential business risk. But more importantly, the CRA's requirements are simply good engineering practice for any fleet of critical connected devices. The regulation is catching up to what we should have been doing all along.

Eclipse Kanto: the modular edge stack on every station

Eclipse Kanto is a modular IoT edge software stack, contributed initially by Bosch and developed in Go, that runs on edge devices and provides all the essential IoT capabilities: cloud connectivity, digital twins, local messaging, container management, and software updates. It's specifically optimized for devices with limited hardware resources and real-time requirements — exactly the profile of an EV charging controller.

Here's why Kanto is architecturally right for this scenario:

Container-based modularity. Every functional capability on the charging station runs as a separate OCI-compliant container: the OCPP communication stack, the ISO 15118 Plug & Charge handler, the payment terminal integration, the energy management module, the local load balancing logic, the monitoring and telemetry agent. Each container is independently deployable, updatable, and removable — the dynamic modularity principle I've been advocating.

This is the key architectural decision. When a critical vulnerability is discovered in the OCPP library, you update the OCPP container alone — without touching the payment module, the energy manager, or any other component. The station continues charging vehicles during the update. No downtime, no full-firmware reflash, no risk of bricking a €50,000 high-power charger in a highway corridor 200 kilometers from the nearest technician.

Pluggable container runtime. Kanto abstracts the container runtime behind a unified API. The default is containerd, but it supports podman, LXC, and other OCI-compliant runtimes. For resource-constrained wall boxes, a lighter runtime can be used. For high-power stations with more capable compute modules, the full containerd stack with advanced isolation features is available. Same architecture, different runtime — the reusability principle at the infrastructure level.

Local MQTT messaging via Eclipse Mosquitto. Components on the station communicate through a local MQTT broker, not through direct API calls. The OCPP stack publishes charging session events. The energy manager subscribes to power delivery data. The telemetry agent subscribes to health metrics from all components. This is the service-oriented, loosely coupled architecture that enables components from different vendors to coexist on the same device — the interoperability principle in action.

Digital twin integration via Eclipse Ditto protocol. Every charging station is represented as a digital twin in the cloud, with its current state — active sessions, power delivery, error conditions, installed software versions — synchronized in near-real-time. The twin serves as the single source of truth for fleet monitoring, configuration management, and compliance reporting.

Built-in software update agent. Kanto's update manager integrates natively with Eclipse hawkBit (and other backends) via the "Desired State" concept. The backend defines the desired software state for a device (which containers at which versions with which configurations), and Kanto's update manager reconciles the device's actual state with the desired state. This declarative approach is fundamentally more robust than imperative "install this file" commands — if the update fails midway, the device knows what state it should be in and can retry or roll back.

Container image verification. Kanto supports Notation-based container image signature verification. Every container image deployed to a charging station is cryptographically signed at build time and verified before execution. This prevents tampering with update artifacts in transit and ensures that only authorized, unmodified software runs on production devices — a direct CRA requirement.

Eclipse hawkBit: fleet-wide update orchestration

Eclipse hawkBit is the backend counterpart — a domain-independent software update server that manages the rollout of updates to large fleets of edge devices. For our 10,000-station charging network, hawkBit provides the command-and-control plane for all software lifecycle management.

Device and software repository. hawkBit maintains a registry of every device in the fleet, its hardware type, its current software state, and its update history. This is the compliance backbone: at any point, an operator can query exactly which software version — down to the individual container — is running on station #7,842 in a parking garage in Lyon. For CRA audit purposes, this history is immutable and timestamped.

Distribution sets and software modules. hawkBit's meta-model allows packaging updates as modular distribution sets. A single rollout can contain an OCPP container update, a new payment module version, and an updated monitoring agent — each as a separate software module within the distribution set. Target devices receive only the modules relevant to their hardware profile and current state. The wall box gets the lightweight OCPP update; the high-power station gets the same OCPP update plus a DC-specific power management module. This is fleet-aware variant management — the dependency management principle applied at scale.

Target types and compatibility management. hawkBit supports defining target types with compatibility constraints: which distribution set types can be deployed to which device types. A distribution set built for x86 hardware cannot accidentally be deployed to an ARM-based wall box. A container requiring 2GB RAM cannot be pushed to a device with only 512MB. Incompatible deployments are rejected by the system, not discovered by a bricked device in the field.

Staged rollouts with error thresholds. hawkBit's rollout engine deploys updates to devices in configurable groups, with cascading execution controlled by trigger thresholds and error limits. A typical rollout for our charging network might look like this: Group 1 (canary): 50 stations across diverse locations and hardware types. Group 2: 500 stations. Group 3: 2,000 stations. Group 4: remaining fleet. Each group only begins after the previous group exceeds the trigger threshold (e.g., 80% successful installations). If any group exceeds the error threshold (e.g., 10% failures), the entire rollout is automatically halted. Emergency shutdown allows stopping a rollout in progress if a critical issue is discovered after deployment has begun — preventing the problem from propagating to the full fleet.

Multiple integration channels. hawkBit exposes a Direct Device Integration (DDI) API for devices that connect directly, and a Device Management Federation (DMF) API via AMQP for integration with intermediary device management platforms. Devices poll the DDI API at configurable intervals, checking for available updates. This pull-based model is deliberate: it means the device initiates the connection, reducing the attack surface compared to a push-based model where the server must be able to reach every device. The polling interval can be adapted per device — highway chargers that need rapid security patches poll more frequently; stable workplace wall boxes can poll less often.

The architecture: putting it all together

Here's how the complete system architecture maps out, from device to cloud:

Edge Layer (on every charging station)

The charging station's compute module runs Linux with Eclipse Kanto as the orchestration layer. The containerized application landscape consists of:

OCPP Gateway Container. Handles all communication with the Charging Station Management System (CSMS) backend. Implements the appropriate OCPP version for this station's generation. Translates between OCPP messages and internal MQTT events. This is the most security-critical container — OCPP has known vulnerabilities around session handling and authentication, especially in legacy 1.6 implementations. Isolating it in its own container with restricted network access limits the blast radius if it's compromised.

ISO 15118 / Plug & Charge Container. Manages the vehicle-to-charger authentication and authorization via the ISO 15118 PKI. Handles TLS certificate management, contract certificate installation, and the complex Plug & Charge handshake. This container requires access to a hardware security module (HSM) or trusted platform module (TPM) for key storage — Kanto's container configuration supports device passthrough for hardware access.

Payment Processing Container. Integrates with contactless payment terminals (NFC readers) and processes payment authorization. Must comply with PCI DSS requirements. By running in an isolated container with no access to the OCPP stack, the energy management logic, or the station's power control interfaces, the payment module's attack surface is minimized and its PCI compliance scope is contained.

Energy Management Container. Implements local smart charging logic: load balancing across multiple connectors, integration with building energy management systems, dynamic power adjustment based on grid signals (OpenADR), and preparation for vehicle-to-grid (V2G) services. This module's configuration is site-specific — a highway station has different power constraints than a workplace installation — but the container image is identical across the fleet. Site-specific parameters are managed as configuration, separate from code.

Monitoring & Telemetry Container. Collects health metrics from all other containers and the underlying hardware: CPU temperature, power supply voltage, connectivity status, charging session statistics, error rates. Publishes aggregated telemetry to the cloud via MQTT. Implements anomaly detection for early warning of hardware failures or security incidents. This is the observability backbone that enables both operational monitoring and CRA-mandated incident detection.

Kanto Update Manager. The system component (not a regular container) that communicates with Eclipse hawkBit, receives desired state specifications, orchestrates container updates, and reports deployment status. Handles rollback if an update fails health checks after installation.

Communication Layer

Station to Cloud: MQTT over TLS. All device-to-cloud communication flows through encrypted MQTT connections. The cloud-side MQTT endpoint handles device authentication (via X.509 certificates provisioned during manufacturing) and message routing to the appropriate backend services. MQTT is bandwidth-efficient — critical for stations on cellular connections — and supports the bidirectional communication needed for both telemetry upload and command delivery. Kanto's built-in cloud connector manages the connection lifecycle, including reconnection handling and message buffering during network outages.

Station to CSMS: OCPP over WebSocket/TLS. The OCPP communication channel to the Charging Station Management System uses encrypted WebSocket connections. OCPP 2.0.1 and 2.1 mandate TLS with mutual authentication via client certificates, providing strong protection against man-in-the-middle attacks.

Inter-container on station: Local MQTT. Components on the station communicate via the local Mosquitto broker, with topic-based access control ensuring that the payment container cannot subscribe to energy management topics and vice versa. This implements the security isolation principle at the application layer — even if one container is compromised, it cannot access data flows it's not authorized to see.

Cloud / Backend Layer

Eclipse hawkBit. Software update orchestration and fleet management, as described above. Maintains the device registry, software repository, and rollout engine.

Eclipse Ditto. Digital twin platform that maintains a virtual representation of every charging station. Operators query Ditto to see the real-time state of any station. Ditto also serves as the integration point for third-party systems — grid operators, roaming partners, fleet management tools — through its HTTP and WebSocket APIs. Ditto's MQTT integration receives telemetry directly from the stations' cloud connectors, authenticates device identity, and routes messages to the appropriate backend services — effectively serving as both the device connectivity layer and the digital twin in a single, streamlined component.

SBOM Management & Vulnerability Tracking. A dedicated service (built on tools like CycloneDX, Dependency-Track, or similar) that ingests the Software Bill of Materials for every container image in the repository. When a new CVE is published, this service cross-references it against the SBOM of every deployed container, identifies which stations are affected, and can trigger an automated rollout of patched containers via hawkBit. This is the CRA's vulnerability handling requirement, operationalized.

Audit Log & Compliance Reporting. An immutable log of every software deployment, configuration change, rollback, and security event across the fleet. Timestamped, cryptographically sealed, and queryable. For CRA compliance, this log must be able to answer the question: "What software was running on station X at time Y, and why was it changed to version Z at time W?" — for any station, at any time, going back years.

Mapping the architecture to CRA requirements

Let me be explicit about how each CRA requirement maps to architectural components:

CRA RequirementArchitectural ComponentSecurity-by-designContainer isolation (Kanto), MQTT access control, TLS everywhere, HSM for key storageVulnerability handlingSBOM tracking, CVE cross-referencing, automated patch rollouts via hawkBitSecure updateshawkBit OTA with staged rollouts, Notation-based image signing in Kanto, pull-based update modelSoftware Bill of MaterialsContainer image SBOM generation at build time, centralized SBOM registry per deployed versionIncident reportingMonitoring container with anomaly detection, Ditto digital twin for real-time fleet visibility, audit logProduct lifetime supportModular container architecture enabling component-level updates for 10-15 years without full reflashMinimize attack surfacePer-container network policies, restricted hardware access, MQTT topic ACLs, no unnecessary servicesData protectionIsolated payment container (PCI scope containment), TLS for all data in transit, local processing where possibleDefault security settingsKanto default configuration with TLS enabled, containers with minimal privileges, no default passwords

Why open source is the right choice for CRA compliance

There's an irony in the CRA that many in the industry haven't fully grasped yet: open-source software is structurally better suited to CRA compliance than proprietary alternatives — despite the initial perception that it might be harder to secure.

Transparency. The CRA demands that manufacturers understand the security properties of every component in their product. With proprietary vendor stacks, you're trusting a black box. With Eclipse Kanto, hawkBit, Ditto, and Mosquitto, you can audit every line of code, assess every dependency, and verify every security claim yourself. The code is the documentation.

Community-driven vulnerability discovery. Open-source projects benefit from broad scrutiny. The Eclipse Foundation's development process, with its mandatory IP reviews and contribution guidelines, provides a governance framework that supports the CRA's supply chain security requirements. Vulnerabilities are discovered and patched by a global community, not by a single vendor's security team.

Vendor independence for long-term maintenance. The CRA requires security updates for the product's lifetime — potentially 10-15 years. Betting on a single proprietary vendor's continued existence, continued support for your hardware platform, and continued willingness to provide patches for a product they consider legacy is a strategic risk. Open-source projects under Eclipse Foundation governance are designed to outlast any single contributor. If Bosch reduces its investment, other community members can — and do — continue development. The code cannot be taken away.

SBOM generation is native. Open-source build pipelines can generate SBOMs automatically from dependency manifests. Every container image built from open-source components has a traceable, machine-readable bill of materials. Proprietary components require the vendor to provide this information — and many cannot or will not.

The Eclipse Foundation recognized this opportunity early. Their Open Regulatory Compliance Working Group, with over 20 open-source foundations participating, is actively developing tooling and processes specifically to help open-source projects meet CRA requirements. By building on Eclipse IoT projects, CPOs aren't just getting technology — they're getting a governance and compliance ecosystem.

Open source means production-ready — not just prototype-ready

There's a persistent misconception I still encounter in boardrooms and procurement meetings: that open source is fine for prototyping and evaluation, but that "real" production deployments require proprietary, commercially licensed software. This was arguably true fifteen years ago. It is demonstrably false today.

The path from evaluation to production-grade deployment with the stack described in this article is measured in weeks, not years. You can have a hawkBit instance running in Docker within minutes, connect real devices via the DDI API within days, and be managing staged fleet rollouts within weeks. The APIs are stable, the documentation is comprehensive, and the integration points are well-defined. This isn't proof-of-concept software — it's software that has been hardened by years of production use across industries.

Let me be concrete about the production credentials of the hawkBit ecosystem:

Bosch IoT Rollouts is a fully managed SaaS service, hosted on AWS, that is 100% API-compatible with Eclipse hawkBit. Bosch — the company that initially contributed hawkBit to the Eclipse Foundation — operates this as a commercial service for enterprise IoT customers worldwide. The fact that Bosch itself bets its commercial reputation on hawkBit's production maturity is perhaps the strongest endorsement possible. The same codebase, the same APIs, the same rollout engine described in this architecture runs in a commercially supported, SLA-backed cloud service today.

SWUpdate, the most widely adopted OTA update agent for embedded Linux, has native hawkBit integration for fleet management. SWUpdate handles the on-device mechanics — A/B partition switching, atomic updates, cryptographic signature verification, rollback on failure — while hawkBit orchestrates the fleet-level rollout. This combination is deployed on countless production devices globally. SWUpdate was chosen by the Civil Infrastructure Platform (CIP), a Linux Foundation project focused on establishing an open-source base layer for industrial-grade civil infrastructure — a strong signal of the toolchain's reliability for long-lived, critical deployments. SWUpdate integrates seamlessly into Yocto and Buildroot build systems, which means the entire path from board support package to OTA-capable production device is well-trodden.

RAUC, another robust embedded update framework, provides a dedicated hawkBit client daemon (rauc-hawkbit-updater) written in C/glib. RAUC handles complex partition layouts, cryptographic verification, and slot-based A/B switching in production environments. For CPOs using custom Linux distributions on their charging controllers, the RAUC-hawkBit combination provides a proven, lightweight update path.

Eclipse Hara, the reference hawkBit client library written in Kotlin, has reached version 2.x and has been — in the project's own words — "successfully used in production for years." The broader ecosystem includes hawkBit clients in Rust (hawkbit-rs), C/glib, and Python, plus integration with Zephyr RTOS for resource-constrained microcontrollers and ChirpStack for LoRaWAN gateway management. The same hawkBit backend can manage updates across this entire device spectrum — from a Zephyr-based sensor node with 256 KB of flash to a Linux-based high-power charging station with 4 GB of RAM.

What does this mean concretely for a CPO building the architecture described in this post? The timeline from "we're evaluating this" to "we're rolling out to our first 500 stations" is roughly:

Day 1: Docker-based hawkBit evaluation — running a complete update server locally, simulating devices, testing the management UI and APIs.
Weeks 1-2: Integrating the DDI API with your device software, connecting SWUpdate or RAUC on your charging controller to the hawkBit server, performing first real OTA updates on lab devices.
Weeks 3-4: Setting up fleet segmentation — target types for different hardware variants, distribution sets for different station types, target filters for geographic or temporal grouping.
Month 2: First canary rollouts to a small group of field-deployed stations, validating the staged rollout engine, error thresholds, and abort mechanisms under real-world conditions.
Month 3: Production fleet management — 10,000+ stations under active software lifecycle management.

This timeline would have been unthinkable with a build-from-scratch approach or even with most proprietary alternatives. The reason it's possible is that every component in this stack has been battle-tested in production by multiple organizations across multiple industries. You're not the first to put this into production — you're joining an ecosystem that already runs at scale.

The open-source model hasn't just caught up with proprietary alternatives for production IoT. In many ways, it has surpassed them — because the collective investment of the community produces software that no single vendor could build and maintain alone, and because the transparency of the codebase provides the auditability that regulations like the CRA now demand.

Designing for the next 15 years

Everything I've described here maps back to the principles I laid out in my first post: dynamic modularity (containerized components with independent lifecycles), service orientation (MQTT-based loose coupling), security isolation (per-container boundaries and access control), configuration management (site-specific parameters decoupled from code), dependency management (hawkBit's target types and compatibility constraints), interoperability (OCPP, ISO 15118, MQTT — all open standards), and reusability (the same container images across hardware variants).

But the most important principle is designing for longevity. A charging station installed today will still be operating in 2040. The OCPP version will have evolved — perhaps to 3.0 or beyond. New grid integration protocols will have emerged. AI-based energy optimization will become standard. V2G will move from pilot to production. New cybersecurity threats that we can't imagine today will have materialized.

The modular, container-based architecture ensures that any individual component can be replaced — the OCPP stack, the energy manager, the payment module — without redesigning the system. The open-source foundation ensures that the technology isn't held hostage by any single vendor's roadmap. The CRA-compliant update infrastructure ensures that security patches can reach every device in the fleet, reliably and verifiably, for as long as the stations are in service.

That's what future-proof by design looks like in practice. Not as a slide in a conference presentation, but as a running system managing 10,000 charging stations that drivers depend on every day.