# Cloudflare Tunnel — Dev Container SSH Access ## Overview 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. --- ## Install Requirement Clarification `cloudflared` is required on **both** sides — but they do different things: | 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 | The dev container (LXC) only needs `sshd` running. It does not need cloudflared. **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 cloudflared is not being invoked — SSH is bypassing Cloudflare entirely. --- ## Architecture ``` Developer laptop (cloudflared as ProxyCommand) ↓ ssh dev-6070.zerolaghub.dev Cloudflare edge ↓ CF Tunnel (persistent service on bastion) Bastion VM (private IP, no public exposure) ↓ SSH proxy jump Dev container (10.100.x.x — just needs sshd) ``` --- ## 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 (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 - ⏳ Portal SSH config snippet not yet built --- ## Remaining Steps ### 1. Configure tunnel ingress in Cloudflare Zero Trust dashboard 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 # Linux 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 GitHub releases # Termux — pkg install cloudflared ``` Add to `~/.ssh/config`: ``` Host *.zerolaghub.dev ProxyCommand cloudflared access ssh --hostname %h User dev ``` Then: `ssh dev-6070.zerolaghub.dev` Confirm it's working by looking for in `-v` output: ``` Executing proxy command: cloudflared access ssh --hostname dev-6070.zerolaghub.dev ``` --- ## Portal Integration (Future) Show on the dev container page as an optional section: ``` 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 3. Connect: ssh dev-6070.zerolaghub.dev Or open VS Code Remote Explorer and add this host. ``` --- ## 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 | | `Permission denied` | SSH key not added to container's `dev` user | | Tunnel not connecting | `cloudflared` service not running on bastion — `systemctl status cloudflared` |