refactor: update tunnel command to use host instead of host and port

Kim committed Dec 11, 2025 at 15:07 UTC d9a70bcfb51b3e7fc87a566a393c690055daa4bd
3 files changed +19 -22
cmd/portal-tunnel/main.go
+2 -5
@@ -27,7 +27,6 @@ var (
27 flagConfigPath string
28 flagRelayURLs string
29 flagHost string
30 - flagPort string
30 flagName string
31 flagDesc string
32 flagTags string
@@ -50,8 +49,7 @@ var rootCmd = &cobra.Command{
49 func init() {
50 rootCmd.Flags().StringVar(&flagConfigPath, "config", "", "Path to portal-tunnel config file")
51 rootCmd.Flags().StringVar(&flagRelayURLs, "relay", "ws://localhost:4017/relay", "Portal relay server URLs when config is not provided (comma-separated)")
53 - rootCmd.Flags().StringVar(&flagHost, "host", "localhost", "Local host to proxy to when config is not provided")
54 - rootCmd.Flags().StringVar(&flagPort, "port", "4018", "Local port to proxy to when config is not provided")
52 + rootCmd.Flags().StringVar(&flagHost, "host", "localhost:3000", "target host to proxy to when config is not provided (host:port or URL)")
53 rootCmd.Flags().StringVar(&flagName, "name", "", "Service name when config is not provided (auto-generated if empty)")
54 rootCmd.Flags().StringVar(&flagDesc, "description", "", "Service description metadata")
55 rootCmd.Flags().StringVar(&flagTags, "tags", "", "Service tags metadata (comma-separated)")
@@ -131,10 +129,9 @@ func runExposeWithFlags() error {
129 metadata.Hide = flagHide
130 }
131
134 - target := net.JoinHostPort(flagHost, flagPort)
132 service := &ServiceConfig{
133 Name: strings.TrimSpace(flagName),
137 - Target: target,
134 + Target: flagHost,
135 Metadata: metadata,
136 }
137 applyServiceDefaults(service)
cmd/relay-server/frontend/src/components/TunnelCommandModal.tsx
+16 -16
@@ -16,8 +16,8 @@ interface TunnelCommandModalProps {
16 }
17
18 export function TunnelCommandModal({ trigger }: TunnelCommandModalProps) {
19 - const defaultPort = "3000";
20 - const defaultName = "myapp";
19 + const defaultHost = "localhost:3000";
20 + const defaultName = "your-app-name";
21
22 // Get current host URL dynamically
23 const currentOrigin = useMemo(() => {
@@ -27,7 +27,7 @@ export function TunnelCommandModal({ trigger }: TunnelCommandModalProps) {
27 return "http://localhost:4017";
28 }, []);
29
30 - const [port, setPort] = useState(defaultPort);
30 + const [host, setHost] = useState(defaultHost);
31 const [name, setName] = useState(defaultName);
32 const [relayUrls, setRelayUrls] = useState<string[]>([currentOrigin]);
33 const [urlInput, setUrlInput] = useState("");
@@ -63,11 +63,11 @@ export function TunnelCommandModal({ trigger }: TunnelCommandModalProps) {
63
64 // Generate the tunnel command
65 const command = useMemo(() => {
66 - const portVal = port === "" ? defaultPort : port;
66 + const hostVal = host === "" ? defaultHost : host;
67 const nameVal = name === "" ? defaultName : name;
68 const relayUrlVal = relayUrls.length > 0 ? relayUrls.join(",") : currentOrigin;
69 - return `curl -fsSL ${currentOrigin}/tunnel | PORT=${portVal} NAME=${nameVal} RELAY_URL="${relayUrlVal}" sh`;
70 - }, [currentOrigin, port, name, relayUrls]);
69 + return `curl -fsSL ${currentOrigin}/tunnel | HOST=${hostVal} NAME=${nameVal} RELAY_URL="${relayUrlVal}" sh`;
70 + }, [currentOrigin, host, name, relayUrls]);
71
72 const handleCopy = async () => {
73 try {
@@ -101,27 +101,27 @@ export function TunnelCommandModal({ trigger }: TunnelCommandModalProps) {
101 </DialogHeader>
102
103 <div className="space-y-4 py-4 [&>div]:flex [&>div]:flex-col">
104 - {/* Port Input */}
104 + {/* Host Input */}
105 <div className="space-y-2">
106 <label
107 - htmlFor="port"
107 + htmlFor="host"
108 className="text-sm font-medium text-foreground"
109 >
110 - Local Port
110 + Host
111 </label>
112 <div className="flex items-center rounded-md bg-border">
113 - <span className="px-3 text-sm text-text-muted">PORT=</span>
113 + <span className="px-3 text-sm text-text-muted">HOST=</span>
114 <Input
115 - id="port"
116 - type="number"
117 - value={port}
118 - onChange={(e) => setPort(e.target.value)}
119 - placeholder={defaultPort}
115 + id="host"
116 + type="text"
117 + value={host}
118 + onChange={(e) => setHost(e.target.value)}
119 + placeholder={defaultHost}
120 className="rounded-l-none"
121 />
122 </div>
123 <p className="text-xs text-text-muted">
124 - The port your local service is running on
124 + The hostname or IP:Port where your service is running
125 </p>
126 </div>
127
cmd/relay-server/tunnel.go
+1 -1
@@ -47,7 +47,7 @@ echo "Downloading portal-tunnel ($TUNNEL_OS/$TUNNEL_ARCH)..." >&2
47 curl -fsSL "$BIN_URL" -o "$BIN_PATH"
48 chmod +x "$BIN_PATH"
49
50 -set -- "$BIN_PATH" --relay "$RELAY_URL" --host "${HOST:-localhost}" --port "${PORT:-4018}"
50 +set -- "$BIN_PATH" --relay "$RELAY_URL" --host "${HOST:-localhost:3000}"
51 [ -n "${NAME:-}" ] && set -- "$@" --name "$NAME"
52 [ -n "${DESCRIPTION:-}" ] && set -- "$@" --description "$DESCRIPTION"
53 [ -n "${TAGS:-}" ] && set -- "$@" --tags "$TAGS"