Configuration
p2proxy reads a YAML config file. By default it looks for Config.yaml in the working directory; override the path with --config (or the P2PROXY_CONFIG env var). The bundled example in the repo is a good starting point; this page covers every field.
Top-level keys
| Key | Type | Default | Description |
|---|---|---|---|
bitping_api_key |
string | — | Required. Authenticates the daemon to the Bitping network. Can also be set via the BITPING_API_KEY env var, which overrides the file value. |
servers |
list | — | One or more proxy listeners (below). |
listen_addrs |
list | 0.0.0.0:0, [::]:0 |
libp2p listen addresses, each a host:port. TCP and QUIC are bound on every entry. Port 0 means “any free port”. Forwarding a fixed port isn’t required, but improves direct (non-relayed) peer connectivity. Takes precedence over port. |
port |
u16 | — | Shorthand that fixes the libp2p port on the default listen addresses (e.g. 45445). Ignored when listen_addrs is set explicitly. |
log_level |
string | info |
Default log level when RUST_LOG is unset — trace, debug, info, warn, error, or a full tracing directive. RUST_LOG overrides it. |
metrics_port |
u16 | 9091 |
Port for the Prometheus metrics endpoint, bound on 0.0.0.0. |
bootstrap_address |
string | /dnsaddr/boot2.bitping.com |
libp2p multiaddr used to bootstrap into the Bitping network. |
grpc_url |
string | https://grpc.bitping.com |
Bitping gRPC endpoint the daemon authenticates against. |
keypair_path |
string | node_keypair.bin |
Path to the persisted libp2p keypair file. |
Per-server keys
Each entry under servers defines a SOCKS5 listener and its peer selection rules.
| Key | Type | Default | Description |
|---|---|---|---|
protocol |
enum | — | Socks5. Currently the only supported protocol. |
port |
u16 | — | Local TCP port to listen on for incoming SOCKS5 connections. |
min_bandwidth |
string | 50Mbps |
Minimum advertised bandwidth a peer must have. Format: <N>{bps,Kbps,Mbps,Gbps}. |
country |
string | — | Optional country filter. Accepts an alpha-2 code (AU), an alpha-3 code (AUS), or a country name; values are normalized to alpha-2. Omit to allow any country. |
city |
string | — | Optional city filter. A bare city name (Amsterdam) or the City; Region; Country form. |
isp |
string | — | Optional ISP filter — a regex matched against the node’s ISP name (e.g. Comcast, or Comcast|Xfinity). |
asn |
number | — | Optional Autonomous System Number (ASN) filter (e.g. 1136). Pins traffic to nodes on a specific network. |
proxy |
enum | allow |
Proxy/VPN-node policy: allow (no constraint), deny (exclude them), or require (only proxy nodes). |
mobile |
enum | allow |
Mobile/cellular policy: allow, deny (exclude cellular), or require (cellular only). |
hosting |
enum | allow |
Hosting/datacenter policy: allow, deny (residential only — no datacenter IPs), or require (datacenter only). |
destination_peers |
list | — | Optional ordered list of peer IDs (or full multiaddrs) to pin traffic to. The first entry is the primary; later entries are failovers. See Pinning & sticky peers. |
fallback_to_discovery |
bool | false |
When all pinned peers are offline: false (default) keeps retrying the list and surfaces an error — your egress IP never silently changes. true falls back to country/min_bandwidth discovery. Only relevant when destination_peers is set. |
sticky |
bool | true |
Remember the discovered exit peer in sticky_peers.json and reconnect to it on restart for a stable egress IP. Set false to get a fresh peer on every restart. Only applies when destination_peers is not set. |
sticky_reconnect |
enum | with-backoff |
How to handle reconnecting to a sticky/pinned peer. with-backoff retries with exponential backoff; fail-fast gives up immediately and re-discovers. |
pool |
object | — | Optional per-server tuning (below). |
Per-server pool keys
p2proxy is not a connection pool — every SOCKS5 connection opens a fresh libp2p stream to the exit peer. These two knobs bound the in-flight streams per server.
| Key | Type | Default | Description |
|---|---|---|---|
max_total |
u32 | 30 |
Hard ceiling on concurrent streams to the exit peer. |
open_timeout_secs |
u64 | 20 |
Give up dialing a new stream after this long. |
Environment variables
| Variable | Description |
|---|---|
BITPING_API_KEY |
Your Bitping API key. Overrides bitping_api_key in Config.yaml. Required if not set in the file. |
P2PROXY_CONFIG |
Path to the config file. Defaults to Config.yaml in the working directory. Same as --config. |
NO_UI |
If true, disables the TUI (equivalent to --no-ui). Defaults to true in the official Docker image. |
RUST_LOG |
Standard Rust tracing filter (info, debug, module=trace, …). Overrides the log_level config key when set; when unset, logging falls back to log_level (default info). |
CLI flags
| Flag | Description |
|---|---|
--config, -c |
Path to the config file (defaults to Config.yaml). |
--no-ui |
Run headless, without the TUI. |
Recipes
Country-pinned listener
A single SOCKS5 listener that only routes through nodes in Australia, with high bandwidth required:
bitping_api_key: <your-key>
servers:
- protocol: Socks5
port: 1080
country: AU
min_bandwidth: 100Mbps
Multi-region setup
Three listeners on different local ports, each pinned to a region:
bitping_api_key: <your-key>
servers:
- protocol: Socks5
port: 1080
country: US
- protocol: Socks5
port: 1081
country: DE
- protocol: Socks5
port: 1082
country: JP
Point your client at localhost:1080 for US traffic, localhost:1081 for DE, etc.
Filtering by network and node type
Beyond country, target a specific network or node type. This routes only through residential nodes on Comcast’s US network:
servers:
- protocol: Socks5
port: 1080
country: US
asn: 7922 # Comcast (AS7922)
hosting: deny # residential only — never a datacenter IP
min_bandwidth: 25Mbps
proxy, mobile, and hosting each take allow (default — no constraint), deny (exclude that type), or require (only that type). isp is a regex, so isp: "Comcast|Xfinity" matches either; add city for metro-level targeting.
Bounding concurrent streams
Raise the per-server stream ceiling for bursty workloads, and give dials longer before they time out:
servers:
- protocol: Socks5
port: 1080
min_bandwidth: 100Mbps
pool:
max_total: 60
open_timeout_secs: 30
Pinned peer list with failover
Route through a preferred peer; fall back to a second if it’s offline:
servers:
- protocol: Socks5
port: 1080
destination_peers:
- 12D3KooWPrimaryPeerIdHere...
- 12D3KooWBackupPeerIdHere...
fallback_to_discovery: false # hard pin — error if both are offline
Entries are bare peer IDs (recommended) or full multiaddrs ending in /p2p/<id>. The hub resolves the current circuit address dynamically, so a bare peer ID stays reachable even when the peer moves between hubs.
Pinning & sticky peers
p2proxy has two complementary ways to keep a stable egress IP:
Ordered peer list (destination_peers) — explicit control. You provide one or more peer IDs in priority order. p2proxy always tries the primary (rank 0) first, moves to rank 1 on failure, and so on. Routes are re-resolved through the hub on every connect, so the peer stays reachable even after it re-homes to a different hub. If every listed peer is offline, p2proxy retries with backoff and surfaces an error (hard pin by default). Set fallback_to_discovery: true to silently fall back to the country/bandwidth filter instead.
Sticky peers (sticky: true, the default) — hands-free stability. For servers without destination_peers, p2proxy remembers the exit peer it chose during discovery and reconnects to the same one on restart. The remembered peer is stored in sticky_peers.json in the current working directory (same location as node_keypair.bin). One entry is kept per listen port.
The sticky entry carries a fingerprint of the server’s selection filters — country, city, isp, asn, the proxy/mobile/hosting policies, min_bandwidth, and the listen port. If you change any of them, the fingerprint no longer matches and p2proxy automatically discards the stale entry and discovers a fresh peer. Set sticky: false to opt out and get a new peer on every restart.
sticky_reconnect controls what happens when the remembered (or pinned) peer drops: with-backoff (the default) retries with exponential backoff, holding the egress IP steady through transient outages; fail-fast gives up immediately and lets discovery pick a replacement.
Default behaviour:
sticky: true. If you want a fresh exit peer on every restart (e.g. for IP rotation), addsticky: falseto each server.
Next
- Integrations — wire your client at the SOCKS5 listener.
- Operations — systemd, Docker, metrics.