Reverse-Connect Architecture¶
Beacon relay is now the default
As of the latest release, Beacon Relay is the default and recommended connectivity mode. Beacon relay requires only outbound TCP 443 from both sides and needs no LoadBalancer or public endpoint on the cluster. Use reverse-connect when you have a direct network path to the cluster and want to avoid the extra hop through the beacon relay.
The reverse-connect model eliminates inbound network access to OpenBao. The OpenBao server initiates an outbound connection to the cluster, not the other way around. Nothing is publicly exposed except the cluster's broker endpoint.
The Problem with Direct Connect¶
In the direct-connect model, the wrapper inside each pod connects directly to the OpenBao endpoint:
┌─────────────────────┐ ┌──────────────────────┐
│ Kubernetes Cluster │ │ EU Vault Server │
│ │ │ (Hetzner / OVH) │
│ ┌────────────────┐ │ HTTPS │ │
│ │ wrapper (pod) │──────────>│ :8200 (public) │
│ └────────────────┘ │ │ │
│ │ └──────────────────────┘
└─────────────────────┘
This requires OpenBao to accept inbound connections. Even with mTLS and IP allowlists, OpenBao has a public attack surface: port 8200 is reachable from the internet. For enterprises running vaults on EU-sovereign infrastructure (Hetzner, OVH, Scaleway), exposing any port to inbound traffic from cloud provider networks is a security and compliance concern.
Direct connect is appropriate when:
- OpenBao and cluster are in the same VPC or private network
- Private peering or VPN connects OpenBao network to the cluster network
- The OpenBao endpoint is not exposed to the public internet
Reverse-Connect Model¶
In the reverse-connect model, the connection direction is inverted. The OpenBao server runs a bridge component that connects outbound to a broker running inside the cluster. The wrapper fetches secrets through the broker, which proxies the request back through the bridge to OpenBao.
┌──────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌────────────────┐ ┌─────────────────────┐ │
│ │ wrapper (pod) │─────>│ broker (in-cluster) │ │
│ └────────────────┘ │ cloudtaser-broker │ │
│ │ svc :8443 │ │
│ ┌────────────────┐ │ │ │
│ │ wrapper (pod) │─────>│ │ │
│ └────────────────┘ └──────────┬──────────┘ │
│ │ gRPC/mTLS │
└─────────────────────────────────────┼─────────────┘
│
(outbound from vault)
│
┌─────────────────────────────────────┼─────────────┐
│ EU Vault Server (Hetzner / OVH) │ │
│ │ │
│ ┌────────────────────┐ ┌────────┴────────────┐ │
│ │ OpenBao / Vault │<──│ vault-bridge │ │
│ │ :8200 (localhost) │ │ (outbound only) │ │
│ └────────────────────┘ └─────────────────────┘ │
│ │
│ Firewall: DENY ALL INBOUND │
│ ALLOW OUTBOUND to broker endpoint │
└─────────────────────────────────────────────────────┘
Connection Flow¶
- vault-bridge starts on the OpenBao server and connects outbound to the cluster's broker endpoint (a LoadBalancer or Ingress with a stable DNS name)
- broker accepts the bridge connection and holds it open as a persistent gRPC stream with mTLS
- When a wrapper needs to fetch secrets, it sends the request to the broker's in-cluster service (
cloudtaser-broker.cloudtaser-system.svc:8443) - The broker proxies the OpenBao API request through the bridge connection to the OpenBao server
- vault-bridge forwards the request to the local OpenBao instance (
localhost:8200) - The OpenBao response travels back through the same path: OpenBao -> bridge -> broker -> wrapper
What Is Exposed¶
| Component | Network Exposure |
|---|---|
| OpenBao server | None. No inbound ports. Egress-only firewall. |
| vault-bridge | None. Outbound connection only. No listening ports. |
| Broker (in-cluster) | Cluster-internal service on port 8443, plus a public endpoint for the bridge to connect to (LoadBalancer or Ingress) |
| Wrapper | None. Connects to in-cluster broker service only. |
The only publicly reachable component is the broker's external endpoint, which accepts connections exclusively from the vault-bridge using mTLS with pinned certificates.
Security Properties¶
Zero inbound attack surface on OpenBao¶
The OpenBao server's firewall denies all inbound traffic. There is no port to scan, no TLS handshake to probe, no endpoint to DDoS. OpenBao is invisible from the internet.
OpenBao controls the connection¶
The vault-bridge initiates and maintains the connection. If the OpenBao operator wants to disconnect, they stop the bridge. The cluster cannot force a connection to OpenBao. This gives the OpenBao operator (the EU data controller) full control over when and whether secrets are accessible.
mTLS with certificate pinning¶
The bridge-to-broker connection uses mutual TLS with pinned certificates. The broker only accepts connections from bridges presenting a known client certificate. The bridge only connects to brokers presenting a known server certificate. Certificate rotation is handled by the cloudtaser operator.
No secret data in the broker¶
The broker is a transparent proxy. It forwards encrypted OpenBao API requests and responses without inspecting or caching them. The broker never holds secret values. If the broker is compromised, the attacker sees only TLS-encrypted OpenBao API traffic and cannot decrypt it without the wrapper's OpenBao token.
Connection resilience¶
The bridge maintains a persistent connection with automatic reconnection. If the connection drops (network interruption, broker pod restart), the bridge reconnects within seconds. Wrappers that need secrets during a disconnection retry with exponential backoff until the bridge reconnects.
Comparison: Direct vs Reverse Connect¶
| Property | Direct Connect | Reverse Connect |
|---|---|---|
| OpenBao network exposure | Inbound port 8200 required | No inbound ports |
| Firewall rules | Allow inbound from cluster IPs | Allow outbound to broker only |
| Connection initiator | Wrapper (in cluster) | Bridge (on OpenBao server) |
| Network topology | VPC peering, VPN, or public endpoint | Any -- OpenBao just needs outbound HTTPS |
| Latency | Direct TLS connection | One additional hop through broker |
| OpenBao control | OpenBao accepts connections passively | OpenBao actively controls the connection |
| Cross-cloud | Requires network peering or VPN | Works out of the box |
| Air-gap compatible | No (requires runtime connectivity) | No (requires runtime connectivity) |
| Recommended for | Same-VPC or peered-VPC deployments | Cross-cloud, EU-sovereign OpenBao hosting |
When to Use Reverse Connect¶
Reverse connect is recommended when:
- OpenBao is hosted on EU-sovereign infrastructure (Hetzner, OVH, Scaleway) outside the cloud provider's network
- Security policy prohibits any inbound traffic to the OpenBao server
- OpenBao serves clusters across multiple cloud providers (GKE + EKS + AKS)
- There is no VPC peering or VPN between OpenBao network and the cluster network
Direct connect is sufficient when:
- OpenBao and cluster are in the same VPC or privately peered VPCs
- A VPN or WireGuard tunnel connects OpenBao network to the cluster
- OpenBao is hosted on the same cloud provider with private service connectivity
Deployment¶
Broker (in-cluster)¶
The broker is deployed by the cloudtaser Helm chart when reverse-connect mode is enabled:
helm repo add cloudtaser https://charts.cloudtaser.io
helm install cloudtaser cloudtaser/cloudtaser \
--namespace cloudtaser-system \
--create-namespace \
--set operator.secretstore.address=broker://cloudtaser-broker.cloudtaser-system.svc:8443 \
--set broker.enabled=true \
--set broker.externalHost=broker.prod.example.com
The broker creates:
- A Kubernetes Service (
cloudtaser-broker) on port 8443 for in-cluster wrapper traffic - A LoadBalancer or Ingress for the bridge to connect to from outside the cluster
- TLS certificates for mTLS authentication
Bridge (on OpenBao server)¶
The bridge runs alongside OpenBao as a standalone binary or container:
vault-bridge \
--broker-address broker.prod.example.com:443 \
--vault-addr http://127.0.0.1:8200 \
--client-cert /etc/bridge/tls.crt \
--client-key /etc/bridge/tls.key \
--ca-cert /etc/bridge/ca.crt
# http:// is safe here: bind is loopback; the bridge terminates TLS at :443 and proxies plaintext to 127.0.0.1:30200 in the same OS namespace.
Or as a systemd service:
[Unit]
Description=cloudtaser Vault Bridge
After=network-online.target vault.service
Wants=network-online.target
[Service]
# http:// is safe here: bind is loopback; the bridge terminates TLS at :443 and proxies plaintext to 127.0.0.1:30200 in the same OS namespace.
ExecStart=/usr/local/bin/vault-bridge \
--broker-address broker.prod.example.com:443 \
--vault-addr http://127.0.0.1:8200 \
--client-cert /etc/bridge/tls.crt \
--client-key /etc/bridge/tls.key \
--ca-cert /etc/bridge/ca.crt
Restart=always
RestartSec=5
User=vault
[Install]
WantedBy=multi-user.target
OpenBao firewall¶
With reverse connect, the OpenBao server's firewall can be maximally restrictive:
# Deny all inbound
iptables -P INPUT DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow outbound to broker only
iptables -P OUTPUT DROP
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -d <broker-ip> -p tcp --dport 443 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT # DNS resolution
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Related¶
- 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
- Protection Score Reference -- all 12 checks explained