Skip to main content
← Back

wasmCloud 2.10: Same-host routing, outbound identity, and OpenTelemetry that follows the spec

Eric Gregory
Senior Technical Writer at Cosmonic
· 10 min read

wasmCloud 2.10 release banner

wasmCloud 2.10.0 is now available! This release centers on connecting workloads and securing the connections:

  • Same-host local routing: An opt-in fast path serves a workload's outgoing HTTP in process when the destination is a co-located workload, skipping the network entirely
  • Outbound client identity: The host can present an mTLS client certificate on components' outbound HTTPS, with rotation that never needs a restart
  • Spec-conformant OpenTelemetry: The host's telemetry export now follows the OpenTelemetry environment spec, with per-signal control, TLS and mTLS to collectors, and misconfiguration that warns instead of aborting

2.10 also enforces egress policy for host plugins, routes implements labels between components in a workload, fixes messaging admission so replicas share one gate, publishes an all-features host image, and upgrades to Wasmtime 48.

At a glance

Area2.9.02.10.0
HTTP between co-located workloadsover the networkopt-in in-process local routing
Outbound HTTPS identitynone (server verification only)mTLS client certificate, rotating
Host telemetryany OTEL_* var activated everythingendpoint-keyed, per-signal, spec-conformant
Plugin egressHTTP and DNS gated for component plugins onlyraw sockets and native plugins gated too
implements labelsroute to host backendsroute to host backends or sibling components
max_in_flight on Kubernetesone gate per replicaone gate per deployment
Host component pluginscustom build requiredpublished -all-features image
EngineWasmtime 47Wasmtime 48

Same-host local routing

When two workloads are scheduled on the same host, an HTTP call between them previously took the full network path: kube-proxy, cluster DNS, and everything between. With 2.10.0's opt-in local routing, the call never leaves the process.

It is a two-key grant, like host loopback. The target workload declares the hostnames it serves in its wasi:http entry (localRoute: 'svc.internal, api.internal/orders', with segment-boundary path prefixes), and the operator enables --http-local-routing on the host (chart value runtime.hostGroups[].http.localBypassRouting). Callers change nothing, and their allowedHosts policy is checked before the short-circuit, so local routing never widens egress. Names declared in localRoute are never reachable from the network; a forged Host header from outside gets a 404.

It's important to emphasize that a localRoute claim is not proof of ownership. Any workload on an enabled host can claim any hostname, including one a neighbor calls over HTTPS, and receive that traffic in plaintext. Locally routed calls also bypass ingress auth, rate limits, mesh mTLS, and NetworkPolicy. Enable it on host groups whose workloads trust each other, never on shared multi-tenant groups. See Same-host local routing and the local-ingress example.

Outbound client identity

Workloads calling services that require mutual TLS previously had no way to present a client certificate. In 2.10.0 the host carries one for them:

  • --http-client-cert-path / --http-client-key-path (PEM) present a client certificate on outbound HTTPS whenever a peer requests one. On Kubernetes, runtime.clientIdentity points at a kubernetes.io/tls Secret, cert-manager-shaped by default.
  • --http-client-identity-refresh re-reads the pair on an interval (the chart sets 30s; the flag itself reads once when unset), built for Kubernetes Secret rotation: new connections pick up the new credential, established connections keep what they negotiated, and a failed re-read keeps the current credential.
  • Expiry is fail-closed under refresh: with the refresh interval set, a host refuses to start with an already-expired identity, and a credential that expires while resident stops being presented rather than being offered stale.

The identity is host-group-wide and destination-wide: every workload authenticates as it, to any peer that asks. Pair it with narrow allowedHosts, and keep untrusted workloads on a host group without one. Details in Workload security.

Spec-conformant OpenTelemetry

The host's own telemetry export was rebuilt around the OpenTelemetry environment spec:

  • Export activates on an endpoint. A signal exports only when OTEL_EXPORTER_OTLP_ENDPOINT (or its per-signal form) is set. Setting OTEL_SERVICE_NAME alone no longer spins up three exporters aimed at localhost.
  • Per-signal control: OTEL_METRICS_EXPORTER=none turns one signal off; per-signal endpoints, protocols, and timeouts are honored; grpc and http/protobuf both work, including to https:// collectors, with OTEL_EXPORTER_OTLP_CERTIFICATE for private CAs and client certificate variables for mTLS.
  • Misconfiguration warns instead of killing the process, OTEL_SERVICE_NAME now sets service.name (the host previously forced wash-runtime), and each enabled signal logs one startup line saying where it exports.

The new Host telemetry page documents the full variable surface.

Plugins: enforced egress and an all-features image

Host plugin egress grants are now enforced on every path. The allowedHosts and allowedIpNameLookups lists on a plugin declaration previously gated component plugins' HTTP and DNS only:

  • The lists now apply to native and component plugins alike, and cover raw sockets.
  • A native plugin that cannot enforce a declared ceiling fails host startup instead of ignoring it.
  • The built-in wasmcloud:nats plugin enforces its ceiling at startup and at bind, and stops following cluster-advertised peers under one, so list every failover member.
  • Plugins can declare allowedHostLoopbackPorts and bind operator-declared ports, reserved in the host's port table.

And running host component plugins no longer requires a custom build: each release now publishes an all-features image, the release tag plus an -all-features suffix (ghcr.io/wasmcloud/wash:2.10.0-all-features), multi-arch and retagged from the exact digest that passed release testing. Point one host group's image.tag at it to run component plugins on stock artifacts.

implements labels route between components

Multi-backend binding's (implements ..) labels gain a second target: a label can now name a sibling component in the same workload, linking the import in process to that component's export, for any interface. Two components exporting the same interface no longer conflict; an importer names its provider, and an unlabeled import of a multi-exported interface is refused with guidance naming the fix. An operator-declared hostInterfaces entry name takes precedence over a same-named component, so the manifest's explicit routing always wins. See Host Interfaces.

Messaging admission shares the gate

2.8's max_in_flight limit was documented as counted across a component's replicas on a host, but on Kubernetes each replica's Workload resource carried a unique name, so each replica opened its own gate at the full ceiling. In 2.10.0 the operator stamps replicas with stable identity annotations and the host keys admission gates on them, so replicas of one deployment genuinely share a single gate. A new admission_group config key overrides the name the gate is keyed under, so same-named components in different deployments can share a gate deliberately. See Messaging admission control.

Wasmtime 48

The engine moves to Wasmtime 48, bringing several behavior improvements along with the upgrade:

  • A denied outbound request no longer traps WASI 0.2 guests: allowedHosts denials surface as a handleable http-request-denied error, matching 0.3 semantics.
  • Socket policy now screens inbound traffic (listens, accepts, received datagrams), and accepted connections count against the inbound quota.
  • Ingress normalizes scheme and authority: guests behind a TLS listener see https, and an invalid Host header is a 400.
  • Hop-by-hop headers are withheld from 0.3 guests as they already were from 0.2.

Other notable changes

What to check before you upgrade

  • Set your OTel endpoint explicitly: hosts that exported to the SDK's localhost default without an endpoint variable stop exporting. Set OTEL_EXPORTER_OTLP_ENDPOINT, and note service.name now honors OTEL_SERVICE_NAME.
  • Messaging replicas share their admission gate: a deployment whose replicas each consumed a full max_in_flight allowance now shares one gate. If throughput drops, raise max_in_flight (and the host ceiling if needed) to the intended aggregate.
  • Plugin egress lists are enforced: lists that previously bound nothing on a native plugin, and left a component plugin's raw sockets ungated, now apply, with allowedHosts and range refusals following the host's socketEgress mode; a native plugin that cannot enforce a declared ceiling fails host startup.
  • WASI 0.2 components see denials as errors: code that relied on trapping when allowedHosts blocked a request now receives an error value to handle.
  • Embedders: Wasmtime 48 unifies the outgoing HTTP surfaces and removes the P3-specific types; MSRV is 1.95. See Building custom hosts.

Everything else is backward compatible: local routing, client identity, and the plugin ports surface are all opt-in, and existing manifests and chart values run unchanged.

What's coming

Host component plugins stay opt-in behind a Cargo feature; the all-features image makes them reachable on stock artifacts while the binding surface settles. wasmcloud:nats is at 0.1.2 with stream and consumer administration still deliberately out of scope, and local routing's per-workload trust model is the open question for a future release. As always, the roadmap has what's in progress, and wasmCloud Wednesday is the place to weigh in.

Get started with wasmCloud 2.10

Install or upgrade wash.

On macOS or Linux via install script:

bash
curl -fsSL https://wasmcloud.com/sh | bash

With Homebrew:

bash
brew install wasmcloud/wasmcloud/wash

On Windows with winget:

shell
winget install wasmCloud.wash

For new users, the quickstart gets you from installation to a running component on Kubernetes in a few minutes.

Full changelog: v2.9.0...v2.10.0

Join the community

About the author

Eric Gregory
Senior Technical Writer at Cosmonic
View profile of Eric Gregory