No description
  • Go 93.4%
  • Dockerfile 6.6%
Find a file
Wesley Channon c62f1da05c
All checks were successful
build / image (push) Successful in 18s
docs: add CLAUDE.md (repo guide) + reconcile refs post server→tachyne-world consolidation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WeJ6iwfdAvxp53wXjd42WH
2026-07-09 09:37:26 +02:00
.forgejo/workflows feat: version-routing front door on the official port 2026-07-06 15:33:41 +02:00
cmd/dispatch log routed login connections (proto + target) 2026-07-06 18:21:04 +02:00
deploy ops: dispatch replicas 2 + zero-downtime rollout (front door was a singleton SPOF) 2026-07-07 10:58:41 +02:00
.dockerignore feat: version-routing front door on the official port 2026-07-06 15:33:41 +02:00
CLAUDE.md docs: add CLAUDE.md (repo guide) + reconcile refs post server→tachyne-world consolidation 2026-07-09 09:37:26 +02:00
dispatch docs: add CLAUDE.md (repo guide) + reconcile refs post server→tachyne-world consolidation 2026-07-09 09:37:26 +02:00
Dockerfile fix: copy the binary to the path the entrypoint runs 2026-07-06 15:37:11 +02:00
go.mod feat: version-routing front door on the official port 2026-07-06 15:33:41 +02:00
go.sum feat: version-routing front door on the official port 2026-07-06 15:33:41 +02:00
README.md docs: add README (routing model, PROXY v1, env, design boundaries) 2026-07-07 08:50:44 +02:00

tachyne-dispatch

The tachyne cluster's public Minecraft front door (192.168.1.10:25565): a tiny protocol-version router. It reads the client's Handshake, picks the gateway deployment that serves that protocol, replays the handshake to it and splices the two TCP streams byte-for-byte from then on. Unknown versions get an honest local answer: a server-list ping showing what IS supported, or a login disconnect naming the supported versions.

Deliberately dumb, by design:

  • Version-blind beyond the handshake, identity-blind always. Dispatch never parses login, never sees names/UUIDs, and does no authorization — policy lives in the gateways (via tachyne-access). At most it may someday grow IP-level pre-filtering.
  • One code path per connection: peek handshake → route → splice. No per-version logic here; adding a protocol is a DISPATCH_ROUTES entry (plus a gateway that serves it).
  • PROXY protocol v1 (DISPATCH_PROXY=1): each spliced connection is prefixed with the real client address; both gateways parse it (tachyne-common/proxyproto) so access checks and logs see LAN IPs, not the pod SNAT. The Service uses externalTrafficPolicy: Local — without it kube-proxy SNAT hides the source before dispatch ever sees it.

Configuration (env)

DISPATCH_LISTEN     listen address                     (default ":25565")
DISPATCH_ROUTES     "770-772=host:port,776=host:port"  (required)
DISPATCH_SUPPORTED  human-readable list for unknown versions
                    (default "1.21.5-1.21.8 and 26.2")
DISPATCH_PROXY      "1" = prefix PROXY protocol v1 to backends

Live routing: 770-772 → tachyne-gw-java-770 svc :25570, 776 → tachyne-gw-java-776 svc :25565 (both cluster-internal — dispatch is the only externally reachable Minecraft port, via externalIPs: [192.168.1.10]). Protocols 773775 are deliberately unrouted (deprioritized; they'd need per-connection translation in gw-770 first).

Build / deploy

go build ./... && go test ./...
kubectl --kubeconfig ~/.kube/tachyne.yaml -n tachyne apply -f deploy/

Forgejo CI builds + pushes the image on every push to main (same conventions as the other tachyne repos: REGISTRY_TOKEN org secret, dind via the job network's default gateway).