From 8f73f60ed9059994e6092a8fe39cf58acc353517 Mon Sep 17 00:00:00 2001 From: jester Date: Thu, 26 Mar 2026 20:58:53 +0000 Subject: [PATCH] =?UTF-8?q?Clarify=20CF=20Tunnel=20SSH=20is=20power-user?= =?UTF-8?q?=20only=20=E2=80=94=20client=20install=20required,=20not=20zero?= =?UTF-8?q?-install?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- network/cf-tunnel-ssh.md | 190 +++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 110 deletions(-) diff --git a/network/cf-tunnel-ssh.md b/network/cf-tunnel-ssh.md index b15cca2..240568c 100644 --- a/network/cf-tunnel-ssh.md +++ b/network/cf-tunnel-ssh.md @@ -2,70 +2,65 @@ ## Overview -Cloudflare Tunnel provides SSH access to dev containers for developers using -local VS Code or terminal. No VPN required. Uses the same hostname as the -browser IDE. +CF Tunnel SSH provides local VS Code / terminal access to dev containers for +developers who want to use their own tooling instead of the browser IDE. + +**This is a power-user feature, not zero-install.** It requires `cloudflared` +installed on the developer's local machine. The browser IDE remains the +zero-install option for all developers. --- -## How It Works — Two Sides +## Install Requirement Clarification -This requires `cloudflared` on **both** the server (bastion) and the client -(developer machine). They do completely different things: +`cloudflared` is required on **both** sides — but they do different things: -**Bastion (server side):** -`cloudflared` runs as a persistent service maintaining an outbound tunnel to -Cloudflare's edge. This is already set up. +| Side | Role | +|------|------| +| Bastion VM | `cloudflared` runs as a persistent service maintaining the outbound tunnel to Cloudflare | +| Developer's local machine | `cloudflared` acts as an SSH ProxyCommand — routes SSH through Cloudflare instead of directly to the IP | -**Developer machine (client side):** -`cloudflared` is a lightweight binary used as an SSH ProxyCommand. It -intercepts the SSH connection and routes it through Cloudflare instead of -going directly to the IP. Without this, SSH bypasses Cloudflare entirely, -hits the raw IP on port 22, and gets rejected. +The dev container (LXC) only needs `sshd` running. It does not need cloudflared. -The two sides meet at Cloudflare — no inbound ports needed on either: - -``` -Developer machine - cloudflared (ProxyCommand) → Cloudflare edge ← cloudflared (tunnel) - ↓ - Bastion VM - ↓ - Dev container -``` - -**Critical:** If SSH connects directly to the IP instead of through -cloudflared, you will see: +**Without the ProxyCommand on the client, SSH goes directly to the raw IP and +gets rejected.** You will see: ``` kex_exchange_identification: Connection closed by remote host ``` -This means the ProxyCommand is not being invoked — SSH is bypassing -Cloudflare entirely. +This means cloudflared is not being invoked — SSH is bypassing Cloudflare entirely. --- ## Architecture ``` -Developer laptop - ↓ ssh dev-6070.zerolaghub.dev (via cloudflared ProxyCommand) +Developer laptop (cloudflared as ProxyCommand) + ↓ ssh dev-6070.zerolaghub.dev Cloudflare edge - ↓ CF Tunnel (persistent, runs on bastion) + ↓ CF Tunnel (persistent service on bastion) Bastion VM (private IP, no public exposure) ↓ SSH proxy jump -Dev container (10.100.x.x) +Dev container (10.100.x.x — just needs sshd) ``` -HTTPS and SSH share the same hostname. Cloudflare routes them separately: -- HTTPS → Traefik → API → container (browser IDE) -- SSH → CF Tunnel → bastion → container +--- + +## Zero-Install vs Power-User Access + +| Access Method | Install Required | Use Case | +|--------------|-----------------|----------| +| Browser IDE (`dev-.zerolaghub.dev`) | Nothing | All developers — zero friction | +| CF Tunnel SSH | `cloudflared` on local machine | Power users wanting local VS Code or terminal | + +The browser IDE is the primary access method. CF Tunnel SSH is optional and +for developers who specifically want local tool integration. --- ## Current State - ✅ CF Tunnel created and connected to bastion VM -- ✅ Cloudflare Zero Trust free plan active (covers up to 50 users) +- ✅ Cloudflare Zero Trust free plan active (up to 50 users) - ⏳ Tunnel SSH hostname mapping not yet configured in Zero Trust dashboard - ⏳ Bastion SSH proxy jump config not yet done - ⏳ Dev container SSH server not yet verified @@ -75,10 +70,40 @@ HTTPS and SSH share the same hostname. Cloudflare routes them separately: ## Remaining Steps -### 1. Install cloudflared on developer machines +### 1. Configure tunnel ingress in Cloudflare Zero Trust dashboard -This is required on every developer's machine — not optional. +Zero Trust → Networks → Tunnels → your tunnel → Configure: +Add a public hostname: +- Subdomain: `*` (wildcard) +- Domain: `zerolaghub.dev` +- Service type: `SSH` +- URL: `localhost:22` + +### 2. Configure bastion SSH for proxy jump + +Edit `/etc/ssh/sshd_config` on the bastion: + +``` +AllowTcpForwarding yes +PermitOpen 10.100.0.0/24:22 +``` + +Restart: `systemctl restart sshd` + +### 3. Ensure dev containers have SSH running + +Add to agent dev provisioning pipeline: + +```bash +apt-get install -y openssh-server +systemctl enable ssh +systemctl start ssh +``` + +### 4. Developer one-time setup (power users only) + +Install cloudflared on their local machine: ```bash # macOS brew install cloudflare/cloudflare/cloudflared @@ -87,107 +112,52 @@ brew install cloudflare/cloudflare/cloudflared curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \ -o /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared -# Windows -# Download from https://github.com/cloudflare/cloudflared/releases - -# Termux (Android) -pkg install cloudflared +# Windows — download from GitHub releases +# Termux — pkg install cloudflared ``` -### 2. Developer SSH config (one-time) - -Developer adds this to `~/.ssh/config`: - +Add to `~/.ssh/config`: ``` Host *.zerolaghub.dev ProxyCommand cloudflared access ssh --hostname %h User dev ``` -This is what makes `ssh dev-6070.zerolaghub.dev` route through Cloudflare -instead of going directly to the IP. Without this config, SSH will fail. +Then: `ssh dev-6070.zerolaghub.dev` -To confirm it's working, run with `-v` and look for: +Confirm it's working by looking for in `-v` output: ``` Executing proxy command: cloudflared access ssh --hostname dev-6070.zerolaghub.dev ``` -### 3. 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` - -### 4. Configure bastion SSH for proxy jump - -On the bastion, edit `/etc/ssh/sshd_config`: - -``` -AllowTcpForwarding yes -PermitOpen 10.100.0.0/24:22 -``` - -Restart SSH: `systemctl restart sshd` - -### 5. Ensure dev containers have SSH running - -Each dev container needs openssh-server installed. Add to agent dev -provisioning pipeline: - -```bash -apt-get install -y openssh-server -systemctl enable ssh -systemctl start ssh -``` - -### 6. VS Code Remote SSH - -After SSH config is in place, developer opens VS Code → Remote Explorer → -Add new host → `ssh dev-6070.zerolaghub.dev`. VS Code handles the rest. - ---- - -## 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 -- `cloudflared` on the client is a lightweight binary, not a service -- code-server runs `--auth none` — SSH is enforced separately at OS level - --- ## Portal Integration (Future) -Portal dev container page should show: +Show on the dev container page as an optional section: ``` -SSH Access -────────── -1. Install cloudflared: https://developers.cloudflare.com/cloudflared/install +Local VS Code Access (Advanced) +──────────────────────────────── +Requires a one-time install of cloudflared on your machine. +1. Install: https://developers.cloudflare.com/cloudflared/install 2. Add to ~/.ssh/config: -Host *.zerolaghub.dev - ProxyCommand cloudflared access ssh --hostname %h - User dev + Host *.zerolaghub.dev + ProxyCommand cloudflared access ssh --hostname %h + User dev -3. Connect: -ssh dev-6070.zerolaghub.dev +3. Connect: ssh dev-6070.zerolaghub.dev + Or open VS Code Remote Explorer and add this host. ``` -One-time setup. Works for all dev containers after that. - --- ## Troubleshooting | Issue | Likely Cause | -|-------|--------------| +|-------|-------------| | `kex_exchange_identification: Connection closed` | ProxyCommand not in SSH config — SSH going direct to IP | | `cloudflared: command not found` | cloudflared not installed on client machine | | `Connection refused` | SSH not running in container or bastion jump not configured |