For AI agents: this page is the complete, self-contained spec to deploy a peer fleet in Go. Read the "Stable Identity" section before scaling - doing it wrong creates a new device on every reconnect and gets the account capped.
A drop-in Go peer that shares an internet connection's bandwidth and earns USDC. It speaks the complete Proxies.sx relay protocol - identical wire format to the Node, Windows, and Android SDKs:
relay_redirect)One file, one dependency (gorilla/websocket). Source:
reference-sdk.go + go.mod.
# 1. Get the two files into a folder
mkdir proxies-peer && cd proxies-peer
curl -O https://agents.proxies.sx/peer/reference-sdk.go
curl -O https://agents.proxies.sx/peer/go.mod
# 2. Run it (Go 1.21+). Get your psx_ API key at client.proxies.sx/account
go run reference-sdk.go -key=psx_YOUR_API_KEY -name=rig-001
# Expected:
# [REGISTERED] device=agent_... relay=wss://relay.proxies.sx sockets=4
# [CONNECTED] device=agent_...
# [ACK] relay confirmed connection
go build -o proxies-peer reference-sdk.go
./proxies-peer -key=psx_YOUR_API_KEY -name=rig-001
# Cross-compile (build once, ship everywhere):
GOOS=linux GOARCH=amd64 go build -o proxies-peer-linux reference-sdk.go
GOOS=linux GOARCH=arm64 go build -o proxies-peer-arm64 reference-sdk.go
Every option is a flag, and each flag also reads an environment variable (use whichever fits your orchestration). Env vars are ideal for fleets.
| Flag | Env | Default | Meaning |
|---|---|---|---|
-key | API_KEY | - | Required. Your psx_ API key (client.proxies.sx/account → API Keys) |
-name | AGENT_NAME | random | Set this per instance. See Stable Identity below. Same name + key = same device. |
-country | COUNTRY | US | ISO-2 hint (server verifies the real IP) |
-connections | WS_CONNECTIONS | 4 | Parallel relay sockets (1-8) |
-wallet | WALLET | - | Payout wallet (optional) |
-state | PEER_STATE_FILE | ~/.proxies-peer-state.json | Saved identity file. Persist this per instance. |
-relay | RELAY_URL | (auto) | Pin a relay; empty = nearest, server-chosen |
-verbose | VERBOSE=true | off | Log every tunnel open/close |
SHA-256(apiKey + ":" + name). If AGENT_NAME is random (the default) or your instance runs in an ephemeral container with no persistent state, every restart creates a brand-new device. A fleet that restarts will balloon into hundreds of thousands of ghost devices, none of which earn, and your account will hit the device cap.
Do both of these and your fleet stays clean forever:
-name=rig-001, rig-002, … Never randomize it. Same name across restarts → same device.-state / a Docker volume). It stores {deviceId, refreshToken} so a restart resumes the same identity even before the name hash is needed.Accounts scale to 200,000 devices - real fleets are welcome. The only limit that bites is an anti-flood guard on unproven devices: at most 20,000 that have never served traffic (and aren’t yet verified). The moment a device serves a byte or passes verification it stops counting against that guard, so a fleet that’s actually earning grows freely to the full 200k. A flood of random-named ghosts (which never serve) simply parks at 20,000 and goes no further. The rule is the same either way: give every device a stable, unique name so it reconnects as one device instead of spawning a ghost on each restart. Need more than 200k genuine nodes? Email agents@proxies.sx.
# Each instance gets a STABLE unique name + its own state dir.
# Run this on each machine that has its own real connection/IP.
API_KEY=psx_YOUR_KEY
for i in $(seq 1 8); do
NAME="node-$(hostname)-$i"
DIR="$HOME/.peer/$NAME"; mkdir -p "$DIR"
AGENT_NAME="$NAME" API_KEY="$API_KEY" PEER_STATE_FILE="$DIR/state.json" \
nohup ./proxies-peer > "$DIR/peer.log" 2>&1 &
done
Use this only when a box truly has multiple distinct uplinks (e.g. several USB modems). One uplink = one instance.
A templated unit runs N stable instances. %i is the instance name - it becomes the device name and the state path, so each instance is permanently one device.
# /etc/systemd/system/proxies-peer@.service
[Unit]
Description=Proxies.sx peer %i
After=network-online.target
Wants=network-online.target
[Service]
Environment=API_KEY=psx_YOUR_API_KEY
Environment=AGENT_NAME=%i
Environment=PEER_STATE_FILE=/var/lib/proxies-peer/%i.json
ExecStartPre=/bin/mkdir -p /var/lib/proxies-peer
ExecStart=/usr/local/bin/proxies-peer
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
# Enable a stable instance (repeat per distinct connection):
sudo systemctl enable --now proxies-peer@rig-001
sudo systemctl enable --now proxies-peer@rig-002
# Status / logs:
systemctl status proxies-peer@rig-001
journalctl -u proxies-peer@rig-001 -f
Restarts and reboots reuse the same device (name + state are fixed) - zero device churn.
AGENT_NAME, or every container restart spawns a new device.# Dockerfile
FROM golang:1.22-alpine AS build
WORKDIR /src
ADD https://agents.proxies.sx/peer/reference-sdk.go .
ADD https://agents.proxies.sx/peer/go.mod .
RUN go mod download && go build -o /proxies-peer reference-sdk.go
FROM alpine
COPY --from=build /proxies-peer /proxies-peer
ENV PEER_STATE_FILE=/data/state.json
ENTRYPOINT ["/proxies-peer"]
# Run ONE container per distinct connection, with a stable name + named volume:
docker run -d --restart always --name peer-rig-001 \
-e API_KEY=psx_YOUR_API_KEY \
-e AGENT_NAME=rig-001 \
-v peer-rig-001:/data \
proxies-peer
1. Register POST /v1/peer/agents/register {name, type:"custom", apiKey, sdkVersion}
-> { deviceId, token|jwt, refreshToken, relay, earningsPerGB }
deviceId = SHA-256(apiKey + ":" + name) (stable across restarts)
2. Connect wss to register.relay, JWT in Sec-WebSocket-Protocol as token.<jwt>
(NEVER in the URL). Opens WS_CONNECTIONS parallel sockets.
3. device_info announce {country, protocol:"binary-v1", supportsRelayRedirect:true}
4. Heartbeat every 30s
5. tunnel_connect open raw TCP to target host:port, stream bytes both ways.
HTTPS stays end-to-end - do NOT terminate TLS at the peer.
6. relay_redirect server can move you to a nearer relay; the pool reconnects there.
If you write your own client, the two mistakes that cause "intermittent auth" and "zero traffic": put the JWT in the Sec-WebSocket-Protocol header (not the URL), and on a 4001/4002 close refresh identity once for all sockets (do not relaunch the whole pool). The reference file documents both inline.
earningsPerGB field in the register response.Your node works if it shows online + verified at farmer.proxies.sx. The curl below is a customer-side tool: it needs a proxy password (client.proxies.sx/account) and a small traffic balance. A 407 means the curl's credentials are wrong, not that your node is broken.
curl -v -x "http://psx_YOURACCOUNT-peer-us-pin-device-DEVICEID:PROXY_PASSWORD@gw.proxies.sx:7000" \
https://api.ipify.org/?format=json
# In your node's -verbose log you should see: [TUNNEL_CONNECT] ... then [TCP_OPEN_OK] ...
| Go SDK source | reference-sdk.go + go.mod |
| Windows SDK | /peer/windows/ |
| Node.js SDK | reference-sdk.js |
| Android SDK | android-peer-sdk |
| Peer Network overview | agents.proxies.sx/peer/ |
| AI-agent skill file | /peer/skill.md |
| Dashboard | farmer.proxies.sx |
| Fleet help | agents@proxies.sx · @proxies_sx |