Skip to main content
The P2P layer lets your ServiceNet node join a decentralized network where provider and agent records are gossiped and backfilled automatically. Nodes use Iroh (QUIC + relay) for transport — no port forwarding required, as relay fallback handles NAT traversal transparently.

Enabling P2P

Set SERVICENET_P2P_ENABLED=1 before starting your node. On startup, the node prints its Iroh EndpointId to stdout and begins listening for peer connections.
SERVICENET_P2P_ENABLED=1 \
SERVICENET_P2P_NETWORK_ID=mainnet \
SERVICENET_P2P_LISTEN_ADDRS=0.0.0.0:4101 \
cargo run -p watt-servicenet-node
You’ll see output like:
servicenet node listening on http://127.0.0.1:8042
servicenet p2p endpoint id: <base32-endpoint-id>
servicenet p2p listening on 0.0.0.0:4101
The node’s EndpointId is printed on startup and its underlying seed is persisted to SERVICENET_P2P_STATE_DIR/node_seed.hex so the same ID is derived on every restart. Copy the printed EndpointId to share with peers that want to bootstrap against your node.

Joining an Existing Network

To connect to an existing peer, pass its EndpointId and address as a bootstrap peer. Bootstrap peer addresses use the format <endpoint_id>@<addr> — these are Iroh EndpointId values, not libp2p multiaddrs.
SERVICENET_P2P_ENABLED=1 \
SERVICENET_P2P_NETWORK_ID=mainnet \
SERVICENET_P2P_LISTEN_ADDRS=0.0.0.0:4102 \
SERVICENET_P2P_BOOTSTRAP_PEERS=<peer-endpoint-id>@203.0.113.5:4101 \
cargo run -p watt-servicenet-node
Get the EndpointId of an existing node from its startup logs. The ID is printed each time the node starts and is also stored in SERVICENET_P2P_STATE_DIR/node_seed.hex.
To bootstrap against multiple peers, provide a comma-separated list:
SERVICENET_P2P_BOOTSTRAP_PEERS=<id-1>@203.0.113.5:4101,<id-2>@203.0.113.6:4101

What Happens on Connection

Once your node establishes a connection to a peer, the following sync steps run automatically:
1

Provider backfill request

Your node sends a sync request to the peer for all known provider records (up to 256 at a time).
2

Agent backfill request

Your node sends a sync request to the peer for all known published agent records (up to 256 at a time).
3

Real-time gossip

Newly registered providers and approved agents are gossiped to all connected peers immediately after they are created or approved locally.
4

Inbound merge

Inbound provider and agent records from peers are merged into your local registry store, subject to your node’s federation trust policy.

P2P Environment Variables

VariableDefaultDescription
SERVICENET_P2P_ENABLED(disabled)Set to 1, true, or yes to enable P2P
SERVICENET_P2P_NETWORK_ID(required if enabled)Network identifier string — nodes on different IDs cannot exchange records
SERVICENET_P2P_LISTEN_ADDRS(auto)Comma-separated listen addresses, e.g. 0.0.0.0:4101
SERVICENET_P2P_BOOTSTRAP_PEERS(none)Comma-separated bootstrap peer addresses in <endpoint_id>@<addr> format
SERVICENET_P2P_STATE_DIR.servicenet-p2p-stateDirectory used to persist the node seed and derive a stable EndpointId

Relay Fallback

If a direct QUIC connection is unavailable — for example, when both nodes are behind NAT — Iroh automatically falls back to its public relay network. No additional configuration is needed. Direct connectivity is always attempted first; the relay is used only when hole-punching fails.
Because relay fallback is built in, you can run P2P-enabled nodes on developer machines, cloud VMs, and container environments without managing firewall rules or port mappings.

Next Steps

Once your node is syncing with peers, configure how much you trust inbound registry data from those peers. See Federation Trust Modes to set up open or trusted federation.