Security posture
Threat model for the self-hosted relay. What it can and cannot see. What still goes to Viewport.
Self-hosting the relay narrows what hits Viewport-managed infrastructure. It does not eliminate it (today). This page is the precise version of that statement.
What the self-hosted relay sees
- Envelope of every frame: workspace id, runtime target id, frame type, sequence number, timestamp.
- Encrypted payload: opaque ciphertext. The relay cannot decrypt.
- Connection metadata: source IP, TLS fingerprint, daemon version (via the handshake), reconnect attempts.
- Admin endpoint output (when enabled): connection state, recent log buffer, Prometheus metrics.
What the self-hosted relay cannot see
- Session transcript content. Encrypted payloads.
- Plan or context vault content. The relay does not transport plans; it transports session frames. Plans go through the platform REST API.
- Auth credentials. JWTs are validated by the platform and never decrypted by the relay (the relay holds only the signing key's public half via JWKS).
- Member identities. The relay knows install IDs and workspace IDs. Mapping those to humans happens on the platform.
What still goes to Viewport (with relay self-host only)
Even when the relay is on your infrastructure, the following still hit api.getviewport.com:
- All user-facing REST routes (
/api/workspaces,/api/plans,/api/inbox-items,/api/audit,/api/vault,/api/workflows). - Daemon → platform sync (
/api/runtime/*). - Relay → platform JWT validation (
/api/runtime/internal/relay/validate). - Audit log writes.
- Email sends (invitations, password resets) via Resend.
For the relay-only self-host path, the privacy delta vs. fully hosted is:
- In-flight session frames stay in your network.
- At-rest control-plane data (members, plans, inbox, workflows, audit, ciphertext vault) still lives in Viewport's database.
If your compliance posture requires the at-rest data to also be on your infrastructure, see On-prem roadmap.
Threat model
What we're defending against:
| Threat | Mitigation |
|---|---|
| Network eavesdropper between daemon and relay | TLS (your terminator). Noise-encrypted payload underneath. |
| Compromised relay operator (us, or a malicious admin on your side) | Relay sees ciphertext only. No decryption keys on the relay. |
| Compromised platform database | Ciphertext-only vault. No transcript table. |
| Stolen daemon keypair | Per-org keypair limits blast radius. Revoke via Machines → Revoke. |
| Replay of session frames | Per-direction nonces; relay enforces sequence. |
| Cross-tenant query injection | Global row-level scope on every tenant table; failure mode is empty result, not leak. |
What we're not (yet) defending against:
- A malicious local admin on a developer's laptop. They have file access; they can read keys at
~/.viewport/relay-identities/. Mitigations: file mode 0o600, OS-level disk encryption, future HSM-backed keys. - A compromised Viewport platform admin with database access. They can read everything except ciphertext vault and (non-existent) session transcripts. Members, plans, inbox, audit, workflows are all in plaintext.
TLS strategy
The relay can run plain WS behind your TLS terminator (recommended), or run TLS directly via RELAY_TLS_CERT / RELAY_TLS_KEY.
Recommendation: terminate TLS in your load balancer (ALB, NGINX, Caddy, whatever). Run the relay container on plain WS. This lets you handle cert rotation in your standard infra.
If you must run TLS in the relay itself, mount the cert/key files into the container and set the env vars.
IP allow-listing
Two layers:
- Network-level: your load balancer or VPC firewall. Only your developers' IP ranges can reach the relay endpoint.
- Per-workspace: set
policy_mode=crypto_pairingon the workspace to require Noise IKpsk2 (pre-shared key) instead of plain Noise IK. Adds a second factor to the handshake.
For workspaces that need both: use both. Network ACLs are the cheap general-purpose answer; crypto pairing adds defense-in-depth.
Audit-grade ops
If you're operating the relay for an audited environment:
- Log retention: send container stdout to your log pipeline; retain per your policy.
- Access control: secret manager for
RELAY_ADMIN_TOKEN,RELAY_INTERNAL_KEY. Rotate quarterly. - Change management: pin to a specific image tag, not
latest. Update through your standard deploy review. - Incident drill: practice revoking a pairing. Document the runbook.
Where to go next
- Concepts: Trust and privacy. The broader story.
- Deploy the relay.
- On-prem roadmap.