From 5dee426686986de39e815eef0b2b7cb2772c81ae Mon Sep 17 00:00:00 2001 From: jester Date: Wed, 25 Mar 2026 21:10:27 +0000 Subject: [PATCH] Add CF Tunnel SSH doc with current state and remaining steps --- network/cf-tunnel-ssh.md | 154 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 network/cf-tunnel-ssh.md diff --git a/network/cf-tunnel-ssh.md b/network/cf-tunnel-ssh.md new file mode 100644 index 0000000..fc20e78 --- /dev/null +++ b/network/cf-tunnel-ssh.md @@ -0,0 +1,154 @@ +# Cloudflare Tunnel — Dev Container SSH Access + +## Overview + +Cloudflare Tunnel provides SSH access to dev containers for developers using +local VS Code or terminal. No VPN client required. Uses the same hostname as +the browser IDE. + +--- + +## Architecture + +``` +Developer laptop + ↓ ssh dev-6070.zerolaghub.dev +Cloudflare edge + ↓ CF Tunnel (persistent, runs on bastion) +Bastion VM (private IP, no public exposure) + ↓ SSH proxy jump +Dev container (10.100.x.x) +``` + +HTTPS and SSH share the same hostname. Cloudflare routes them separately: +- HTTPS → Traefik → API → container (browser IDE) +- SSH → CF Tunnel → bastion → container + +--- + +## Current State + +- ✅ CF Tunnel created and connected to bastion VM +- ✅ Cloudflare Zero Trust free plan active (covers up to 50 users) +- ⏳ Tunnel configuration not fully complete +- ⏳ SSH hostname mapping not yet configured +- ⏳ Bastion SSH proxy jump not yet configured +- ⏳ Dev containers SSH not yet verified reachable from bastion +- ⏳ Portal SSH config snippet not yet built + +--- + +## Remaining Steps + +### 1. Configure tunnel ingress in Cloudflare Zero Trust dashboard + +In Zero Trust → Networks → Tunnels → your tunnel → Configure: + +Add a public hostname: +- Subdomain: `*` (wildcard) or specific `dev-ssh` +- Domain: `zerolaghub.dev` +- Service type: `SSH` +- URL: `localhost:22` + +This routes SSH traffic arriving at Cloudflare for `*.zerolaghub.dev` through +the tunnel to port 22 on the bastion. + +### 2. Configure bastion SSH for proxy jump + +On the bastion, edit `/etc/ssh/sshd_config` to allow the bastion to act as +a jump host into dev containers: + +``` +# Allow TCP forwarding for proxy jump +AllowTcpForwarding yes +PermitOpen any +``` + +Or scope it to the container subnet only: +``` +PermitOpen 10.100.0.0/24:22 +``` + +Restart SSH: `systemctl restart sshd` + +### 3. Ensure dev containers have SSH running + +Each dev container needs an SSH server running and accessible from the bastion: + +```bash +# In dev container +apt-get install -y openssh-server +systemctl enable ssh +systemctl start ssh +``` + +The agent should handle this as part of dev container provisioning — add to +agent's dev provisioning pipeline. + +### 4. Developer one-time setup + +Developer adds this to `~/.ssh/config` (portal will surface this as a +copyable snippet): + +``` +Host *.zerolaghub.dev + ProxyCommand cloudflared access ssh --hostname %h + User dev +``` + +After that: +```bash +ssh dev-6070.zerolaghub.dev +``` + +### 5. VS Code Remote SSH + +Developer opens VS Code → Remote Explorer → Add new host: +``` +ssh dev-6070.zerolaghub.dev +``` + +VS Code handles the rest — connects through the tunnel, mounts the workspace. + +--- + +## Security Notes + +- Bastion has no public IP — all SSH access goes through CF Tunnel only +- CF Tunnel is outbound-only from bastion to Cloudflare — no inbound ports open +- Zero Trust free tier: up to 50 users, core access control included +- Developer must have `cloudflared` installed locally for the ProxyCommand +- code-server runs `--auth none` — SSH access is separate and enforced at + the OS level by the SSH server in the container + +--- + +## Portal Integration (Future) + +Portal dev container page should show: + +``` +SSH Access +────────── +Copy this to your ~/.ssh/config: + +Host *.zerolaghub.dev + ProxyCommand cloudflared access ssh --hostname %h + User dev + +Then connect with: +ssh dev-6070.zerolaghub.dev +``` + +One-time setup. Works for all dev containers after that. + +--- + +## Troubleshooting + +| Issue | Likely Cause | +|-------|--------------| +| `cloudflared: command not found` | Developer needs to install cloudflared client | +| `Connection refused` | SSH not running in container or bastion jump not configured | +| `Permission denied` | SSH key not added to container's `dev` user | +| Tunnel not connecting | `cloudflared` service not running on bastion — check `systemctl status cloudflared` |