feat: n2n P2P overlay + fleet wizard — runner registration fix, Serveo removal, repo obfuscation overhaul (#5 followup)#6
Merged
Conversation
- Replace Pinggy TCP relay with Serveo (SSH-based, no binary download) - Add ISP censorship warning for public n2n supernodes in README - Update connection modes table with Serveo + Ngrok alternatives - Update fleet scripts and wizard to reference Serveo instead of Pinggy
- Change default tunnel from serveo to trycloudflare - Move serveo to last option in dropdown, mark as experimental - Serveo free tier only supports HTTP forwarding (no raw TCP) - Use WebSocket transport for both trycloudflare and serveo HTTP tunnels - Serveo uses -R 80:localhost:PORT (HTTP subdomain) instead of TCP mode
Serveo free tier doesn't work for proxy tunneling (HTTP warning page kills the UX). YAGNI — fully remove: - proxy.yml: remove serveo from options, delete entire tunnel step, update step numbering and transport selection comment - README.md: remove from tagline, connection modes table, when-to-use-what, project structure, FAQ. Promote trycloudflare to default - animamesh-fleet.sh: remove from help text, tunnel options, obfuscation - meshify-wizard.sh: remove from tunnels array - .gitignore: add dist/ and worker/package-lock.json
Document the multi-account matrix (vi70x5–vi70x20) covering: - Account naming & scope (GH + Cloudflare + coordinator) - Local storage layout (~/.animamesh/) - Fleet management workflow (add, deploy, coordination) - Fork obfuscation strategy - Cloudflare account integration for permanent tunnels - Authentication matrix with rotation policy - Operational notes (coordinator sharing, suspension resilience, rate limits)
No fork network = no 'forked from animamesh/backend' badge linking
throwaway accounts to the real project. Each repo is built from
scratch with only the workflow file and an innocent README.
Changes:
- add_account: gh repo create instead of gh repo fork. Delete
existing repo by name before recreating (clean slate)
- New create_minimal_repo() replaces obfuscate_fork():
- Copies proxy.yml from backend, obfuscates it (renamed steps,
stripped revealing comments)
- Generates innocent CI-pipeline README (LLM or static fallback)
- Creates minimal .gitignore
- 2-commit push: 'Initial commit' + 'Add CI workflow config'
(looks like organic development)
- GENERATED_NAMES: utility library names → CI/automation names
(ci-config, build-workflows, task-runner, etc.)
- gen_readme prompt: now describes a CI pipeline config repo, not
a utility library
- AGENTS.md: updated Fleet Architecture to reflect new strategy,
renamed section from 'Fork Obfuscation' to 'Repo Obfuscation'
- Help text: 'fork' → 'repo' terminology throughout
Makes throwaway repos look like legitimate CI pipeline projects instead of empty shell repos. Each fork gets deterministic (stable across re-runs) TypeScript utility files: - package.json with jest/typescript devDependencies - tsconfig.json and jest.config.js - src/collect.ts — collection utilities (4 variants, seed from repo name) - src/format.ts — string formatting utilities (4 variants) - src/index.ts — barrel exports - src/__tests__/*.test.ts — basic jest test files No mention of proxy, VPN, tunnel, mesh, or any infrastructure. Just boring utility functions and a CI workflow that could be for any Node.js/TypeScript project.
- Set local git user.name/email before commits (no dependency on user's global git config — fixes crash on headless machines) - Use http.extraHeader for auth instead of embedding token in remote URL (safer if script crashes — avoids leaking token to .git/config) - Use --force push as fallback (repo was just created, no conflicts) - Strip revealing comments with case-sensitive sed (drop GNU-only I flag for broader compatibility)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Massive cleanup and hardening of the fleet deployment pipeline. Removes dead-end Serveo tunnel, fixes runner registration (the root cause of silent proxy failures), rewrites fork obfuscation to create fresh standalone repos instead of forking, and adds fake TypeScript source code generation so throwaway repos look like legitimate CI projects.
Changes
Core: Fix runner registration (was silently skipping)
COORDINATOR_URLinstead of unreliablesecrets.orenv.context inif:conditionalsAUTH_TOKEN(exits with clear error instead of silent skip)secrets.*orenv.*inif:expressions at step evaluation timeTunnel: Strip Serveo, default to trycloudflare
serveo→trycloudflaretrycloudflareuses WebSocket, all others use raw TCPFleet obfuscation: No more forks
animamesh-fleet.sh add: Replacedgh repo fork animamesh/backendwithgh repo create <name>— creates a fresh standalone repo with zero fork network. No "forked from animamesh/backend" badge visiblecreate_minimal_repo(): New function replacesobfuscate_fork(). Builds repo from scratch with only the obfuscated workflow + README + fake source codegen_fake_source(): New function generates deterministic TypeScript utility files (4 variants, seeded by repo name). Includespackage.json,tsconfig.json,jest.config.js,src/collect.ts,src/format.ts,src/__tests__/*.test.ts. Zero mentions of proxy/VPN/mesh/tunnelGENERATED_NAMESfrom library names (csv-parse,date-fmt) to CI-sounding names (ci-config,build-workflows,task-runner)Coordinator deployment via GHA
meshify-wizard.sh: Added option to deploy the Worker via GitHub Actions (creates a temp repo, pushes code, lets GHA runwrangler deploy). Workaround for localwrangler deployhang bugwrangler.toml: Smart Placement disabled (was causing deploy hang). KV namespace id documented as placeholderDocumentation
Questions for Gemini reviewer
Two-layer trust model — Is the explanation (n2n key = WiFi WPA2, Hy2 password = router admin) clear enough? Any gaps in the threat model for the n2n + Hysteria2 architecture?
Fake source code obfuscation — The
gen_fake_source()function generates deterministic TypeScript utility files based on a repo-name seed. Is this over-engineered? Could a simpler approach (just a real-looking README + empty package.json) achieve the same obfuscation effect, or does the fake code meaningfully reduce suspicion?Fresh repo vs fork — By creating standalone repos instead of forking, we lose the ability to pull upstream changes. Each repo must be independently maintained. Is this tradeoff worth the opsec gain (no "forked from animamesh" badge)? Should we add a periodic sync mechanism?
2-commit strategy robustness — The "Initial commit" + "Add source code and CI workflow" commit sequence could cause merge conflicts if the remote repo has changed between
gh repo createandgit push. We handle this with--forcevia delete-then-create, but should we use force-push as a fallback instead?Dashboard repurpose — The
TODO.mdplans to migrate the Express/Socket.IO dashboard onto the Cloudflare Worker. The 1MB Worker size limit is a constraint. Should we use Cloudflare Workers Assets (newer, hosts static files on edge CDN) or inline everything?gen_readme() LLM fallback — Relies on
http://localhost:3001/v1/chat/completionswith a hardcoded API key. The static fallback is the actual guarantee. Should we make the LLM URL/KEY configurable via env vars for end users who run local models?Workflow secret obfuscation — The proxy.yml step names are renamed to generic CI terms. However, the
run:blocks still contain commands likesudo apt-get install n2n,sing-box run,cloudflared tunnel. The step names are what appear in the GitHub UI — is this sufficient, or should we also obfuscate the echo/log messages inside the run blocks?Applied from Gemini review
Iflag from comment-stripping patterns — uses case-sensitive matching (casing is known/consistent)Applied from Gemini review
git config user.name "CI Bot"/git config user.email "bot@ci.local"before commits — no dependency on user's global git confighttp.extraHeader— token not visible in.git/configif script crashesgit push -u origin main --forceas retry — repo was just created, no legitimate conflicts possibleIflag from comment-stripping patterns — uses case-sensitive matching (casing is known/consistent)