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), add sticky: false to each server.

Next