Repository navigation
Releases: minpeter/global-egress
Release list
github.com/minpeter/global-egress@0.1.0
Distinguish proxy acquisition timeouts (7a62229)
Return HTTP 504 when proxy acquisition ends on a context deadline. Pool
exhaustion and unknown failures remain HTTP 502, so clients can rotate stalled
exits without broadening retries for ordinary upstream failures.
Pull request & contributors
Keep the textfile collector parseable and stoppable (d023431)
The collector no longer redeclares a /v1/stats field that /v1/metrics
already exports. A second # TYPE line made node_exporter's textfile
collector reject the whole file, so every Global Egress Proxy panel showed
No data. The daemon now exits on SIGTERM and removes its temporary output,
so rc-service global-egress-metrics restart replaces the running process.
Pull request & contributors
Require Go 1.26.9 (8ba23bb)
Raise the minimum Go version from 1.25.13 to 1.26.9 and update
golang.org/x/net to v0.60.0. govulncheck found nine reachable
standard-library vulnerabilities in the HTTP/2, CONNECT, TLS and MIME header
paths that the proxy uses, and Go 1.25 has no fixed release. Building with Go
1.25 is no longer supported. The container image is built with Go 1.26.9.
Pull request & contributors
github.com/minpeter/global-egress@0.0.6
Keep Docker configuration private and readable (4d6aa2d)
Include config.toml in the uid 65532 ownership and mode 0600 handoff so the nonroot container can read configuration created under the restrictive umask.
Pull request & contributors
github.com/minpeter/global-egress@0.0.5
Create Docker secrets privately from the first write (fb6f0ec)
Set a restrictive umask before creating Docker secrets and create the provider catalog at mode 0700 before placing key material in it, closing the exposure window before the final ownership and permission hardening commands run.
Pull request & contributors
github.com/minpeter/global-egress@0.0.4
Stop recommending world-readable Docker secrets (9c62196)
Replace the chmod 644 instruction in the Docker deploy guide with a least-privilege flow: uid 65532 ownership with mode 0600 on proxy-password and control-token, mode 0700 on the catalog directory, and 0600 on provider key files, plus an explanation of the host-ownership tradeoff.
Pull request & contributors
Clamp timeout-phase metrics to the closed set (81347b9)
TimeoutPhase is a string alias, so a caller can pass any value into
ObserveRequest. The scrape still has to emit only acquire, upstream, or
unknown: a free-form phase label would grow with whoever typed it.
The metrics boundary now switches on the closed set and records anything else
as unknown. Empty and omitted phases already landed there; out-of-set values
now do too. No new label was added.
Pull request & contributors
github.com/minpeter/global-egress@0.0.3
Export the collector control token path (64ba7eb)
Pass CONTROL_TOKEN_FILE from the OpenRC confd into the metrics collector process so authenticated control scraping works after restart.
Pull request & contributors
github.com/minpeter/global-egress@0.0.2
Fail closed for remote control mutations (c91e67c)
Require bearer authentication for mutating control API requests received from
non-loopback clients, while preserving the existing read-only endpoint policy.
Pull request & contributors
Container health check without a shell (72afd9b)
Add a global-egress healthcheck subcommand that probes the control API's
/healthz and reports the verdict as its exit status, plus a default Docker
HEALTHCHECK and a Compose healthcheck block that use it.
The image is distroless, so there is no curl or wget to probe from a shell
and the binary probes itself. The probe is bounded by -timeout (2s default) so
Docker never has to kill it, and reads a bearer token from -token-file when the
control API requires one, keeping the secret out of the image, the Compose file,
and docker inspect.
The image keeps a tokenless default probe. The Compose service passes
-token-file and mounts ./control-token read-only, because the container config
example sets access.control_token_file and a configured token is checked on
every control request including GET /healthz; an unauthenticated probe would
report a healthy container as unhealthy. The Compose command and the config
example are pinned to each other by tests so they cannot drift.
The control API now always permits loopback clients through
access.allowed_clients: the example ACL names only remote CIDRs, and without
the exemption the in-container probe would be refused with 403 before token
auth runs. Bearer-token auth still applies to loopback requests.
Pull request & contributors
Require Go 1.25.13 (945347b)
Raise the minimum Go toolchain to 1.25.13, which includes fixes for the reachable
standard-library and golang.org/x/net vulnerabilities reported by govulncheck.
Pull request & contributors
Date every exit-IP measurement, and separate slot count from measured IPs (b0d789e)
The README, docs/operations.md and docs/capacity.md each quoted a different
"definitive" unique-IP total (456, 524, 529) for the same 532-slot bundle, with no
date, mode or device attached. They now share one measurement log in
docs/capacity.md, where every row carries its date, mode, bundle and run
parameters, and the surviving claim is "one measured address per reachable exit,
zero duplicates" rather than any single total.
Documents also stop standing in for the running service: slot count is a catalogue
property, while slots_with_known_ip and unique_public_ips in /v1/stats (plus
/v1/ips) are the current measured state that uniq= batches draw on.
Pull request & contributors
Split request timeouts by phase, and expose entry rotation health (59cae57)
global_egress_request_results_total{result="timeout"} collapsed two unrelated
faults into one number. A timeout before the upstream was ready means pool
capacity or handshake latency; a timeout after it was established means the exit
or the destination. Both arrive as context.DeadlineExceeded, so the single
result label could not tell an operator which half to look at.
/v1/metrics now also carries global_egress_request_timeouts_total, labelled
with a closed phase enum (acquire, upstream, unknown) alongside the
existing bounded country and entry dimensions. The SOCKS5 and HTTP listeners
report the phase from the classifier that already decided the result, so no new
error handling was introduced.
Entries were the other blind spot: they are the scarce resource — each one costs
a key association — but nothing on the scrape said how many were up, spare, or
benched. global_egress_entry_state{state="open"|"idle"|"disabled"} reports the
rotation breakdown, always emitting all three series so a state never vanishes
from a scrape, and global_egress_entry_failures_total{reason="open"|"dial"}
separates an entry that will not come up from one whose tunnel is up but no
longer carrying traffic.
Every new label is a fixed enum or an existing bounded dimension. No target,
address, session or entry-identity label was added, and slot ranking is
unchanged.
Pull request & contributors
Authenticate the metrics collector (28eb19f)
Allow the node-exporter collector to read a protected control token file and authenticate every read-only control API request without exposing the bearer in argv, logs, or Prometheus output.
Pull request & contributors
github.com/minpeter/global-egress@0.0.1
Container packaging and Tegami-managed releases (3298320)
Add a distroless Docker image and Compose layout for unprivileged deploys.
Drive versions with Tegami (.tegami entries → Version Packages PR → vX.Y.Z
tag and GitHub Release), then attach static binaries and push multi-arch images
to GHCR as CI side artifacts.
First public tag is v0.0.1 (no prior tags → baseline 0.0.0, patch bump).