Skip to main content
← Back to list
01Issue
BugClosedSwamp CLI
Assigneesstack72

Relationships

#1629 Remote execution has no working network configuration: off-loopback serve requires TLS, but worker connect cannot connect over TLS

Opened by kiljoy · 8/12/2026

Version: 20260723.235316.0-sha.a6927867 (both ends) Orchestrator: macOS 15 / darwin-arm64 Worker: Ubuntu 24.04 / linux-x86_64

Summary

swamp serve refuses to bind a non-loopback address without TLS. swamp worker connect cannot complete a WebSocket handshake against a TLS listener, because the server negotiates HTTP/2 via ALPN and the client speaks only HTTP/1.1.

The two constraints are mutually exclusive, so there is no configuration in which a worker on another host can enroll — which is the documented purpose of remote execution.

Reproduction

1. Off-loopback without TLS is refused:

$ swamp serve --host 100.x.y.z --port 9090 --auth-mode none
Error: Off-loopback binding requires TLS — provide --cert-file and --key-file, or bind to 127.0.0.1

2. With a valid TLS cert, serve starts normally. (Cert here is a real Let's Encrypt certificate issued by tailscale cert; openssl x509 confirms CN and SAN match the hostname used below, and the key matches the cert.)

$ swamp serve --host 100.x.y.z --port 9090 --auth-mode token --admins "user:ryan" \
    --cert-file ~/.config/swamp-serve/host.crt --key-file ~/.config/swamp-serve/host.key
[INF] serve  listening

3. The worker cannot connect to it:

$ swamp worker connect wss://myhost.example.ts.net:9090 \
    --token <name>.<secret> --label host=behemoth --cache-dir ~/.swamp-worker
Connecting to wss://myhost.example.ts.net:9090 (attempt 1)...
Disconnected: socket closed before enrollment: NetworkError: failed to connect to WebSocket: HTTP/2 not supported by this client
Reconnecting in 1s
Connecting to wss://myhost.example.ts.net:9090 (attempt 2)...
Disconnected: socket closed before enrollment: NetworkError: failed to connect to WebSocket: HTTP/2 not supported by this client

It retries indefinitely and never enrolls.

Control

The same worker binary, same enrollment token, same cache dir, enrolls immediately against a plaintext loopback listener reached through an SSH reverse tunnel:

$ swamp serve --host 127.0.0.1 --port 9094 --auth-mode token --admins "user:ryan"

$ swamp worker connect ws://127.0.0.1:9094 \
    --token <name>.<secret> --server-token <name>.<secret> \
    --label host=behemoth --cache-dir ~/.swamp-worker --concurrency 4
[INF] worker·connect: Enrolled as "behemoth-ocr"
✓ Enrolled as behemoth-ocr

So the failure is specific to the TLS transport, not to the token, the labels, the cache dir, or network reachability.

Actual vs expected

  • Actual: wss:// never enrolls; HTTP/2 not supported by this client.
  • Expected: worker connect enrolls over wss://, either by the client offering http/1.1 in ALPN or by the server accepting http/1.1 for the WebSocket upgrade path.

Notes

  • Neither side appears to expose a flag to force HTTP/1.1. Checked the full option lists via swamp help serve and swamp help worker connect.
  • references/workflow/references/remote-execution.md documents swamp worker connect ws://orchestrator.internal:4000, i.e. plaintext over a routable hostname. That example cannot be followed, since serve will not bind off-loopback without TLS.

Workaround

Bind serve to 127.0.0.1 and reach it from the worker host through an SSH reverse tunnel (ssh -N -R 9094:127.0.0.1:9094 worker-host). Plaintext ws:// on the worker's own loopback, transport encryption from SSH. This works, and a placed workflow has run to completion over it.

02Bog Flow
OPENTRIAGEDIN PROGRESSCLOSED+ 1 MOREASSIGNEDCLASSIFICATION

Closed

8/12/2026, 8:51:55 PM

No activity in this phase yet.

03Sludge Pulse
stack72 assigned stack728/12/2026, 8:41:14 PM
Editable. Press Enter to edit.

stack72 commented 8/12/2026, 8:51:55 PM

Hey @kiljoy — thanks for the detailed report! The version you're running (20260723) is missing a fix that shipped shortly after: we improved how the WebSocket client classifies TLS connection errors, which was causing Deno to surface a misleading "HTTP/2 not supported" message. Could you update to the latest version (swamp update) and try the wss:// worker connection again? If it still fails after updating, reopen this and we'll dig deeper.

Sign in to post a ripple.