EQProxy Load balancer and reverse proxy in Rust

Installation

EQProxy is distributed as a static binary for Linux and macOS and as a multi-architecture image in two registries. This page covers both paths, the binary's real requirements and the first start with a minimal TOML, including prior validation through the CLI.

Binary and build

Each release publishes four precompiled binaries — eqproxy-darwin-arm64, eqproxy-darwin-amd64, eqproxy-linux-arm64 and eqproxy-linux-amd64 —, the source code as eqproxy-0.9.1-src.tar.gz and a single SHA256SUMS.txt that covers the five artifacts.

The Linux binaries are statically linked against musl (static-pie linked on amd64, statically linked on arm64): they need no libc, no glibc version and no packages, and they start in FROM scratch. The macOS ones are not static. The production platform declared in the project is Linux x86_64 (glibc), per ADR-0001.

# Verification after download
shasum -a 256 -c SHA256SUMS.txt --ignore-missing     # macOS
sha256sum -c --ignore-missing SHA256SUMS.txt          # Linux
chmod +x eqproxy-linux-amd64
./eqproxy-linux-amd64 --version

From source, with the toolchain pinned in rust-toolchain.toml (1.99.1, the same one that builds the release artifacts):

cargo build --release --locked
./target/release/eqproxy --version

Docker images

The same images are published on GitHub Container Registry and on Docker Hub, with identical digests, for linux/amd64 and linux/arm64:

The references are ghcr.io/exyonq/eqproxy:0.9.1 and exyonq/eqproxy:0.9.1, plus the moving :latest tag, which points to the same image as the latest release.

The runtime base is Wolfi (cgr.dev/chainguard/wolfi-base, pinned by digest), with the binary in /opt/eqproxy, the unprivileged user 65532:65532 and the state directory /var/lib/eqproxy exported as EQPROXY_STATE_DIR. The image exposes port 8080 as a convention; the process listens wherever the configuration says.

docker pull ghcr.io/exyonq/eqproxy:0.9.1
docker run --rm ghcr.io/exyonq/eqproxy:0.9.1 --version

The entrypoint is /opt/eqproxy: the arguments that follow the image name go to the CLI. With no arguments, it prints --help.

Requirements

First start

A minimal eqproxy.toml: one HTTP listener and one backend.

schema_version = 1

[listener.web]
listen = "0.0.0.0:8080"
mode = "http"
backend = "api"

[backend.api]
server = "127.0.0.1:9000"
./eqproxy-linux-amd64 run --config eqproxy.toml
# or, in a container:
docker run --name eqproxy -d -p 8080:8080 \
  -v "$PWD/eqproxy.toml:/etc/eqproxy/eqproxy.toml:ro" \
  ghcr.io/exyonq/eqproxy:0.9.1 run --config /etc/eqproxy/eqproxy.toml

On start, the process writes INFO listener web listening on 0.0.0.0:8080 to stderr and, every --metrics-interval (30s by default), a METRICS … line with the counter snapshot.

CLI validation

config validate binds nothing and opens no ports: it parses, validates and resolves the whole document (certificates, addresses, balancing) before saying yes.

./eqproxy-linux-amd64 config validate --config eqproxy.toml
# config OK: 1 listener(s), 1 backend(s) in eqproxy.toml

Errors go to stderr with file, line, field, cause and an example fix; the exit status is 1. The rest of the CLI:

CommandWhat it does
config schema --output eqproxy.schema.jsonWrites the JSON Schema generated from the same types the parser accepts
config explain --config … [--listener …] [--method …] [--host …] [--path …]Simulates a routing decision with no effects: rules, backend, balancer and what each timeout does when it fires
config diff base.toml candidata.tomlCompares two configurations; report on stdout
config plan --config …Shows the change plan without applying it
config apply --config …Validates, resolves, makes a backup and changes the local versioned state (does not touch any running process)
config rollbackRestores the most recent backup into current
config import --input … --output … [--report …]Converts nginx, HAProxy, ingress-nginx or Envoy; see Converters
doctor [--config …]Checks the configuration, the bind of each listener, TLS and the FD budget; ends with doctor: PASS or doctor: FAIL

config apply and config rollback write to ./.eqproxy unless EQPROXY_STATE_DIR points to another directory; the image already sets it to /var/lib/eqproxy.