Skip to content

Security & encryption

LinkMesh’s security model is small enough to hold in your head: all control-plane traffic rides one TLS front door, every edge component authenticates with a Bearer credential it presents on an outbound connection, and the secrets the server keeps are encrypted or hashed at rest. There is no inbound port on any collector or agent, and your telemetry never passes through the control plane.

Encryption in transit

The server binds a single port for everything: the web UI, the REST API, the agent control channel, OpAMP, Alloy remote-config, and the collector own-metrics push all share it. External TLS is terminated at the ingress in front of the server (Let’s Encrypt certificate for app.linkmesh.io), so every one of these connections reaches the server as HTTPS:

TrafficPathProtocol
Web UI + REST API/…HTTPS
OpAMP collectors/v1/opampWebSocket over TLS
Alloy remote-config/collector.v1.CollectorServiceConnect-RPC over TLS
Collector own-metricsPOST /v1/metricsOTLP/HTTP over TLS
Onboarding agent/v1/agentWebSocket over TLS

Behind the ingress the server’s listener is cluster-internal only — nothing dials it from outside except through the TLS front door.

Every edge component (collector, supervisor, agent) opens its connection outbound to the server. None of them expose an inbound port for LinkMesh, so a managed host needs no open listening ports and no inbound firewall rule. For the full port-and-direction breakdown, see Firewall & connectivity.

Encryption at rest

The server keeps three kinds of secret, each protected differently.

  • API tokens and per-collector tokens are stored as one-way hashes (SHA-256). The raw value of a service-account token (lmsat_…) or a per-collector OTLP token is shown once, at creation, and never persisted. When a caller presents a token, the server re-hashes the presented value and compares — it never needs the original back.
  • User passwords are stored with bcrypt. Web-UI sessions are issued as JWTs after a successful password login.
  • Destination credentials are encrypted (AES-256-GCM) in the secrets vault, and referenced from config by name — ${secret:name} — so the committed config, history, and API reads hold only the reference. The real value is substituted only when config is delivered to a collector. See Destination secrets.

Enrollment and control-channel authentication is Bearer-over-TLS throughout — there are no client certificates, and the server holds no private certificate authority to protect.

What the server can and can’t see

The control plane carries configuration and status — not your telemetry.

  • The edge is outbound-only. Collectors and agents dial the server; the server never dials them. There is no inbound port to a collector or agent, so the server cannot reach into a managed host.
  • Telemetry never transits LinkMesh. Your logs, metrics, and traces flow collector → destination (Grafana Cloud, Loki, Mimir, your own backends), outbound from your network on each backend’s own port. LinkMesh is not in that path and never sees the payloads.
  • What the server does see is the config it generated for each collector, the collector’s own internal metrics (self-telemetry), and the health and status each edge component reports. That’s the whole surface — see Self-telemetry for exactly what the own-metrics push contains and what it deliberately leaves out.

See also