Clarify CF Tunnel SSH is power-user only — client install required, not zero-install
This commit is contained in:
parent
9ae64dab91
commit
8f73f60ed9
@ -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-<vmid>.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
|
||||
|
||||
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 |
|
||||
|
||||
Loading…
Reference in New Issue
Block a user