runner: publish gRPC port + grpcs:// for TLS via Caddy Verified
The runner gRPC port (9443) wasn't being published on the host —
only the cave-net podman network could reach it. That made a
laptop runner impossible. Three changes:
cavectl:
- New ports.grpc (default 9443) and ports.grpc_bind (default
"127.0.0.1") in cave.yaml; cavectl init picks a free port near
9443.
- createCave publishes the gRPC port via ports.grpc_bind.
Set ports.grpc_bind: 0.0.0.0 on a public VPS to let remote
runners connect.
Runner client TLS:
- parse-grpc-url now recognizes grpcs:// alongside grpc://, returns
a third value (tls-p), defaults the grpcs port to 443.
- handle-runner threads :tls tls-p into the two ag-grpc:make-channel
calls (initial register + the watch-loop reconnect).
- This lets you front cave's plaintext h2c gRPC with Caddy:
runner.cave.example.com {
reverse_proxy h2c://127.0.0.1:9443
}
Runners then connect with --url grpcs://runner.cave.example.com,
Caddy terminates Let's Encrypt TLS, talks h2c to cave's :9443
on loopback.
Runner registration UI:
- Was hardcoded to grpc://localhost:9443. New runner-grpc-url
helper derives the right URL from :runner-public-url (override)
or :base-url's host on :grpc-port, so the copy-paste command on
the Admin / Settings runner pages reflects the actual deploy.
Caveat documented in cavectl config: cave's gRPC has no native TLS
yet; over the public internet without Caddy in front, the runner
auth token is sent in clear. Use grpcs:// (Caddy in front) or
restrict to a trusted network.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>