Peer-to-peer binary cache for Nix. Share derivations between machines via Iroh P2P or local network broadcast.
Basically like torrent tracker, but for your /nix/store/
Add to flake.nix inputs:
inputs.peerix.url = "github:sophronesis/peerix";Add peerix.nixosModules.peerix to your modules, then in configuration.nix:
Uses Iroh for NAT-traversing P2P connectivity with automatic relay fallback:
services.peerix.enable = true;
# trackerUrl defaults to "https://sophronesis.dev/peerix"Zero-config peer discovery on local networks (no internet required).
Set trackerUrl = null to use LAN mode:
services.peerix = {
enable = true;
trackerUrl = null; # Use LAN mode instead of Iroh
};Mode is auto-selected based on trackerUrl:
trackerUrlset (default) → Iroh mode (P2P with NAT traversal via tracker)trackerUrl = null→ LAN mode (UDP broadcast, local network only)
# On server
services.peerix-tracker.enable = true;
# On clients
services.peerix.trackerUrl = "http://your-server:12305";Peerix implements a Nix binary cache. When Nix queries peerix for a package:
- Iroh mode: Queries peers via Iroh P2P protocol, fetches NAR directly from peer
- LAN mode: Broadcasts UDP request, peers respond if they have the package
Store path hashes are verified against cache.nixos.org by default.
- NAT traversal via Iroh relay servers (euw1-1.relay.iroh.network)
- Direct peer connections when possible
- Persistent node identity across restarts
- Connection pooling with retry logic
- Pre-buffered NAR streaming for reliability
- Web dashboard at
http://localhost:12304/dashboard - Health check at
http://localhost:12304/health - Prometheus metrics at
http://localhost:12304/metrics
| Option | Default | Description |
|---|---|---|
enable |
false |
Enable peerix |
trackerUrl |
"https://sophronesis.dev/peerix" |
Tracker URL (null=LAN mode, set=Iroh mode) |
openFirewall |
true |
Open firewall ports |
privateKeyFile |
null |
Path to signing key |
publicKey |
null |
Public key for signature verification |
priority |
5 |
Cache priority (lower = higher priority) |
timeout |
10.0 |
Connection timeout in seconds |
scanInterval |
3600 |
Seconds between store scans (0 to disable) |
| Option | Default | Description |
|---|---|---|
services.peerix-tracker.enable |
false |
Enable tracker server |
services.peerix-tracker.port |
12305 |
Tracker HTTP port |
Generate a key pair:
nix-store --generate-binary-cache-key myhost cache-priv-key.pem cache-pub-key.pemSet privateKeyFile on the serving node and publicKey (or publicKeyFile) on consuming nodes so nix can verify signatures.
Alternatively, set NIX_SECRET_KEY_FILE environment variable — peerix will sign narinfo responses with ed25519 directly (requires pynacl).
Peerix includes a web dashboard at http://localhost:12304/dashboard:
- Node Status: Iroh node ID, relay URL, direct addresses
- Peers: Connected peers with country flags and IPs
- Store: Available hashes, filter progress, scan status
- Most Requested: Top requested derivations
- Most Served: Top served derivations with per-peer tracking
- Activity Log: Recent checks, downloads, and serves with peer IDs
Stats persist across restarts to /var/lib/peerix/stats.json.
| Option | Description | Default |
|---|---|---|
services.peerix.enable |
Enables Peerix | false |
services.peerix.trackerUrl |
Tracker URL (null=LAN mode, set=Iroh mode) | "https://sophronesis.dev/peerix" |
services.peerix.openFirewall |
Open the necessary firewall ports | true |
services.peerix.user |
User to run the peerix service under | "nobody" |
services.peerix.group |
Group to run the peerix service under | "nobody" |
services.peerix.privateKeyFile |
Path to the private key file for signing | null |
services.peerix.publicKeyFile |
Path to the public key file for verification | null |
services.peerix.publicKey |
Public key string for verification | null |
services.peerix.upstreamCache |
Upstream cache URL for hash verification | "https://cache.nixos.org" |
services.peerix.priority |
Cache priority (lower = higher priority) | 5 |
services.peerix.timeout |
Connection timeout in seconds | 10.0 |
services.peerix.scanInterval |
Seconds between store scans (0 to disable) | 3600 |
services.peerix.filterMode |
Filter mode: "nixpkgs" or "rules" |
"nixpkgs" |
services.peerix.filterConcurrency |
Max concurrent filter requests | 10 |
services.peerix.noFilter |
Disable filtering (serve all packages) | false |
services.peerix.noVerify |
Disable hash verification against upstream | false |
services.peerix.allowInsecureHttp |
Allow HTTP (non-TLS) connections | false |
services.peerix.lanDiscovery |
Enable LAN discovery alongside Iroh | false |
| Option | Description | Default |
|---|---|---|
services.peerix-tracker.enable |
Enable the peerix tracker server | false |
services.peerix-tracker.port |
Port for the tracker HTTP server | 12305 |
services.peerix-tracker.dbPath |
Path to the tracker SQLite database | "/var/lib/peerix-tracker/tracker.db" |
services.peerix-tracker.openFirewall |
Open the firewall for the tracker port | true |
- Hash verification: Store path hashes verified against upstream cache before sharing
- NixpkgsFilteredStore: Only serves packages that exist in cache.nixos.org
- Narinfo signing: When
NIX_SECRET_KEY_FILEorprivateKeyFileis set, narinfo responses are signed with ed25519 - Localhost restriction: Main narinfo endpoint restricted to 127.0.0.1
- Iroh: Custom protocols
/peerix/narinfo/1.0.0and/peerix/nar/1.0.0over QUIC. NAT traversal via relay servers, direct connections when possible. - LAN: UDP port 12304 for broadcast-based peer discovery. Packet byte 0 is message type (0=request, 1=response), bytes 1-4 are request ID.
- HTTP: Port 12304 serves local narinfo/NAR to peers and proxied remote content to the local nix daemon.
- Tracker: HTTP API for peer registration and package hash lookup.
- Python 3.12+:
trio,starlette,httpx,pynacl,uvicorn - Iroh mode:
irohPython bindings - System:
nix,nix-serve
# Run with Iroh mode (default)
peerix-iroh --port 12304 --tracker https://sophronesis.dev/peerix --verbose
# Run with LAN discovery enabled (supplements Iroh)
peerix-iroh --lan-discovery --verbose
# Options
--config, -c Path to config file (default: ~/.config/peerix/config.toml)
--port HTTP port (default: 12304)
--tracker Tracker URL for peer discovery
--peer-id Human-readable peer ID (default: hostname)
--priority Cache priority (default: 5)
--timeout Connection timeout in seconds (default: 10)
--state-dir Directory for persistent state
--private-key Path to signing key
--scan-interval Seconds between store scans (default: 3600)
--no-filter Disable package filtering
--no-verify Disable hash verification
--filter-concurrency Max concurrent filter requests (default: 10)
--lan-discovery Enable LAN peer discovery via UDP broadcast
--verbose Enable verbose logging- v0.0.4: Health/metrics endpoints, peer reputation, unified LAN+Iroh, config file, test suite
- v0.0.3: Iroh P2P integration, dashboard, peer tracking, stats persistence
- v0.0.2: IPFS mode, filtering, verification
- v0.0.1: Initial release with LAN mode