Skip to main content

Dev box / jump box SSH over Cloudflare WARP

Private, VPN-only SSH to the vbhel jump box (also the beta-dev Docker-Compose host, public IP 65.21.252.138). SSH is reached only through Cloudflare WARP — once the public firewall closes port 22, the box has no public SSH surface. Auth is WARP enrollment (any @upsquad.ai device in the upsquad Zero Trust org).

This is the manually-managed dev-box counterpart to the GCP env access plane (ADR-0018 §2.5 / core#1282). The dev box stays outside Pulumi/GCP per ADR-0001, so this path is configured on the host + the Cloudflare API, not in IaC.

Components (all live)

PieceValue
Zero Trust accountb12538c0dc2fb7882da39a7cc280596c (upsquad)
Tunneldevbox-ssh — id 26caa5ed-1067-4d47-8414-af9025d22882
WARP route65.21.252.138/32devbox-ssh, default vnet c31e82cf-7067-4eb5-b879-42aa82ebf22e
Connectorsystemd unit cloudflared-devbox-ssh.service on vbhel
Token/etc/cloudflared/devbox-ssh.env (TUNNEL_TOKEN=…, root, mode 600)
warp-routingenabled on the tunnel; no public ingress hostnames

The connector is a dedicated tunnel, separate from the upsquad tunnel that serves the public hostnames (research/app/upsquad.ai) — so the emergency SSH path is not coupled to the web tunnel's lifecycle.

Connecting (engineers)

  1. Install the Cloudflare WARP client and enroll: Login with Cloudflare Zero Trust, team name upsquad (upsquad.cloudflareaccess.com), authenticate with your @upsquad.ai identity. (Device-enrollment policy must allow @upsquad.ai — same enrollment the beta env uses.)
  2. With WARP connected: ssh <user>@65.21.252.138 — routed edge → tunnel → connector → local sshd.
  3. With WARP disconnected (after the firewall is closed): the same command times out. That is the intended VPN-only posture.

Closing the public SSH surface (FINAL step — do after verifying step 2)

The "bastion firewall" is the Hetzner Cloud Firewall in front of vbhel (the host itself runs no ufw/iptables). After confirming SSH-over-WARP works for at least one operator, remove the public inbound tcp/22 allow in the Hetzner Cloud Console (or via hcloud firewall). Do not close 22 before a successful WARP SSH test — there is no other ingress path and the connector's WARP edge hop cannot be tested from the host itself.

Rollback if locked out: re-open tcp/22 in the Hetzner firewall from the console.

Token rotation

# regenerate the connector token (Zero Trust account, scoped API token)
curl -s -X POST -H "Authorization: Bearer $CF_API_TOKEN" \
".../accounts/b12538c0.../cfd_tunnel/26caa5ed.../token" # returns new token
# write it back (never echo to a shell history / argv):
{ printf 'TUNNEL_TOKEN='; cat newtoken; echo; } | sudo tee /etc/cloudflared/devbox-ssh.env
sudo systemctl restart cloudflared-devbox-ssh.service

Health check

curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
".../accounts/b12538c0.../cfd_tunnel/26caa5ed..." | jq '.result.status' # "healthy"
systemctl is-active cloudflared-devbox-ssh.service # "active"

Known cruft (unrelated)

cloudflared.service (distinct from cloudflared-devbox-ssh.service and cloudflared-upsquad.service) is a broken leftover unit whose ExecStart points at a missing /tmp/cloudflared binary; it flaps in auto-restart. Safe to systemctl disable --now cloudflared.service — left untouched here because it was pre-existing and outside this change's scope.