Local agent for AS2Expert Relays — receive webhooks on a machine that has no public IP (home connection behind CGNAT, office NAT, laptop, Raspberry Pi…).
The agent opens an outbound TLS WebSocket to the Relays gateway, authenticates with your endpoint's agent key, and forwards every webhook to a URL on your machine or LAN. It reports the real HTTP result back, so the delivery log in the dashboard is honest. While the agent is offline, webhooks wait in the queue and are delivered when it reconnects. Nothing is lost.
- One static binary per OS: Linux (x86_64, aarch64), macOS (universal), Windows (x86_64). Pure-Rust TLS, no OpenSSL, no runtime dependencies.
- No inbound ports, no port forwarding, no dynamic DNS.
- Every delivery carries
X-Relay-Signature(HMAC-SHA256) so your app can verify it came from Relays.
Linux / macOS (downloads the latest release, verifies the checksum, installs
to /usr/local/bin; set INSTALL_DIR to change):
curl -fsSL https://raw.githubusercontent.com/as2expert/relay-agent/main/install.sh | shWindows (PowerShell): download relay-agent-windows-x86_64.zip from the
latest release,
unzip, and put relay-agent.exe somewhere on your PATH:
Invoke-WebRequest https://github.com/as2expert/relay-agent/releases/latest/download/relay-agent-windows-x86_64.zip -OutFile relay-agent.zip
Expand-Archive relay-agent.zip -DestinationPath "C:\Program Files\relay-agent" -Force
& "C:\Program Files\relay-agent\relay-agent.exe" --versionManual: grab the archive for your platform from the
releases page and
check it against SHA256SUMS.
From source (Rust 1.85+): cargo install --git https://github.com/as2expert/relay-agent
- In the dashboard, open your endpoint → Agent and copy the agent key
(
rak_…). Add a destination of type agent in the Destinations tab. - Run the agent pointing at the local URL that should receive the webhooks:
relay-agent --key rak_… --forward http://localhost:3000/hooksINFO relay-agent starting version=0.1.0 gateway=wss://relays.as2expert.com/agent forward=http://localhost:3000/hooks
INFO connected to gateway
INFO forwarded locally delivery_id=… method=POST http_status=200 latency_ms=12
Check the setup without leaving the agent running:
relay-agent --key rak_… --forward http://localhost:3000/hooks --check
ok: authenticated with the gateway (wss://relays.as2expert.com/agent)| Flag | Env | Default | Meaning |
|---|---|---|---|
--key |
RELAY_AGENT_KEY |
— | Agent key of the endpoint (rak_…). Rotate it in the dashboard if it leaks. |
--forward |
RELAY_FORWARD_URL |
— | Local URL that receives the webhooks. Method, headers and raw body are preserved. |
--gateway |
RELAY_GATEWAY_URL |
wss://relays.as2expert.com/agent |
Gateway URL (only change for self-hosted relays). |
--timeout |
— | 30 |
Seconds to wait for the local target. |
--insecure-local-tls |
— | off | Accept self-signed certificates on the local target only. |
--json-logs |
— | off | JSON-lines logs. RUST_LOG controls verbosity. |
--check |
— | — | Connect, authenticate, exit 0 on success. |
The public URL token (rt_…) is not an agent key and is rejected, both
locally and by the gateway. Only the agent key grants access to your webhooks.
Examples in deploy/:
- Linux (systemd):
deploy/relay-agent.service—sudo cp deploy/relay-agent.service /etc/systemd/system/, put the key in/etc/relay-agent.env,sudo systemctl enable --now relay-agent. - macOS (launchd):
deploy/com.as2expert.relay-agent.plist— copy to~/Library/LaunchAgents/andlaunchctl loadit. - Windows:
deploy/windows.md— Task Scheduler at logon, or a proper service with NSSM /sc.exe.
provider ──HTTPS──▶ relays.as2expert.com ──queue──▶ gateway ══WSS══▶ relay-agent ──HTTP──▶ your app
(outbound only)
- The agent authenticates with the agent key in the first frame; the gateway
closes the connection with a reason if it is wrong (
relay-agent --checkshows it). - Each webhook arrives as a JSON frame with the original method, headers, raw
body (base64) and our
x-relay-signature; the agent replays it to--forwardand answers with the local status code, latency and a response excerpt. - If the connection drops while a webhook is in flight, the platform re-queues
it. Make your handler idempotent (use
X-Relay-Signature/ the event id). - Reconnects with exponential backoff (1 s → 30 s). Keepalive pings every 25 s.
The frame format is documented in docs/PROTOCOL.md.
X-Relay-Signature: t=<unix_ts>,v1=<hex HMAC_SHA256(signing_secret, "{t}.{raw_body}")>.
The signing secret is in the dashboard. Reject timestamps older than ~5 minutes.
Snippets for Python, Node and shell are in the
Relays documentation.
cargo build --release # binary in target/release/relay-agent
cargo test && cargo clippy --all-targets -- -D warningsReleases are built by GitHub Actions on tag push (v*) for
linux-x86_64 (musl, static), linux-aarch64 (musl), macos-universal and
windows-x86_64, with a SHA256SUMS file.
- Product documentation: https://relays.as2expert.com/docs#agent
- Wire protocol:
docs/PROTOCOL.md - Issues and feature requests: https://github.com/as2expert/relay-agent/issues
Apache-2.0. © AS2Expert.