Beacon Relay Connectivity¶
The beacon relay is customer-deployed infrastructure. Its one job is to let your EU-hosted secret store and your US-cloud Kubernetes cluster establish an mTLS tunnel without either side exposing an inbound port. Both the port (next to your secret store) and the operator broker (in your cluster) connect outbound to a beacon process with operational state that you run; the beacon matches them cryptographically and forwards encrypted bytes between them. It relays inner mTLS ciphertext and sees connection metadata. Outer TLS and tenant authentication have separate relay-side keys and configuration.
Customers choose their relay explicitly. The customer path uses a relay under
customer control with verified TLS, tenant enrollment and restart custody.
beacon.cloudtaser.io is demo only; hosted customer and pilot enrollment
are unavailable. The shipped chart address defaults to beacon.cloudtaser.io:443,
with system-root TLS trust enabled; the CLI P2P relay address has the same default.
Leaving the address unset points at the demo relay, so set your own relay
address and verified TLS/tenant inputs explicitly.
When to use beacon relay¶
The chart enables the Port/beacon profile by default. This is separate from
the CLI command mode: target install --mode defaults to deploy (chart only),
not full P2P bootstrap. Use the relay pattern when:
- Your OpenBao and cluster have no direct network path
- Both sides are behind NAT or firewalls
- You only allow outbound TCP 443 traffic
- You want outbound-only connectivity after configuring your chosen relay and tenant
Use reverse-connect (--mode reverse) instead when:
- You have a direct network path and want lower latency
- You can expose a LoadBalancer or public endpoint on the cluster
Use direct (--mode direct) only for legacy setups where pods connect directly to OpenBao.
Default mode
target install --mode defaults to deploy (chart only). Full P2P bootstrap
requires explicit --mode p2p and its prerequisites. Neither command mode
replaces customer relay selection and enrollment; the shipped relay address
defaults to the demo fleet until you override it.
Architecture¶
EU Jurisdiction Beacon US Cloud Provider
┌──────────────────────────┐ ┌────────────────────┐ ┌──────────────────────────┐
│ │ │ │ │ │
│ OpenBao / Vault │ │ TCP relay │ │ Managed Kubernetes │
│ + Port │─────────>│ port 443 only │<──────│ + Operator (broker) │
│ │ outbound │ │ │ │
└──────────────────────────┘ │ Matches by │ │ ┌──────────────────┐ │
│ info_hash │ │ │ Protected pods │ │
│ │ │ │ → Broker → Beacon │ │
│ Relays encrypted │ │ │ → Port → Vault│ │
│ mTLS bytes │ │ └──────────────────┘ │
└────────────────────┘ └──────────────────────────┘
Data flow for secret delivery:
- The port runs alongside OpenBao and connects outbound to the beacon
- The operator (broker) connects outbound to the beacon from the K8s cluster
- The beacon matches them by their shared info hash (SHA-256 of the port CA certificate)
- After matching, the beacon relays bytes bidirectionally
- Through the relay, port and broker establish mTLS (end-to-end encrypted)
- The beacon never sees plaintext -- it only relays encrypted traffic
Security¶
mTLS end-to-end¶
Port and broker authenticate each other via certificates generated during the self-bootstrap protocol. The beacon relay is transparent -- it forwards bytes without inspecting or modifying them. Even if the beacon is compromised, the attacker cannot decrypt the traffic.
Info hash as capability¶
The info hash is the SHA-256 of the port CA certificate. Only parties that possess the same CA certificate compute the same hash. The beacon uses this hash to match port and broker connections. Without the correct info hash, a connection cannot be paired.
Beacon retains operational state¶
The relay does not persist application payloads or inner-tunnel keys. It does hold outer-TLS and tenant-authentication material and configuration. After restart, reconnection depends on those inputs remaining valid; qualify recovery on your chosen relay.
Zero trust¶
The security model does not trust the beacon. Even under full compromise of the beacon server, the attacker sees only TLS-encrypted bytes. Secrets remain protected by the mTLS tunnel between port and broker.
Connection hardening (May 2026)¶
The beacon applies TCP keepalive probes immediately after Accept, before the TLS handshake begins, preventing half-open connections from accumulating under adverse network conditions. The per-IP rate limiter aggregates IPv6 addresses to /64 prefixes (preventing rotation-based bypass) and caps the rate-limit map at 10,000 entries with oldest-entry eviction. The /admin/drain endpoint is served on a dedicated loopback-only listener when the health server binds to a non-loopback address, so access is enforced at the network layer rather than by inspecting RemoteAddr. See Upgrade Section E1 for operator-facing details.
Operator-visible limits¶
The beacon enforces three hard limits to protect against unauthenticated abuse. All are compile-time defaults with no runtime configuration knobs -- the values are chosen to be generous for legitimate traffic while capping the blast radius of sustained attacks.
| Limit | Default | Scope | Behaviour when exceeded |
|---|---|---|---|
| Forward rate limit | 100 connections/min | Per source IP (IPv6 bucketed by /64) | Connection closed with rateLimit error |
| Concurrency cap | 1,000 simultaneous forwarded connections | Global (per beacon process) | New connections block until a slot frees (backpressure, not rejection) |
| Gossip value size | 8,192 bytes | Per ACME gossip entry | Entry rejected with errGossipValueTooLarge |
Scanner-triggered log lines (TLS handshake failures, unexpected protocols, premature close) are logged at DEBUG, not WARN, to reduce noise in production log pipelines. See Upgrade Section G for the full changelog and operator-action guidance.
Security hardening (beacon v0.6.23+)¶
Secure key loading¶
Previous beacon versions accepted --auth-key and --gossip-key as inline flag values. These values leak to /proc/<pid>/environ and process listings visible to any process with sufficient privileges on the beacon host. Beacon v0.5.3+ introduces file-based alternatives as the recommended approach:
| Old (deprecated) | New (recommended) | Purpose |
|---|---|---|
--auth-key <value> |
--auth-key-file <path> |
HMAC registration auth key |
--gossip-key <value> or CLOUDTASER_BEACON_GOSSIP_KEY env |
--gossip-key-file <path> |
HA gossip encryption key |
When deploying via Helm, the chart mounts keys from Kubernetes Secrets into the beacon pod's filesystem automatically and references them via --auth-key-file and --gossip-key-file — no inline values appear in the pod spec or environment.
Metrics endpoint authentication¶
When --metrics-addr is bound to a non-loopback address (for example :9090), a bearer token is required:
The beacon exits with an error at startup if a non-loopback metrics address is configured without --metrics-token. For loopback-only metrics (127.0.0.1:9090), no token is required.
HMAC nonce and timestamp registration protocol¶
Beacon v0.5.3 tightens the HMAC computation used during port and broker registration. Registrations now include a nonce and RFC3339 timestamp alongside the auth key in the HMAC input. This prevents indefinite replay attacks — a captured registration message cannot be replayed after the timestamp window closes.
A migration flag supports rolling upgrades:
While the compatibility deadline has not passed, the beacon accepts both old-format (no nonce) and new-format registrations, logging a warning for old-format ones. After the deadline, only new-format registrations are accepted.
This is a protocol change. Operator and port clients must be updated to produce the new format before or alongside the beacon upgrade. See Upgrade Section J for the full migration procedure.
Behavioral hardening¶
Four security improvements ship without configuration changes:
- Gossip holder validation — only the registered holder may update gossip state for a connection, preventing holder spoofing attacks in HA beacon clusters
- PendingRegistry caps — the pending connection registry is bounded to the beacon's configured capacity, preventing unbounded pre-registration that could exhaust memory before connections are forwarded
- Forwarder-identity rate limiting — forwarded connections are rate-limited by the forwarding beacon's identity rather than the client IP, preventing identity laundering where an attacker routes through a beacon to bypass per-IP limits
- HMAC re-verification on forwarded connections — the target beacon re-verifies HMAC on registrations received from a forwarding beacon, closing an auth bypass that existed in HA topologies
In-memory certificates¶
All mTLS certificates for the port-to-broker connection are stored in OpenBao and loaded into operator process memory at runtime. No certificates are stored in Kubernetes Secrets. See Zero Kubernetes Secrets Architecture for details.
For how per-pod child vault tokens are minted on top of this tunnel and delivered into wrapper memory via the HKDF-v2 unseal envelope, see Trust Chain & Per-Pod Isolation.
Setup¶
Use the host-Port installation procedure for Linux host Port + customer relay + US cluster + EU store. It specifies the matched CLI v0.19.176, chart 1.0.359, Port v0.4.133 and beacon v0.6.23, including signature verification, relay trust, source authority, private introduction and application-level checks. Its dated observations and release limits define the measured scope.
Linux host Port¶
Select the host installer explicitly:
Review the signed-binary installer and run it on the EU host as described in the
procedure. Installing the binary does not authorize or start a managed Port
session. Complete source authority prepare, the approved source host-launch
lifecycle and the operator introduction in the procedure. The relay registration
token alone does not replace source authority or the Port/broker mTLS identity.
Kubernetes Port (planned)¶
The published CLI defaults source install port to Kubernetes. That deployment
is not qualified for this customer path. Use --type=linux for the host procedure;
do not substitute Kubernetes Port flags or legacy chart coordinates. See
Secret Store & Port Installation
and the published command reference.
Direct secret-store deployments¶
The direct Helm installation requires a store reachable from the cluster and has its own qualification limits. It does not use the host Port or relay topology and does not establish an outbound-only connection to the EU store.
Beacon deployment¶
The beacon is a Go binary deployed under the relay operator's control. Use the matched release and the host-Port procedure linked above.
The relay holds tenant registration keys, nonce replay caches, rate-limit and pairing/registry state, plus its outer TLS and gossip material. Optional ACME storage persists to the configured cache directory; without that directory ACME state is in memory. These are separate from endpoint mTLS private keys and application plaintext, which the relay does not receive. Memory state is scoped to process lifetime and configured expiry; disk retention and backups belong to the relay operator.
Published server and limiter state fields (inferred): acmeCacheProbe, activation, activeConns, activeRelays, addr, allowedSNISet, audit, authKeyMu, beforeParkCommit, certCache, certFile, certSwapper, cfg, closePublicListener, counters, expectedMembers, forwardClient, forwardServer, haAttachMu, handshakeSem, infoHashLimiter, keepaliveApplier, keyFile, lastMatchAt, lastRelayDurationNanos, lifecycleMu, limit, listenerFactory, logger, lru, maxEntries, membership, metrics, mu, nearMiss, noTenantNonceCaches, noTenantNonceEntries, nonceCache, nonceExpirations, nonceLimits, nonceMu, now, nowFunc, parkedConnsBySource, pendingConns, pendingConnsBySource, pendingRegistry, pendingSourceMu, preListenHook, preQuorum, rateLimiter, readyzFailing, relayAdmissionMu, relayWg, resumptionGrace, ring, sealed, serveCtx, serving, stopCleanup, stopCleanupOnce, tenantKeyCache, tenantNonceCaches, tlsConfigOverride, tlsHandshakeTimeout, totalBytesRelayed, totalConnRejected, totalConnRejectedPerSource, totalConnected, totalErrors, totalForwardAttempts, totalForwardDialFailed, totalForwardHeaderFail, totalForwardLoops, totalForwardMTLSFailed, totalForwardOversized, totalForwardSuccess, totalHMACCompatAccepts, totalHandshakeTimeouts, totalMatches, totalNonceCacheCapHits, totalPanicsRecovered, totalPreviousAuthKeyAccepts, totalRateLimited, totalRateLimitedInfoHash, totalRelayCompletions, totalRelayDurationNanos, totalSNIRejected, totalTimeouts, unsealCallback, version, waiting, window.
Customer-deployed (production)¶
The customer pattern is a relay under your control, reachable on TCP 443 from both Port and the cluster. It must not need secret-store administrator access for application traffic. Outer TLS and tenant authentication require relay-side key material; the inner Port/broker mTLS tunnel protects application payloads. See the trust model for connection metadata exposure.
Helm chart:
helm install cloudtaser-beacon cloudtaser/cloudtaser-beacon \
--namespace cloudtaser-beacon \
--create-namespace \
--set service.type=LoadBalancer \
--set tls.existingSecret=beacon-tls
Standalone binary (systemd, bare metal, or a small VM):
curl -sfL https://codeberg.org/cloudtaser/cloudtaser-beacon/releases/latest/download/cloudtaser-beacon-linux-amd64 \
-o /usr/local/bin/cloudtaser-beacon
chmod +x /usr/local/bin/cloudtaser-beacon
cloudtaser-beacon \
--addr :443 \
--tls-cert /etc/cloudtaser/beacon/cert.pem \
--tls-key /etc/cloudtaser/beacon/key.pem
For high availability, run multiple beacon instances behind a load balancer or configure clients with comma-separated addresses:
Public demo beacon (demo only)¶
beacon.cloudtaser.io:443 serves the hosted demo only.
Hosted customer and pilot enrollment are unavailable; do not reuse its demo
identity/key or configure customer workloads against it. The demo relay is not
a customer installation service, a production default or an SLA-backed service.
It can expose connection metadata to its operator and can be unavailable during
maintenance. Customer pilots also need their own explicitly chosen relay.
Network requirements¶
| Side | Direction | Destination | Port | Protocol |
|---|---|---|---|---|
| OpenBao (port) | Outbound | Beacon server | 443 | TCP/TLS |
| Cluster (broker) | Outbound | Beacon server | 443 | TCP/TLS |
| Beacon server | Inbound | From port and broker | 443 | TCP/TLS |
No inbound ports are required on either OpenBao or the cluster. Both sides initiate outbound connections only.
Comparison of connectivity modes¶
| Feature | Direct | Reverse-Connect | Beacon Relay |
|---|---|---|---|
| Network requirement | OpenBao reachable from pods | Broker reachable from OpenBao | Outbound TCP 443 only |
| Configuration | OpenBao address per pod | Port endpoint | Customer-chosen relay, verified TLS and tenant enrollment |
| NAT traversal | No | Partial | Full |
| Default mode | No | No | Yes |
| Latency | Lowest | Low | Low (+1 hop) |
| OpenBao inbound ports | Required | None | None |
| Cluster inbound ports | None | Required (LoadBalancer) | None |
| Third-party dependency | None | None | None (beacon is customer-deployed) |
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
| Broker cannot connect to beacon | Egress firewall blocking TCP 443 to beacon address | Allow outbound TCP 443 to your beacon's public DNS name or IP |
| Port cannot connect to beacon | Secret-store-side egress restricted | Allow outbound TCP 443 to your beacon's public DNS name or IP |
| Port and broker connected but mTLS fails | Mismatched info hash or certificates | Check the matched release set and Port/broker identity using the host-Port procedure. Operator memory loss requires a fresh private introduction; a shared relay token alone does not establish mTLS trust |
| Secrets not fetching after relay established | OpenBao Kubernetes auth not configured | Verify with cloudtaser-cli target validate |
| High latency on secret fetch | Beacon server geographically distant | Self-host a beacon closer to both sides, or use reverse-connect mode |
cloudtaser-cli target debug shows relay errors |
Beacon connection dropping | Check network stability; create a DebugReport CR for diagnostics |
Related¶
- Self-Bootstrap Protocol -- cluster onboarding after explicit relay and tenant enrollment
- Reverse-Connect Architecture -- alternative mode when you can expose a LoadBalancer
- Enterprise Deployment Architecture -- CLI-as-orchestrator and air-gap workflows
- GKE Deployment Guide -- step-by-step GKE setup
- Security Model -- trust boundaries and threat model
- Upgrade Guide: HMAC Protocol Migration -- rolling upgrade procedure for the nonce/timestamp registration change