Single static binary
One Linux binary per node. No runtime deps, no daemon to keep alive, no companion control plane — drop it in and run.
p2pcp is a peer-to-peer file replication CLI. The more peers join, the faster the transfer goes — because every peer becomes a source. One static binary, zero companion services.
$ p2pcp -dst /data -peer-list peer1,peer2,peer3 -exit-complete
How it works
Every node pulls from one storage. Bandwidth divides as nodes pile on.
Every peer shares chunks. Throughput grows as the fleet grows.
Built to scale
p2pcp is designed to fan out terabyte-class source data across hundreds of peer nodes — throughput grows as the fleet grows, bounded by your network rather than the tool.
In production at NAVER
Reference deployment inside NAVER, with zstd compression enabled. Numbers vary with topology, chunk size, compressibility of the data, and storage characteristics.
Features
One Linux binary per node. No runtime deps, no daemon to keep alive, no companion control plane — drop it in and run.
Role set by flags: -src to seed, -dst to pull. No master, no scheduler, no manager process to keep alive.
A static -peer-list a,b,c works on day one. DNS SRV/A and HTTP registry are optional add-ons, never prerequisites.
Drops cleanly into an init container, sidecar, or DaemonSet. Point at a Headless Service FQDN and peers find each other via SRV/A — no operator, no CRD.
Chunked parallel transfer between every peer. Aggregate bandwidth grows with the fleet rather than collapsing on the source.
xxh3 digests per chunk, -verify-on-complete, optional zstd compression, tunable chunk size (8–128 MiB) and per-peer concurrency.
Quick start
One node holds the source and serves chunks.
seeder $ p2pcp -src /data/files
Each peer downloads from every other peer, in parallel. seeder, peer1, peer2 are resolvable hostnames (or host:port) — pass the real ones for your fleet.
peer $ p2pcp -dst /data/dst -peer-list seeder,peer1,peer2 -exit-complete
Point at a Kubernetes headless service — peers find each other.
peer $ p2pcp -dst /data/dst -peer-list-srv p2pcp.default.svc.cluster.local
Full CLI reference, tuning guide, and external-registry protocol in the README.
Kubernetes pattern
When a Deployment scales out, every new pod's init container pulls the dataset from the seeder and every running peer in parallel. The sidecar then keeps serving that data — so each successive replica reaches steady state faster than the last.
# deployment.yaml — excerpt
spec:
template:
spec:
initContainers:
- name: p2pcp-init
image: p2pcp:2
args:
- -dst=/data
- -peer-list=seeder.default.svc.cluster.local # source of truth
- -peer-list-srv=my-app.default.svc.cluster.local # sibling pods (Headless Service)
- -exit-complete
volumeMounts:
- { name: data, mountPath: /data }
containers:
- name: app
image: my-app
volumeMounts:
- { name: data, mountPath: /data, readOnly: true }
- name: p2pcp-sidecar
image: p2pcp:2
args: [-src=/data] # serve to next replicas
volumeMounts:
- { name: data, mountPath: /data, readOnly: true }
volumes:
- name: data
emptyDir: {}
A Headless Service selecting the pods is required so SRV records resolve to sibling replicas.
The seeder can be any reachable host running p2pcp -src — a standalone pod, a
StatefulSet, or a node outside the cluster.