Repository navigation
Releases
Releases · topcheer/etunnel
v1.6.2
v1.6.1
v1.4.0 — multi-instance cluster layer
v1.4.0 — 2026-11-10
Multi-instance cluster layer. One binary, three modes; single-node
deployments keep byte-identical behavior with zero config changes.
Server (etunneld)
- Cluster modes —
ETUNNEL_CLUSTER=single(default) |mesh|sticky.mesh: memberlist gossip ownership + cross-peer forwarding; works
behind any L4 load balancer (round-robin fine).sticky: Redis routing table (et:route:<sub>, 15s TTL lease, 5s
heartbeat) for L7 load balancers.
- Postgres account store —
ETUNNEL_PG_DSN; in-memory hot path with
write-through + 5s poll; auto-migrated schema. Without it: JSON store
as before. - Redis global counters —
ETUNNEL_REDIS_URL; exact global per-IP /
per-account limits. Without it: per-instance limits as before. - Graceful drain —
/healthzflips 503 on SIGTERM, sessions drain,
SDKs re-land on any peer with the same URL (resume tokens verify via
sharedSESSION_SECRET). - Fix: brand-asset file server was claiming the global
/assets/
subtree — a tunneled WebUI's own/assets/*.js|cssreturned Go's
default 404 while the homepage proxied fine. Now host-scoped to the
base domain only.
Deployment artifacts
- Docker image (distroless, ~17MB) +
deploy/docker-compose.yml(3-node
mesh + PG + Redis, verified end-to-end). - Helm chart
deploy/helm/etunnel(StatefulSet + headless DNS, verified
on k3s: 3-pod mesh,K3S-CLUSTER-OKx3). - Bare-metal systemd template
deploy/systemd/etunneld-cluster@.service. - Full guide with mermaid diagrams:
deploy/CLUSTER.md.
CI
- Every build runs the live PG/Redis cluster-store tests against service
containers (postgres 16 + redis 7) and fails on SKIP, so store
coverage can never silently regress.
SDKs
- Go: reconnect-policy unit tests (grow/jitter/isPermanent).
- No API changes — all 20 SDKs at 1.4.0.
Upgrade notes
- Single-instance users: drop-in binary replacement; no new env vars
required. - To enable the cluster layer see
deploy/CLUSTER.md— the only required
secret in any multi-instance mode isSESSION_SECRET.
v1.3.1 — themed 502 everywhere
All 19 SDKs (plus the Go SDK and the server) now serve the same branded 502 page when the tunnel is up but the local app is not: real dial error in a panel, pulsing auto-retry hint, site palette. CLI reconnect prints a prominent green 'reconnected / same URL' banner.
v1.3.0 — reconnect, resume, and the whole commercial stack
Highlights
- Auto-reconnect for all 20 SDKs + the Go CLI — dropped connections (including a server restart) re-dial with exponential backoff (500ms→30s, ±20% jitter), and the subdomain is reclaimed via a self-signed resumeToken (HMAC, 30min TTL), so shared links keep working.
- Billing: subscriptions expire automatically after 30 days; lapsed paid accounts keep a durable EverPaid marker so they are never garbage-collected.
- User portal: OAuth login (Google/GitLab/GitHub/Apple), account page (key reset, cancel, custom subdomains, close), subscription expiry display.
- Payments: PayPal (live), NOWPayments crypto checkout with verified IPN.
- Telegram admin bot: tap-menu commands + payment notifications.
- Legal: /terms and /privacy pages, linked from every footer.
- Site: unified design system across landing/pricing/login/me, mobile-responsive, working favicon.
- Reliability: stream-stall reset instead of head-of-line blocking, stream id lifecycle on both sides, per-account tunnel caps, register hardening, XFF edge authority, config preflight.
v1.2.0 — default server t.etun.uk
Domain migration: all 20 SDKs default to wss://t.etun.uk/tunnel (legacy t.ggcode.uk aliased for one week). Clojure artifact now dev.ggcode:etunnel-clj on Clojars. Adds payments (Stripe/PayPal), OAuth login (Google/GitLab/Apple), user portal /me, Telegram admin bot, and compile-time default-server injection for C/C++/Rust/Dart.