Easy Proxies: sing-box Proxy Pool Management and Failover
A proxy node pool management tool based on sing-box, supporting multiple protocols, automatic failover and load balancing. 基于 sing-box 的代理节点池管理工具,支持多协议、多节点自动故障转移和负载均衡。
At a glance
- What is it?
- Easy Proxies gives operators a local HTTP or SOCKS5 endpoint over multiple sing-box proxy nodes, with health checks, scheduling, retry, session routing, and subscription refresh. Docker is the documented primary deployment, while source builds require Go 1.26.9 or newer.
- Who is it for?
- Easy Proxies fits operators who need one authenticated local proxy entry across several upstream nodes and require health checks, scheduling, or subscription management. It is a poor fit for a simple single-node proxy or for organizations that cannot establish suitable licensing terms.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Easy Proxies Pool Scheduling and Failure Recovery
Pool scheduling has four documented choices: `sequential`, `random`, `balance`, and `latency`. Sequential scheduling performs round-robin selection, random chooses a node, balance uses the fewest active connections, and latency selects the node with the lowest measured latency. The configuration also sets `failure_threshold`, `blacklist_duration`, retry behavior, and separate cooldowns for transient failures and HTTP 429 responses.
The README distinguishes transient failures such as timeouts, connection resets, and 503 responses from rate-limit responses. Their cooldown values can be configured independently. This is useful when a node is unavailable for a short period but should not be treated like a node that is rate limited for a longer interval. The example sets both cooldowns to `60s`, while the documentation also suggests that a rate-limit cooldown such as `2h` can avoid using a node for longer.
Automatic failover retries a request when dialing the selected node fails. `retry_enabled` controls this behavior, and `retry_attempts` limits the total number of dial attempts. The WebUI and management API can probe nodes, change blacklist state, and release nodes manually. These mechanisms reduce the effect of an individual unhealthy node, but they do not guarantee that a request will succeed. A retry consumes another attempt, and a failed attempt can still occur if every available node has the same problem.
Session routing adds a second scheduling decision. On the main HTTP or SOCKS5 listener, `username.sessionID` keeps a named session on the same upstream node, while a bare username continues normal pool scheduling. If the fixed node fails, the README states that failover can move the session to another node. This is useful for services that need stable identity across connections, although it means that the selected upstream is not necessarily fixed for the entire session.
Easy Proxies Container Installation and First Local Use
The following commands prepare the example configuration and node file. The README identifies `config.example.yaml` as documentation rather than a working node source, so the example proxy entry must be replaced before use.
cp config.example.yaml config.yaml
touch nodes.txtFor the documented Docker workflow, put the prepared configuration at `data/config.yaml`, or let the container generate its configuration on first run. Then create the mounted directories and start the published image:
mkdir -p data logs
docker run --user $(id -u):$(id -g) \
-v $(pwd)/data:/etc/easy_proxies \
-v $(pwd)/logs:/app/logs \
--network host \
ghcr.io/jasonwong1991/easy_proxies:latestThe Compose file starts the same service definition. After startup, open `http://localhost:9091` in a browser. The minimal configuration uses port `2323` for the local proxy listener. The reader should use the WebUI to confirm that configured nodes appear and that the pool has a usable healthy entry before sending production traffic through it.
The README warns about a specific bind-mount mistake. If Docker creates a directory where the host expects a file, the container may see a directory instead of `nodes.txt`. The documented repair is:
rm -rf ./data/nodes.txt && touch ./data/nodes.txtThis is not a general networking fix. It applies to the documented case where a host file mount did not exist before Docker started. The Compose alternative is:
docker compose up -dThe Compose file uses host networking by default. Its comments also describe manual port mapping for the pool port, management port, and multi-port range.
Easy Proxies Source Builds and Optional Feature Tags
Source execution uses the Go module in `go.mod`, which declares `go 1.26.9`. The repository documentation says to use Go 1.26.9 or newer and pins the Docker builder to the same version. The basic command passes the configuration file to `cmd/easy_proxies`:
go run ./cmd/easy_proxies --config config.yamlA plain source build omits optional sing-box features, including Clash API traffic counters. The WebUI remains available, but real-time traffic charts require `with_clash_api`. The README gives this command for the same feature tags used by the Docker image:
go run -tags "with_utls with_quic with_grpc with_wireguard with_gvisor with_clash_api" \
./cmd/easy_proxies --config config.yamlThis difference is operationally relevant. A source operator may have a working dashboard while missing traffic statistics that exist in the container build. The tags also control optional protocol and runtime support, so the build command should match the intended deployment rather than being chosen only because it is shorter.
A minimal configuration selects pool mode, listens on `0.0.0.0:2323`, enables management on `0.0.0.0:9091`, and reads `nodes.txt`:
mode: pool
listener:
address: 0.0.0.0
port: 2323
username: user
password: pass
management:
enabled: true
listen: 0.0.0.0:9091
password: ""
nodes_file: nodes.txtThe example credentials are placeholders. Session routing requires a non-empty listener username, and the README recommends a strong, non-empty password. The management password field is separate from the listener credentials, so an operator should decide whether both surfaces need access restrictions.
The Docker image builds for Linux with `CGO_ENABLED=0` and includes `ca-certificates` in the Debian Bookworm slim runtime image. The Dockerfile exposes `2323`, `9091`, and `24000-24200`, while the supplied Compose file uses host networking. Those details matter when a deployment requires explicit port publication or a different runtime platform.
Easy Proxies Runtime Modes and Stable Node Ports
Easy Proxies supports `pool`, `multi-port`, and `hybrid` runtime modes. Pool mode exposes one local entry for all healthy nodes. Multi-port mode gives each node a separate local port, which is useful when a client needs to address a particular upstream. Hybrid mode exposes both forms and shares node status between them.
In multi-port and hybrid mode, each node keeps the same local port across subscription refreshes and restarts. The state is persisted in `node_ports.json`. The Compose comments describe automatic reassignment when a port conflict occurs, moving to the next available port. That behavior is convenient in a changing container environment, but it means an external client that hard-codes a multi-port address should verify the mapping after a restart or conflict.
The README documents GeoIP region routing. Nodes can be classified by country, and traffic can be directed through a specific region through a dedicated HTTP proxy endpoint. This is a separate routing policy from ordinary pool selection, so operators should avoid confusing region selection with session routing. A named session stays associated with a node until it expires or fails, while region routing selects according to the node classification.
Multiple node sources are supported: inline configuration, `nodes.txt`, and subscription URLs. Subscription formats include Base64, plain text, and Clash YAML. This flexibility also creates a configuration decision. Inline nodes are explicit, file-backed nodes are easy to inspect, and subscriptions require attention to refresh and content changes. The README does not document a complete validation report for every subscription parser, so operators should confirm that the imported nodes appear as intended before relying on them.
Subscriptions, DNS, Logs, and the Easy Proxies WebUI
Subscription URLs are periodically fetched and reloaded without restarting the service. Hot reload reduces manual node replacement, but an upstream subscription change can alter the effective pool while the process continues running. Operators need to know which URLs are configured and should compare node status after a refresh. The README does not specify every refresh failure or malformed-content behavior, so a failed or incomplete refresh should not be assumed to preserve the previous pool without verification.
DNS is configurable with fallback servers and IPv4 or IPv6 strategy control. The example uses `223.5.5.5`, port `53`, and `prefer_ipv4`. This setting affects name resolution for upstream connections and should be reviewed alongside the network environment hosting Easy Proxies. A resolver that works locally but cannot reach the selected upstream network will affect dialing even when the node itself is healthy.
The WebUI covers real-time node status, traffic charts, diagnostics, a log console, and common runtime and subscription settings. The REST management API supports node CRUD, probing, blacklisting, subscription management, and configuration reload. These controls are valuable because node pool state changes over time, but they also make the management listener an important operational endpoint. The README shows `management.enabled` and a management password setting. It does not document a complete route-by-route authentication policy, so operators should restrict network access and review the configured credential behavior rather than assume that every management route has the same protection.
Log rotation is size based and supports configurable backup count, age, and compression. The Compose deployment mounts `./logs:/app/logs`, making persistence and retention visible to the operator. If file logging is enabled through the WebUI, the mounted log directory is therefore part of the production filesystem layout, not merely a diagnostic convenience.
Easy Proxies Upgrades, Licensing, and Direct sing-box Alternative
The repository is not archived, and its last push was on 2026-10-11. Recent releases include v3.2.0 on 2026-10-11, v3.1.2 on 2026-10-08, and v3.1.1 on 2026-09-19. Their recorded changes concern named sessions and reliability, Clash gRPC service-name preservation, and cooldowns being released incorrectly. Recent commit activity does not eliminate upgrade cost, but it shows that the project has current repository activity rather than an old recorded push.
The v3.2.0 instructions say to back up the mounted configuration directory and retain `node_ports.json`. To pin that release, the Compose image can be set as follows:
services:
easy_proxies:
image: ghcr.io/jasonwong1991/easy_proxies:3.2.0After the publication workflow finishes, pull and recreate the service:
docker compose pull easy_proxies
docker compose up -d --force-recreate easy_proxiesDirectory mounts allow atomic configuration replacement. Individual-file bind mounts use an in-place fallback that the README says lacks the same crash and power-loss atomicity guarantees. Named sessions are in memory and are cleared by recreation. Per-node ports survive when their persisted state is retained.
No license identifier is declared in the repository metadata presented for this project. That is not enough to establish redistribution or modification rights. Anyone embedding Easy Proxies in a product or distributed deployment needs to confirm the applicable terms rather than infer them from the public GitHub or container URL.
A direct sing-box configuration is the main alternative. It is simpler for a fixed node, a small fixed outbound set, or environments that do not need a health-managed local pool, dashboard, subscription refresh, or named sessions. Easy Proxies adds scheduling and operational controls around sing-box, but it also introduces cooldowns, persistent port assignments, subscription state, and a management surface. Choose Easy Proxies when that control layer solves a real node-management problem; choose direct sing-box configuration when it would merely add moving parts.
Editorial conclusion
Easy Proxies fits operators who need one authenticated local proxy entry across several upstream nodes and require health checks, scheduling, or subscription management. It is a poor fit for a simple single-node proxy or for organizations that cannot establish suitable licensing terms. Before adoption, verify the node source and protocol, the selected runtime mode, persistent storage for `node_ports.json`, and whether the source build needs the optional production feature tags.
Frequently asked questions
How do I install Easy Proxies with Docker?
Copy `config.example.yaml`, create `nodes.txt`, and start `ghcr.io/jasonwong1991/easy_proxies:latest` with the documented directory and log mounts. The WebUI is available at `http://localhost:9091`.
What Go version and build tags does Easy Proxies require?
The repository documentation requires Go 1.26.9 or newer. The production source command includes `with_utls with_quic with_grpc with_wireguard with_gvisor with_clash_api`; a plain build omits optional features such as Clash API traffic counters.
Does Easy Proxies support load balancing and automatic failover?
Yes. Pool scheduling can be `sequential`, `random`, `balance`, or `latency`. When enabled, `retry_enabled` and `retry_attempts` allow dial failures to be retried against other healthy nodes.
How does session routing work in Easy Proxies?
On the main pool listener, `username.sessionID` keeps a named session on one upstream node, with failover when that node fails. A bare username continues to use normal pool scheduling, and session bindings expire after the configured idle lifetime.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jasonwong1991-easy-proxies)Was this useful?