Skip to content

v1.6.0

Choose a tag to compare

@github-actions github-actions released this 06 May 03:35
· 38 commits to main since this release

Highlights

Stability under sustained load

The exit server now properly closes sessions on upstream EOF and keeps partial drains queued so trailing FIN frames always reach the client. Previously, ~270 zombie sessions could accumulate in production logs (active=290 sessions while goroutines=51), eventually starving the server and triggering Apps Script HTML error pages (the root cause of "non-batch payload" reports — issue #56). Closes #31, #44, #62.

Multi-deployment-single-account configs no longer overload Apps Script

Workers and idle long-poll slots now scale by Google account bucket, not endpoint count. Users with multiple deployments under one account previously got 3 × N workers slamming a single account, hitting the per-second concurrency cap and getting HTML error pages back instead of encrypted batches. Workers are now (workersPerEndpoint + idleSlotsPerBucket - 1) × bucketCount. Closes #56, refs #41 #73.

Label your script_keys with the account field — the label is now load-bearing, not just for stats.

New idle_slots_per_bucket knob

Opt up concurrent idle long-polls per account when your accounts can sustain it. Default 1 (safe), max 3. May increase download throughput on accounts with multiple deployments. Closes #14 (downstream tuning).

Adaptive uplink coalescing

Set coalesce_step_ms (default 0, off) to collapse bursts of small TX operations into a single Apps Script call. Trades a bit of latency (20–40 ms typical) for fewer UrlFetchApp invocations on interactive workloads. Closes #14.

Version negotiation + /healthz endpoint

Clients can now query the server's version and protocol on connect; ops can health-check the VPS without holding a tunnel key. Closes #86, #87.

Per-account script stats aggregation

The periodic [stats] line now reports actual UrlFetchApp counts per Google account, so you can see which account is doing the work. Closes #55, #81.

Docker integration

Server now ships with a Dockerfile and docker-compose.yml. Closes #88.

Frame compression

Zstandard (preferred) and DEFLATE compression for batch bodies, with transparent fallback for older peers.

Performance & polish

  • HTTP/2 transport tuning: 1 MiB MaxReadFrameSize, ReadIdleTimeout, PingTimeout (#58)
  • TCP_NODELAY + TCP_QUICKACK on SOCKS listener for snappier interactive traffic (#60)
  • Buffer pooling on hot paths to reduce GC pressure (#63)
  • Unpadded raw base64 saves ~1.5% protocol overhead (#64)
  • TLS 1.3 floor (#61)
  • Dynamic queue-age fairness (#67)
  • workersPerEndpoint bumped 3 → 4

Other changes

  • carrier worker count now scales with idle_slots_per_bucket so TX pool isn't drained when raising the RX cap
  • Stats: goroutines= and clients= added to the always-on [stats] line for leak detection without pprof
  • systemd: StartLimit* moved to [Unit] with modern field names
  • diagnose: lowercase error messages, JSON doGet pre-flight handling
  • SOCKS session logs gated behind debug_timing
  • README: clarified script_keys format, troubleshooting tips for "Exec format" and "non-batch payload", Termux chmod +x step
  • Issue forms added

Full Changelog: v1.5.0...v1.6.0

Upgrade Notes

Redeploy everything together: client, server, and the Apps Script (Code.gs).

The frame wire format remains backward-compatible (raw base64 decoder still accepts padded legacy format; compression is negotiated), but several v1.6.0 features need both ends to be on v1.6.0:

  • Version negotiation + /healthz (server-side)
  • Compression (both ends must agree)
  • Per-account stats aggregation (Code.gs reports invocation counts back to client)

apps_script/Code.gs has substantive changes (70+ lines across 3 commits since v1.5.0). Redeploy the Apps Script to pick up version negotiation, the RELAY_URL rename, and per-account stats. Mixing a v1.5 Apps Script deployment with a v1.6 client is supported but you'll miss the new features.

Spread your script_keys across multiple Google accounts when you can. Workers and idle long-polls now scale by distinct account labels:

Config v1.5.0 workers v1.6.0 workers
1 deployment / 1 account 3 4
3 deployments / 1 account (unlabeled or same label) 9 4
3 deployments / 3 accounts (each labeled) 9 12
6 deployments / 3 accounts 18 18
6 deployments / 6 accounts 18 24

If your script_keys are unlabeled, the carrier treats them as one bucket and logs a startup WARN advising you to label them. Add "account": "A", "B", etc. to each entry in script_keys — the label is now load-bearing, not cosmetic.

Single-account users: try idle_slots_per_bucket: 2 (or 3, which is the cap) if your account has 2+ deployments. May increase download throughput at the cost of more simultaneous executions per account. Don't set it above what your account empirically tolerates — going too high re-triggers issue #56 (HTML error pages instead of encrypted batches).