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
- Architecture:
linux/amd64andlinux/arm64in image and binaries;darwin/amd64anddarwin/arm64only as a binary. - libc: none on Linux (static musl); on macOS the binary is not static.
- Privileges: none if high ports are listened on; below 1024 you need
--user 0or a mapping on the host. - Descriptors: about 2 FDs per proxied connection, plus listeners and the admin plane;
eqproxy doctorchecks the budget. - Files: the TOML and the certificates must be readable by uid 65532 in the image (
chmod 644is enough).
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:
| Command | What it does |
|---|---|
config schema --output eqproxy.schema.json | Writes 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.toml | Compares 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 rollback | Restores 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.