import type { Metadata } from 'next'; import CodeBlock from '@/components/ui/CodeBlock'; import P2NSFlowDiagram from '@/components/diagrams/P2NSFlowDiagram'; export const metadata: Metadata = { title: 'How It Works - P2NS Documentation', description: 'Complete explanation of how P2NS works from domain registration to accessing services. Understand the P2NS workflow and processes.', keywords: ['P2NS how it works', 'workflow', 'process', 'domain registration', 'P2NS explanation'], authors: [{ name: 'Raven Scott' }], openGraph: { title: 'How It Works - P2NS Documentation', description: 'Complete explanation of how P2NS works from domain registration to accessing services', url: 'https://p2ns.space/docs/how-it-works', siteName: 'P2NS', type: 'website', }, twitter: { card: 'summary_large_image', title: 'How It Works - P2NS Documentation', description: 'Complete explanation of how P2NS works from domain registration to accessing services', }, alternates: { canonical: 'https://p2ns.space/docs/how-it-works', }, }; export default function HowItWorksPage() { return (
Understanding the complete P2NS workflow from start to finish
P2NS (Peer-to-Peer Name System) is a decentralized DNS system that allows you to access services and websites without relying on traditional DNS servers or centralized infrastructure. Instead, it uses a peer-to-peer network where nodes work together to resolve domain names and establish direct connections.
Unlike traditional DNS where a central authority controls domain names, P2NS uses a distributed ledger where anyone can claim a domain and peers vote to reach consensus on which service should be associated with each domain. This makes it resistant to censorship and single points of failure.
The system uses UDP hole-punching (via HyperDHT) to connect through firewalls and NAT, making it possible to reach services behind restrictive networks. Two P2P layers work together: Hyperswarm on the P2NS topic syncs DNS claims and votes; Holesail uses separate hashes on the DHT for each published service tunnel. Let's walk through exactly how this works, step by step.
Here's a high-level view of what happens when you access a P2NS domain:
The key components are: peers (Hyperswarm + Corestore/Autopass for DNS state),
protomux-rpc (core invites and plugin traffic),
Holesail (per-service tunnels),
virtual interfaces (local IPs per domain), and
HTTPS/HTTP proxies (TLS and routing). Built-in sites such as{' '}
p2ns.admin and plugin domains under{' '}
plugin-sites/ are resolved without a P2P claim.
Before anyone can access a service through P2NS, the service provider needs to register their domain. Here's how it works:
The service provider first needs to create a Holesail connection hash. They run:
Use --public so the service is announced on HyperDHT for remote peers.
This generates a hash like hs://s00084bf87dfa89a3048fb081c0e6207eb5a.
That hash is independent of the P2NS swarm topic—peers use it only when connecting to your service tunnel.
Next, they register their domain (e.g., example.tld)
by creating a claim in the P2P network. This claim says "I own example.tld and it should point to this Holesail hash."
Claims live in the shared Autopass store (dnsPass) on top of Corestore—an append-only, signed log replicated across writers.
You can add domains via the admin UI (https://p2ns.admin),{' '}
cache/domains.json (genesis master by default), or the API. On a new network, exactly one node runs as{' '}
genesis master (--master --genesis) to create the shared Autopass ledger and{' '}
cache/network.json. Everyone else joins with node p2ns.js (joiner) or an optional secondary master (--master without --genesis) after receiving an invite.
The claim is stored with a key like claim:example.tld:claimant-id
where claimant-id is a unique identifier for the person making the claim.
Once the claim is created, it's automatically synchronized to all connected peers in the network. Each peer maintains a copy of the distributed ledger, so the claim propagates throughout the network. This happens in real-time as peers connect and exchange data.
If multiple people claim the same domain, the network uses a voting and consensus mechanism to decide which claim is legitimate (we'll cover this in detail later).
For P2NS to work, nodes need to find and connect to each other. This happens automatically using a technology called Hyperswarm.
All P2NS nodes use the same "topic" to find each other. Think of it like a meeting room number - everyone who wants
to participate in P2NS goes to the same room. The topic is a 32-byte buffer from sha256(TOPIC_SEED) (default p2ns-dns),
which ensures all P2NS nodes discover each other regardless of where they are in the world.
When a node starts up, it joins Hyperswarm on this topic. Under the hood, HyperDHT announces and looks up peers, coordinates UDP hole punching, and falls back to encrypted relays when needed. Each connection completes a Noise XX handshake before any application data flows.
The connection process involves:
dnsPass to authorized writers (separate from the P2NS topic used only for discovery)
Only peers with Autopass writer access can append claims and votes. All nodes on a network share one Autopass ledger identified by networkId in cache/network.json:
--master --genesis creates the ledger (once per network)--master on empty storage waits for an invite (no implicit second ledger)node p2ns.js; no master flag required for everyday useAdmission uses protomux-rpc on the P2NS swarm connection:
invite.request — peer asks a master or writer for an inviteinvite.deliver / invite.ack — invite wire is delivered and acknowledgedcore.status — exposes networkId, invite capability, and split-network warnings
Masters may proactively send invites when new peers connect (MASTER_PROACTIVE_INVITE_DELAY).
Quorum counts writers with initialized dnsPass, not raw swarm connections.
See Architecture and Configuration.
Once a peer is a writer, new claims and votes append to dnsPass and replicate
to other writers through Autopass. Corestore manages the underlying Hypercore logs. When a new claim or vote is added, authorized peers receive it automatically.
This means:
Now let's see what happens when someone wants to access a P2NS domain. This is where the magic happens!
When you type a domain like https://example.tld
in your browser, or when an application makes a DNS query, it goes to the P2NS DNS server (port 53 by default, configurable).
This server is configured as your system's DNS resolver, so queries flow through P2NS first.
Before P2P lookup, the resolver checks:
p2ns.admin and any domain with a plugin under plugin-sites/{domain}/config.json (e.g. peer.directory, peer.paste)cache/local_dns.json override both P2P and public DNSFirst, P2NS checks its local cache to see if it recently resolved this domain. If the cache entry is still valid (typically cached for 30 seconds), it returns the cached result immediately. This makes repeated queries very fast.
If not in cache, P2NS looks up the domain in the distributed ledger. It searches through all the claims stored locally (remember, each node has a complete copy) to find any claims for the requested domain.
The system looks for entries with keys like claim:example.tld:*
to find all people who have claimed this domain.
If multiple people have claimed the same domain, P2NS uses a consensus algorithm to determine which one is correct:
CONSENSUS_QUORUM_THRESHOLD (default 50% of active peers) and CONSENSUS_MIN_VOTES (default 2).This ensures that everyone in the network agrees on which service should be associated with each domain name.
If the domain is not internal, not in local DNS, and not resolved via P2P consensus, P2NS forwards to PUBLIC_DNS_SERVER (comma-separated list supported for failover).
You can use P2P domains and the public internet through one resolver.
Once P2NS has the Holesail hash for a domain, it needs to set up local networking to route traffic to that domain. This is where virtual network interfaces come in.
P2NS assigns each domain a unique local IP address from a configured subnet (default: 192.168.3.x).
For example, the first domain might get 192.168.3.2,
the second gets 192.168.3.3, and so on.
You can configure multiple subnets with different IP ranges, and P2NS will automatically allocate IPs from available subnets. This gives you flexibility to organize domains across different network ranges.
P2NS creates a virtual network interface (like lo0 on macOS or lo on Linux)
and adds the IP address as an alias. This makes the IP address available on your local machine, even though it's not
connected to a physical network.
The virtual interface acts like a local network adapter, allowing your system to route traffic to that IP address. When your browser or application connects to the domain, it resolves to this local IP, and the traffic gets intercepted by P2NS for processing.
Virtual interfaces are necessary because:
Now that we have a local IP address, P2NS needs to establish a connection to the actual service. This is where Holesail comes in - it's the technology that punches through firewalls and NAT to create direct connections.
Holesail uses UDP hole-punching to establish connections through firewalls and NAT (Network Address Translation). Traditional networking often fails when both the client and server are behind firewalls, but Holesail solves this by:
FULL_PERSISTENCE keeps clients/servers alive across restarts (see Configuration)
Holesail server and client configs persist under cache/holesail_servers.json and{' '}
cache/holesail_clients.json.
The Holesail hash we got from the domain claim is a random cryptographic string that acts as a key to look up the service on the DHT. When P2NS needs to connect, it:
P2NS creates a Holesail client that uses this hash to look up and connect to the service provider's Holesail server. The connection process happens automatically in the background.
Once established, the Holesail connection can be kept alive persistently. This means:
Now we have a Holesail tunnel established, but we still need to handle HTTPS properly and route requests correctly. This is where the proxy servers come in.
P2NS automatically generates TLS certificates for each domain using its own Certificate Authority (CA). When you first access a P2NS domain, the system:
You need to trust the P2NS root CA in your browser/system to avoid security warnings. P2NS auto-installs on macOS and Windows;
on Linux, Chrome requires both the system CA bundle and the NSS trust database (certutil / ~/.pki/nssdb) — see{' '}
Troubleshooting.
P2NS runs an HTTPS proxy server on port 443. When your browser makes an HTTPS request to a P2NS domain:
P2NS also runs an HTTP server on port 80 that automatically redirects all HTTP requests to HTTPS. This ensures all connections are encrypted and secure.
The proxy also supports WebSocket connections, allowing real-time applications to work through P2NS. WebSocket upgrades are handled transparently, maintaining the connection through the Holesail tunnel.
Let's put it all together! Here's exactly what happens when you access a P2NS domain:
https://example.tld in your browserexample.tldexample.tldhs://s00084bf87dfa89a...)192.168.3.2) for this domainAll of this happens automatically in milliseconds! The first request might take a bit longer as connections are established, but subsequent requests are much faster as connections are reused.
One of the most important aspects of P2NS is how it handles conflicts when multiple people claim the same domain. The consensus mechanism ensures the network agrees on which service should be associated with each domain.
When a peer sees a domain claim, they can vote for it by creating a vote entry in the ledger. The vote key looks like:
vote:example.tld:claimant-id:voter-id
Peers typically vote for the claim they believe is legitimate. This could be based on:
For a domain to be considered "resolved" (consensus reached), it must meet quorum requirements:
CONSENSUS_QUORUM_THRESHOLD (default 0.5 = 50% of active peers)CONSENSUS_MIN_VOTES (default 2), regardless of peer countThis ensures that consensus isn't reached by just one or two nodes, but represents actual network agreement.
When multiple claimants have the same number of votes, P2NS uses tie-breaking strategies:
CONSENSUS_TIE_BREAKER=timestamp, default)This deterministic approach ensures all nodes reach the same conclusion when resolving ties, maintaining network consistency.
P2NS uses several advanced technologies. Here's what each one does in simple terms:
What it does: Discovers other P2NS nodes on topic sha256(TOPIC_SEED), coordinates hole punching, and opens encrypted swarm connections.
Simple analogy: A distributed meeting room—everyone who joins the same topic can find each other without a central directory server.
What it does: Multiplexes JSON-RPC methods on each peer connection—core invites, consensus helpers, and per-plugin protocols.
Simple analogy: Several phone lines over one secure call—core control traffic and plugin apps share the same tunnel without mixing messages.
What it does: Corestore holds Hypercore append-only logs; Autopass (dnsPass) stores claims and votes with invite-gated writers.
Simple analogy: A signed ledger everyone authorized can append to—entries are immutable and verifiable by Merkle proofs, not by trusting who sent them.
What it does: Publishes and connects to service tunnels by hash on HyperDHT—separate from the P2NS DNS swarm topic.
Simple analogy: A dedicated address for your web server or game port; DNS consensus points a domain name at that address.
Let's walk through a concrete example to see how everything fits together:
hs://s00084bf87dfa89a3048fb081c0e6207eb5aalice.blog with this hashalice.bloghttps://alice.blog in his browseralice.blog in the ledger192.168.3.2 to alice.blogTimeline: All of this happens in under a second for the first request. Subsequent requests are even faster because the Holesail connection is reused.
The magic: Even though Alice and Bob are both behind firewalls and NAT, they can communicate directly thanks to Holesail's UDP hole-punching. No central server needed, no port forwarding required!
Service subscriptions allow peers to automatically connect to services hosted by domain owners. This is especially useful when a domain owner hosts multiple services (like a web server, API, and game server) and wants others to easily access them.
alice.servicesclients array containing all three servicesExample claim record structure:
alice.services and sees all three available servicesalice.servicesalice.services_web (TCP client)alice.services_api (TCP client)alice.services_game (UDP client)cache/subscriptions.jsonalice.services, P2NS automatically:
alice.services_chatalice.services_game Holesail clientcache/subscriptions.jsonKey Benefits:
The Power: Service subscriptions make it easy for peers to discover and connect to services across the network. Domain owners can offer multiple services, and subscribers can automatically access them all with minimal configuration. The system handles all the complexity of connection management, protocol differences, and dynamic updates.
--clean