P2P from GitHub Actions runners to your machine. Supports n2n mesh VPN (direct) and Cloudflare tunnels.
Ephemeral nodes running inside GitHub Actions, connected to your machine via Cloudflare tunnels. The coordinator is just a rendezvous — your traffic flows through Cloudflare's edge network.
No VPS required. 🧪 Pure science experiment.
GitHub Actions runners have unrestricted outbound internet but block all inbound traffic. You can't connect to a runner. But the runner can dial out to a supernode — and so can you.
n2n turns this asymmetry into a direct tunnel (if the public supernode is reachable):
⚠️ Note on n2n: Public n2n supernodes (supernode.ntop.org) are often DNS-blocked or unreachable depending on your ISP/country. If n2n fails, use one of the TCP tunnel fallbacks below. See Connection Modes for alternatives.
Your PC Supernode GHA Runner
─────── ───────── ─────────
edge -c net -k key -a 10.0.0.2 ──► supernode.ntop.org:7777 ◄── edge -c net -k key -a 10.0.0.1
│ (forwards peer coords) │
◄─────────── direct UDP hole-punched P2P link ──────────────►
│ │
Hysteria2 client Hysteria2 server
(SOCKS5 on 127.0.0.1:1080) (bound to 10.0.0.1:PORT)
The supernode is never in the data path — it just introduces peers so they can punch through NAT. Once both edges connect, they talk directly. Your traffic never touches any relay, CDN, or coordinator.
┌──────────────────────┐
│ Cloudflare Worker │
│ (coordinator) │
│ │
│ Public endpoints: │
│ GET /mesh/n2n-config → {community, supernode}
│ POST /mesh/n2n-join → {community, key, supernode}
│ GET /sub/all → subscription
│ GET /health → status
└──────┬───────────────┘
│ HTTPS (control plane only)
┌────────────┴────────────┐
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ GHA Runner │ │ Your Linux PC │
│ 10.10.10.1 │◄───────►│ 10.10.10.X │
│ Hysteria2 │ n2n │ Hysteria2 client │
│ (server) │ P2P │ (SOCKS5 ) │
└──────────────┘ └──────────────────┘
▲ ▲
└───── Direct ────────┘
(no middleman!)
| Layer | What it does | Credential | Who distributes it |
|---|---|---|---|
| n2n overlay | VPN mesh — L2 adjacency, direct P2P reachability | Community name + encryption key (-c / -k) |
Worker (/mesh/n2n-join, auth-gated) |
| **Hysteria2 ** | Application-level SOCKS5 tunnel, QUIC+TLS encrypted | Random per-run password | Worker (/sub/all, inside the subscription URL) |
Why two passwords? The n2n key gets you on the network — like WiFi WPA2. The Hysteria2 password lets you use the — like your router admin password. Even if someone else joins the same n2n community, they can't use your without the per-run Hysteria2 password. Two factors: network access + application auth.
See SPEC-V3 §6 Data Models for the full PublicRecord and SignedSnapshot schemas, and SPEC-V3 §10 Subscription Generation for how credentials flow into subscription links.
The Cloudflare Worker serves two roles, both control plane only:
- n2n coordinator — distributes community name, encryption key, and supernode address so you can join the mesh
- subscription server — lists active endpoints (host, port, protocol credentials) so your client knows where to connect
Neither role touches traffic. The Worker never sees a single byte of your browsing.
- A GitHub account (free tier works)
- A Linux machine (Debian/Ubuntu, Arch, or Fedora)
sudoon your machine (n2n creates a TUN interface)- 5 minutes
- Fork this repository
- Go to Settings → Secrets and variables → Actions
- Add these secrets:
| Secret | What it is | Example |
|---|---|---|
COORDINATOR_URL |
Your Worker URL (after deploying in Step 2) | https://animamesh.you.workers.dev |
AUTH_TOKEN |
Shared secret for Worker auth | my-secret-token-123 |
N2N_COMMUNITY |
n2n community name — pick something unique | animamesh-net-2026 |
N2N_KEY |
n2n encryption key — strong password | MyStr0ngP2PEncrypt10n! |
NETWORK_ID |
Mesh network identifier | my-mesh |
git clone https://github.com/YOURUSERNAME/animamesh.git
cd animamesh/backend
npm install
# Deploy the Cloudflare Worker
cd worker
npm install
npx wrangler login
npx wrangler deploy
# → Save the URL (e.g. https://animamesh.you.workers.dev)
# Set n2n secrets on the Worker
npx wrangler secret put N2N_COMMUNITY # enter your community name
npx wrangler secret put N2N_KEY # enter your encryption key# Trigger a GitHub Actions runner with n2n tunnel + Hysteria2
./scripts/-up.sh --protocol hysteria2
# Or manually: Actions → BPB Action → Run workflow
# Protocol: hysteria2
# Tunnel: n2nThe runner will:
- Start n2n edge → join the overlay VPN as
10.10.10.1 - Start Hysteria2 server bound to
10.10.10.1:PORT - Register itself with the Worker coordinator
- Heartbeat every 5 minutes until the 45-minute timeout
# One command — that's it
./scripts/animamesh-connect.sh \
--coordinator https://animamesh.you.workers.dev \
--auth-token my-secret-token-123This will:
- Install
n2nif missing - Fetch n2n credentials from the Worker (auth-gated)
- Join the n2n P2P overlay as
10.10.10.X - Discover active Hysteria2 proxies from the Worker subscription
- Start Hysteria2 SOCKS5 tunnel on
127.0.0.1:1080
curl --socks5 127.0.0.1:1080 https://ifconfig.me
# Or set environment variables
export http_=socks5://127.0.0.1:1080
export https_=socks5://127.0.0.1:1080Press Ctrl+C to gracefully disconnect — stops Hysteria2 and n2n edge.
Animamesh supports multiple tunnel types, from purely direct to CDN-backed:
| Tunnel | Data path | NAT traversal | Latency | Setup | Clients |
|---|---|---|---|---|---|---|
| trycloudflare 🌟 | Cloudflare CDN | CF tunnel | Medium | Just works | Any OS, stock Hiddify/v2ray |
| n2n | Direct P2P (UDP hole-punched) | Supernode-assisted | Low | Set 2 secrets | Linux only (requires root/TUN), animamesh-connect.sh |
| direct | Raw STUN punch | STUN server | Lowest | Fragile, often blocked | Any OS, stock Hiddify/v2ray |
trycloudflare is the default — works everywhere, no setup, stock Hiddify/v2ray compatible. n2n is available for direct P2P when the supernode is reachable.
- trycloudflare 🌟 — Default for all platforms. Works everywhere, no setup, compatible with stock Hiddify/v2ray.
- n2n — Direct P2P when supernode is reachable. Linux only, requires
animamesh-connect.sh. Lower latency but ISP-dependent. - direct — Raw STUN-based NAT punching. Lowest latency but fragile — many networks block it.
backend/
├── node/ # libp2p DHT mesh node (optional DHT discovery)
│ ├── src/
│ │ ├── dht.ts # Kademlia DHT node lifecycle
│ │ ├── announce.ts # DHT provider publish + record server
│ │ ├── discover.ts # DHT discovery + record fetch + verify
│ │ ├── signing.ts # Ed25519 signing/verification
│ │ ├── record.ts # PublicRecord creation + validation
│ │ ├── types.ts # Data model types
│ │ ├── index.ts # Entry point
│ │ └── indexer.ts # Standalone DHT indexer process
│ └── package.json
│
├── worker/ # Cloudflare Worker coordinator
│ ├── src/
│ │ └── index.ts # register, heartbeat, sub/all, mesh/*, n2n endpoints
│ ├── wrangler.toml
│ └── package.json
│
├── src/ # Dashboard panel (Express + Socket.IO)
│ ├── assets/panel/ # Web dashboard UI
│ ├── server.ts
│ └── index.ts
│
├── scripts/
│ ├── animamesh-connect.sh # 1-click n2n P2P client (Linux)
│ ├── -up.sh # Trigger a runner
│ ├── -down.sh # Remove active proxies
│ ├── -status.sh # Check health
│ └── stun_punch.py # STUN-based direct NAT traversal
│
├── .github/
│ └── workflows/
│ ├── .yml # GHA runner: trycloudflare/n2n/direct tunnel
│ └── panel.yml # Dashboard CI/CD
│
├── docs/
│ ├── SPEC-V3-ANIMAMESH-BACKEND.md # V3 backend spec (n2n, signing, mesh)
│ ├── SPEC-V2-MESH.md # Original DHT mesh spec + consillium decisions
│ └── ANIMAMESH-CLIENT.md # Linux client documentation
│ # → See 📚 Specification Index below for section-level references
│
└── README.md # You are here
The Worker exposes these endpoints. The n2n-specific ones are the heart of the P2P architecture. Full request/response schemas: SPEC-V3 §9 Worker Coordinator Protocol.
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/mesh/n2n-config |
GET | None | Public: community name + supernode (no key) |
/mesh/n2n-join |
POST | Bearer | Full n2n config: community + key + supernode |
/mesh/register |
POST | Bearer | Runner registers signed record |
/mesh/heartbeat |
POST | Bearer | Runner refreshes TTL |
/mesh/deregister |
POST | Bearer | Runner removes its record |
/mesh/status |
GET | None | Active mesh nodes (JSON) |
/mesh/snapshot |
GET | None | Signed snapshot of all records |
/sub/all |
GET | None | Hiddify-compatible subscription (all proxies) |
/sub/{id} |
GET | None | Single subscription |
/proxies |
GET | None | JSON list |
/register |
POST | Bearer | Legacy v1 registration |
/heartbeat |
POST | Bearer | Legacy v1 heartbeat |
/delete/{id} |
DELETE | Bearer | Remove record |
/health |
GET | None | Service health check |
| Threat | Mitigation |
|---|---|
| Coordinator compromise | Coordinator is control-plane only. No traffic flows through it. Signed records (Ed25519) prevent metadata tampering. See SPEC-V3 §5 Trust Model and SPEC-V2 §6 Threat Model. |
| n2n key leak | Anyone with the key can join the overlay — but they still need per-run Hysteria2 passwords to use proxies (from /sub/all). Two-factor: network access + app auth. |
| Supernode metadata exposure | The supernode sees your real public IP and the runner's IP (needed for UDP hole-punching). It cannot decrypt payload traffic (AES-encrypted by community key). If obscuring your home IP from the network broker is a requirement, n2n is not the right tool — consider Tor or multi-hop instead. |
| Supernode MITM | n2n encrypts peer-to-peer traffic with AES using the community key. The supernode only sees encrypted UDP packets and peer coordinates — never plaintext. |
| Lateral movement (L2 risk) | n2n creates a virtual LAN — any peer on the overlay has L2 adjacency to your machine via edge0. A compromised runner or malicious peer could probe your local services. Mitigation: treat edge0 as an untrusted public network. Block unsolicited inbound with sudo ufw deny in on edge0 or equivalent firewall rules. |
| Other n2n peers | Hysteria2 password is per-run, random. Even other peers on the same overlay can't use your . |
| Runner dies | Ephemeral by design. 45-minute TTL. No persistent state. Trigger a new one with -up.sh. |
| Sybil attack | Network-ID = shared secret. Coordinator auth-gates registration. DHT records signed with Ed25519. See SPEC-V2 §8 Q7 Defection. |
| Ghost nodes | Short TTL, heartbeat every 5 minutes, tombstones on deregister. |
Is this free? Yes. GitHub Actions free tier gives 2,000 minutes/month. Each runner uses ~45 min. The mesh draws 1-3 nodes at a time. You can run for many hours before hitting limits.
Do I need a VPS? No. That's the whole point. n2n uses public supernodes (free) to broker the initial connection. Once both peers are on the overlay, traffic flows directly between them.
What if the supernode is down?
Try an alternative. Set N2N_SUPERNODE secret or pass --supernode to animamesh-connect.sh:
| Supernode | Location |
|---|---|
supernode.ntop.org:7777 |
Official ntop (default) |
vps.luckynet.info:7777 |
Europe/CIS |
n2n.luckynet.info:7777 |
Fallback |
supernode.lucaswilliams.co.uk:7777 |
UK |
Is traffic encrypted? Twice. n2n encrypts the wire between peers (AES with community key). Hysteria2 adds QUIC+TLS on top with its own password. Even if someone sniffs the supernode, they see encrypted UDP. Even if another n2n peer inspects traffic, they see QUIC ciphertext.
Caveat: the supernode sees your real IP address (it needs this to broker the UDP hole-punch). If hiding your IP from the network broker is a hard requirement, n2n is not the right tool — Tor or multi-hop routing would be needed.
Why two passwords? n2n key = join the WiFi. Hysteria2 password = use the . Other peers on the same n2n community can ping you but can't through you without the per-run password.
Is this Tor? No. Tor is a production-grade multi-hop onion network with thousands of nodes and decades of security research. This is a weekend experiment that puts nodes in GitHub Actions and connects to them via n2n. Philosophy-wise? Same neighborhood. Security-wise? Not even close.
Can I use Hiddify instead of the Linux client?
If you're using trycloudflare tunnel mode, yes — GET /sub/all returns standard v2ray subscription links that work with Hiddify on any platform. For n2n mode, you need to join the n2n overlay first (the Linux client does this automatically). Stock Hiddify doesn't speak n2n — n2n requires running the edge daemon with root/TUN access, which only the animamesh-connect.sh script currently automates on Linux.
Why Hysteria2 vs VLESS? Hysteria2: QUIC-based, fast on lossy networks, no TLS cert needed, works great over n2n. VLESS: more widely supported, WebSocket transport works through CDNs. Both are first-class. Hysteria2 is the recommended default for n2n mode.
What about DHT?
The libp2p DHT (node/) is an optional discovery layer. The Worker coordinator is the primary discovery path today. DHT adds resilience for when the Worker is down — but for most users, the Worker is perfectly fine. See SPEC-V2 §3.1 DHT Discovery Layer and SPEC-V3 §8 DHT Protocol for the full architecture.
All design documents, kept for research and architectural reference.
| Document | What it covers | When to read it |
|---|---|---|
SPEC-V3-ANIMAMESH-BACKEND.md |
V3 implementation spec — data models (PublicRecord, SignedSnapshot), Ed25519 signing, Worker V3 mesh endpoints (/mesh/register, /mesh/heartbeat, /mesh/snapshot), DHT rendezvous protocol, subscription generation, runner lifecycle, IPFS mirroring, testing plan |
Before modifying worker/src/index.ts, node/src/, or .yml |
SPEC-V2-MESH.md |
Original mesh architecture — DHT topology (Kademlia), lifecycle state machine (SPAWN → DEREGISTER → DIE), 7-AI consillium decisions (bootstrap cascade, multi-hop killed, proactive overspawn, tunnel provider cascade, reputation/PoW stake), threat model, implementation roadmap | For DHT design rationale, consillium voting records (§8), and historical context |
ANIMAMESH-CLIENT.md |
Linux client docs — animamesh-connect.sh usage, n2n join flow, discovery, Hysteria2 SOCKS5 setup, troubleshooting, alternative supernodes |
Before using or modifying scripts/animamesh-connect.sh |
| Topic | SPEC-V3 | SPEC-V2 | Client doc |
|---|---|---|---|
| Data models & signing | §6 PublicRecord, §7 signing model |
— | — |
| Worker mesh API | §9 /mesh/register, /mesh/heartbeat, /mesh/status, /mesh/snapshot |
— | — |
| n2n P2P overlay | (implemented, see .yml + worker) | — | Architecture diagram, Step-by-step flow |
| DHT rendezvous keys | §8 /bpb/v2/{net-id}/{protocol}/{peer-id} |
§3.1 DHT Discovery Layer, §8 Q1 bootstrap cascade | — |
| Subscription generation | §10 Hysteria2 link, VLESS WS link, secret material | — | How proxies are discovered from /sub/all |
| Runner lifecycle | §11 workflow inputs, TTL, respawn | §3.3 Ephemeral Lifecycle Manager | — |
| 6-AI consillium decisions | — | §8 voting matrix + per-question analysis | — |
| Threat model | §5 trust boundaries, untrusted actors | §6 full threat table | — |
| IPFS/IPNS mirroring | §13 optional, SignedSnapshot to IPFS |
— | — |
| Implementation phases | §15 Phase 1–5, §16 file-by-file changes | §9 roadmap P0–P9 | — |
| Testing plan | §17 unit, integration, workflow smoke | — | — |
Research project. Fork it, break it, improve it. PRs welcome.
See the Specification Index above for all design documents.
MIT — Because sharing is caring. 💙