Skip to content

feat: Multi-target LAN routing (Cloudflare Tunnel-style)#15

Open
osa911 wants to merge 22 commits intomainfrom
feat/multi-target-lan-routing
Open

feat: Multi-target LAN routing (Cloudflare Tunnel-style)#15
osa911 wants to merge 22 commits intomainfrom
feat/multi-target-lan-routing

Conversation

@osa911
Copy link
Owner

@osa911 osa911 commented Mar 17, 2026

Summary

  • One CLI instance now serves ALL user tunnels — no more running separate CLI per service
  • Each tunnel maps a domain to a target_host:target_port in the local network (e.g., app.example.com → 192.168.1.5:8080)
  • Dashboard changes push to connected CLI in real-time via gRPC ConfigUpdate messages
  • giraffecloud connect — no --domain flag needed, serves everything

Changes

Database & API

  • Added target_host field to Tunnel schema (default: localhost) with composite unique index on (user_id, target_host, target_port)
  • Removed per-tunnel token field (auth uses API tokens only now)
  • Updated repository, DTOs, mapper, service validation, and handler

Protocol & gRPC Server

  • New proto messages: TunnelRouteConfig, ConfigUpdate, ConfigUpdateReason
  • EstablishTunnel registers one gRPC stream for ALL user domains
  • ControlChannel uses token-based lookup via userStreams map
  • PushConfigUpdate pushes live config changes when tunnels are created/updated/deleted

CLI

  • New RouteTable maps domains to LAN targets
  • gRPC client populates route table from handshake and handles live ConfigUpdate
  • Connect() simplified — just token, no domain/port
  • --domain flag removed

Frontend

  • "Target Host" input in tunnel create/edit dialog (default: localhost)
  • Tunnel list shows full host:port target
  • Getting Started page updated for new flow

Docs

  • README, installation, architecture docs, llms.txt updated

Test plan

  • Create tunnel with default target (localhost:port) — verify backward compat
  • Create tunnel with custom target_host (LAN IP:port) — verify routing
  • Connect CLI with giraffecloud connect — verify all tunnels served
  • Add/edit/delete tunnel in dashboard while CLI connected — verify live ConfigUpdate
  • Disconnect CLI — verify all Caddy routes cleaned up
  • Verify uniqueness constraint: same host+port per user rejected

🤖 Generated with Claude Code

osa911 and others added 22 commits March 17, 2026 12:44
Design for evolving GiraffeCloud from one-CLI-one-tunnel to Cloudflare
Tunnel-style multi-target LAN routing. One CLI instance serves all user
tunnels, each mapping a domain to a target_host:port in the local network.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
20-task plan across 5 chunks: DB/API layer, Protocol/gRPC server,
CLI changes, Frontend changes, and Documentation. Covers all changes
from the approved design spec.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Authentication now uses only the user's API token from the tokens table.
The per-tunnel token field has been removed from the Ent schema, repository,
service, interface, DTO, mapper, and the Ent-generated code was regenerated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…error handling

- Replace parallel Domains/TunnelIDs slices with single DomainMappings slice
  of structs to prevent index desynchronization bugs (C1/C2/C3)
- Use net.SplitHostPort for IPv6-safe port stripping in resolveTargetAddr (I2)
- Add warning log for hardcoded localhost:8080 fallback in resolveTargetAddr (I1)
- Add error handling for GetByUserID calls in config push paths (I6)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant