feat: add TLS support for demo app and portal tunnel, enhance command handling for TLS configuration

rabbitprincess committed Feb 25, 2026 at 23:12 UTC 6642a00a4b0ee1c7342bd79066f4302f31c84fc0
5 files changed +18 -12
cmd/demo-app/main.go
+7 -1
@@ -34,6 +34,7 @@ var (
34 flagTags string
35 flagOwner string
36 flagHide bool
37 + flagTLS bool
38 )
39
40 func main() {
@@ -44,6 +45,7 @@ func main() {
45 flag.StringVar(&flagTags, "tags", "demo,connectivity,activity,cloud,sun,moning", "comma-separated lease tags")
46 flag.StringVar(&flagOwner, "owner", "PortalApp Developer", "lease owner")
47 flag.BoolVar(&flagHide, "hide", false, "hide this lease from listings")
48 + flag.BoolVar(&flagTLS, "tls", true, "enable TLS (end-to-end encryption via ACME DNS-01)")
49
50 flag.Parse()
51
@@ -54,7 +56,11 @@ func main() {
56
57 func runDemo() error {
58 // 1) Create SDK client and connect to relay(s)
57 - client, err := sdk.NewClient(sdk.WithBootstrapServers([]string{flagServerURL}))
59 + opts := []sdk.ClientOption{sdk.WithBootstrapServers([]string{flagServerURL})}
60 + if flagTLS {
61 + opts = append(opts, sdk.WithTLS())
62 + }
63 + client, err := sdk.NewClient(opts...)
64 if err != nil {
65 return fmt.Errorf("new client: %w", err)
66 }
cmd/portal-tunnel/main.go
+1 -1
@@ -25,7 +25,7 @@ type Config struct {
25 Name string `flag:"name" env:"APP_NAME" about:"Service name"`
26
27 // TLS Mode
28 - TLSEnable bool `flag:"tls" env:"TLS_ENABLE" about:"Enable TLS termination on tunnel client (uses relay ACME DNS-01)"`
28 + TLSEnable bool `flag:"tls" env:"TLS_ENABLE" default:"true" about:"Enable TLS termination on tunnel client (uses relay ACME DNS-01)"`
29
30 // Metadata
31 Protocols string `flag:"protocols" env:"APP_PROTOCOLS" default:"http/1.1,h2" about:"ALPN protocols (comma-separated)"`
cmd/relay-server/frontend/src/components/TunnelCommandModal.tsx
-5
@@ -229,11 +229,6 @@ export function TunnelCommandModal({ trigger }: TunnelCommandModalProps) {
229 </div>
230 </div>
231
232 - {/* className="text-xs text-text-muted">
233 - Press Enter to add. Multiple relay servers for redundancy.
234 - </p>
235 - </div>
236 -
232 {/* Generated Command */}
233 <div className="space-y-2">
234 <label className="text-sm font-medium text-foreground">
cmd/relay-server/tunnel.go
+4
@@ -54,6 +54,9 @@ set -- "$BIN_PATH" --relay "$RELAY_URL" --host "${HOST:-localhost:3000}"
54 if [ "${HIDE:-}" = "1" ] || [ "${HIDE:-}" = "true" ]; then
55 set -- "$@" --hide
56 fi
57 +if [ "${TLS:-}" = "0" ] || [ "${TLS:-}" = "false" ]; then
58 + set -- "$@" --tls=false
59 +fi
60
61 echo "Starting portal-tunnel..." >&2
62 exec "$@"
@@ -98,6 +101,7 @@ if ($env:TAGS) { $ArgsList += "--tags", $env:TAGS }
101 if ($env:THUMBNAIL) { $ArgsList += "--thumbnail", $env:THUMBNAIL }
102 if ($env:OWNER) { $ArgsList += "--owner", $env:OWNER }
103 if ($env:HIDE -eq "1" -or $env:HIDE -eq "true") { $ArgsList += "--hide" }
104 +if ($env:TLS -eq "0" -or $env:TLS -eq "false") { $ArgsList += "--tls=false" }
105
106 Write-Host "Starting portal-tunnel..."
107 try {
sdk/client.go
+6 -5
@@ -114,7 +114,12 @@ func (c *Client) Listen(name string, options ...MetadataOption) (net.Listener, e
114 return nil, fmt.Errorf("create relay listener: %w", err)
115 }
116
117 - // For TLS mode, initialize certificate after listener is created but before Start
117 + // Register lease with relay BEFORE requesting certificate
118 + if err := listener.Start(); err != nil {
119 + return nil, fmt.Errorf("start relay listener: %w", err)
120 + }
121 +
122 + // For TLS mode, initialize certificate after lease is registered
123 if c.config.TLSEnabled {
124 autoMgr := NewAutoCertManager(relayAddr, name, lease.ID, reverseToken)
125 if err := autoMgr.Initialize(context.Background()); err != nil {
@@ -125,10 +130,6 @@ func (c *Client) Listen(name string, options ...MetadataOption) (net.Listener, e
130 autoMgr.StartRenewal()
131 }
132
128 - if err := listener.Start(); err != nil {
129 - return nil, fmt.Errorf("start relay listener: %w", err)
130 - }
131 -
133 c.leases[lease.ID] = lease
134
135 if c.config.TLSEnabled {